static SkIRect rand_rect(SkMWCRandom& rand, int n) { int x = rand.nextS() % n; int y = rand.nextS() % n; int w = rand.nextU() % n; int h = rand.nextU() % n; return SkIRect::MakeXYWH(x, y, w, h); }
static void TestSort(skiatest::Reporter* reporter) { /** An array of random numbers to be sorted. */ int randomArray[500]; /** The reference sort of the random numbers. */ int sortedArray[SK_ARRAY_COUNT(randomArray)]; /** The random numbers are copied into this array, sorted by an SkSort, then this array is compared against the reference sort. */ int workingArray[SK_ARRAY_COUNT(randomArray)]; SkMWCRandom rand; for (int i = 0; i < 10000; i++) { int count = rand.nextRangeU(1, SK_ARRAY_COUNT(randomArray)); rand_array(rand, randomArray, count); // Use qsort as the reference sort. memcpy(sortedArray, randomArray, sizeof(randomArray)); qsort(sortedArray, count, sizeof(sortedArray[0]), compare_int); memcpy(workingArray, randomArray, sizeof(randomArray)); SkTHeapSort<int>(workingArray, count); check_sort(reporter, "Heap", workingArray, sortedArray, count); memcpy(workingArray, randomArray, sizeof(randomArray)); SkTQSort<int>(workingArray, workingArray + count - 1); check_sort(reporter, "Quick", workingArray, sortedArray, count); } }
static void rand_irect(SkIRect* r, int N, SkMWCRandom& rand) { r->setXYWH(0, 0, rand.nextU() % N, rand.nextU() % N); int dx = rand.nextU() % (2*N); int dy = rand.nextU() % (2*N); // use int dx,dy to make the subtract be signed r->offset(N - dx, N - dy); }
static void rand_rect(SkRect* rect, SkMWCRandom& rand, SkScalar W, SkScalar H) { rect->fLeft = rand.nextRangeScalar(-W, 2*W); rect->fTop = rand.nextRangeScalar(-H, 2*H); rect->fRight = rect->fLeft + rand.nextRangeScalar(0, W); rect->fBottom = rect->fTop + rand.nextRangeScalar(0, H); // we integralize rect to make our tests more predictable, since Gather is // a little sloppy. SkIRect ir; rect->round(&ir); rect->set(ir); }
virtual void onDraw(SkCanvas* canvas) { SkPaint paint; this->setupPaint(&paint); paint.setAntiAlias(true); SkMWCRandom rand; for (int i = 0; i < SkBENCHLOOP(3); i++) { SkRect r = SkRect::MakeWH(rand.nextUScalar1() * 400, rand.nextUScalar1() * 400); paint.setImageFilter(fFilter); canvas->drawOval(r, paint); } }
static inline void test_fast_interp(skiatest::Reporter* reporter) { SkMWCRandom r; U8CPU a0 = 0; U8CPU a255 = 255; for (int i = 0; i < 200; i++) { SkColor colorSrc = r.nextU(); SkColor colorDst = r.nextU(); SkPMColor src = SkPreMultiplyColor(colorSrc); SkPMColor dst = SkPreMultiplyColor(colorDst); REPORTER_ASSERT(reporter, SkFastFourByteInterp(src, dst, a0) == dst); REPORTER_ASSERT(reporter, SkFastFourByteInterp(src, dst, a255) == src); } }
static void rand_op(SkCanvas* canvas, SkMWCRandom& rand) { SkPaint paint; SkRect rect = SkRect::MakeWH(50, 50); SkScalar unit = rand.nextUScalar1(); if (unit <= 0.3) { // SkDebugf("save\n"); canvas->save(); } else if (unit <= 0.6) { // SkDebugf("restore\n"); canvas->restore(); } else if (unit <= 0.9) { // SkDebugf("clip\n"); canvas->clipRect(rect); } else { // SkDebugf("draw\n"); canvas->drawPaint(paint); } }
static void test_matrix_decomposition(skiatest::Reporter* reporter) { SkMatrix mat; SkScalar rotation0, scaleX, scaleY, rotation1; const float kRotation0 = 15.5f; const float kRotation1 = -50.f; const float kScale0 = 5000.f; const float kScale1 = 0.001f; // identity mat.reset(); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, SK_Scalar1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, SK_Scalar1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // make sure it doesn't crash if we pass in NULLs REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, NULL, NULL, NULL, NULL)); // rotation only mat.setRotate(kRotation0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation0))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, SK_Scalar1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, SK_Scalar1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // uniform scale only mat.setScale(kScale0, kScale0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // anisotropic scale only mat.setScale(kScale1, kScale0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // rotation then uniform scale mat.setRotate(kRotation1); mat.postScale(kScale0, kScale0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // uniform scale then rotation mat.setScale(kScale0, kScale0); mat.postRotate(kRotation1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // rotation then uniform scale+reflection mat.setRotate(kRotation0); mat.postScale(kScale1, -kScale1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation0))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, -kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // uniform scale+reflection, then rotate mat.setScale(kScale0, -kScale0); mat.postRotate(kRotation1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(-kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, -kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // rotation then anisotropic scale mat.setRotate(kRotation1); mat.postScale(kScale1, kScale0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // anisotropic scale then rotation mat.setScale(kScale1, kScale0); mat.postRotate(kRotation0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation1, SkDegreesToRadians(kRotation0))); // rotation, uniform scale, then different rotation mat.setRotate(kRotation1); mat.postScale(kScale0, kScale0); mat.postRotate(kRotation0); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(rotation0, SkDegreesToRadians(kRotation0 + kRotation1))); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleX, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyEqual(scaleY, kScale0)); REPORTER_ASSERT(reporter, SkScalarNearlyZero(rotation1)); // rotation, anisotropic scale, then different rotation mat.setRotate(kRotation0); mat.postScale(kScale1, kScale0); mat.postRotate(kRotation1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); // Because of the shear/skew we won't get the same results, so we need to multiply it out. // Generating the matrices requires doing a radian-to-degree calculation, then degree-to-radian // calculation (in setRotate()), which adds error, so this just computes the matrix elements // directly. SkScalar c0; SkScalar s0 = SkScalarSinCos(rotation0, &c0); SkScalar c1; SkScalar s1 = SkScalarSinCos(rotation1, &c1); // We do a relative check here because large scale factors cause problems with an absolute check REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); // try some random matrices SkMWCRandom rand; for (int m = 0; m < 1000; ++m) { SkScalar rot0 = rand.nextRangeF(-SK_ScalarPI, SK_ScalarPI); SkScalar sx = rand.nextRangeF(-3000.f, 3000.f); SkScalar sy = rand.nextRangeF(-3000.f, 3000.f); SkScalar rot1 = rand.nextRangeF(-SK_ScalarPI, SK_ScalarPI); mat.setRotate(rot0); mat.postScale(sx, sy); mat.postRotate(rot1); if (SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)) { SkScalar c0; SkScalar s0 = SkScalarSinCos(rotation0, &c0); SkScalar c1; SkScalar s1 = SkScalarSinCos(rotation1, &c1); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); } else { // if the matrix is degenerate, the basis vectors should be near-parallel or near-zero SkScalar perpdot = mat[SkMatrix::kMScaleX]*mat[SkMatrix::kMScaleY] - mat[SkMatrix::kMSkewX]*mat[SkMatrix::kMSkewY]; REPORTER_ASSERT(reporter, SkScalarNearlyZero(perpdot)); } } // translation shouldn't affect this mat.postTranslate(-1000.f, 1000.f); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); s0 = SkScalarSinCos(rotation0, &c0); s1 = SkScalarSinCos(rotation1, &c1); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); // perspective shouldn't affect this mat[SkMatrix::kMPersp0] = 12.f; mat[SkMatrix::kMPersp1] = 4.f; mat[SkMatrix::kMPersp2] = 1872.f; REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); s0 = SkScalarSinCos(rotation0, &c0); s1 = SkScalarSinCos(rotation1, &c1); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); // rotation, anisotropic scale + reflection, then different rotation mat.setRotate(kRotation0); mat.postScale(-kScale1, kScale0); mat.postRotate(kRotation1); REPORTER_ASSERT(reporter, SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); s0 = SkScalarSinCos(rotation0, &c0); s1 = SkScalarSinCos(rotation1, &c1); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleX], scaleX*c0*c1 - scaleY*s0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewX], -scaleX*s0*c1 - scaleY*c0*s1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMSkewY], scaleX*c0*s1 + scaleY*s0*c1)); REPORTER_ASSERT(reporter, scalar_nearly_equal_relative(mat[SkMatrix::kMScaleY], -scaleX*s0*s1 + scaleY*c0*c1)); // degenerate matrices // mostly zero entries mat.reset(); mat[SkMatrix::kMScaleX] = 0.f; REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); mat.reset(); mat[SkMatrix::kMScaleY] = 0.f; REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); mat.reset(); // linearly dependent entries mat[SkMatrix::kMScaleX] = 1.f; mat[SkMatrix::kMSkewX] = 2.f; mat[SkMatrix::kMSkewY] = 4.f; mat[SkMatrix::kMScaleY] = 8.f; REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1)); }
static void test_matrix_max_stretch(skiatest::Reporter* reporter) { SkMatrix identity; identity.reset(); REPORTER_ASSERT(reporter, SK_Scalar1 == identity.getMaxStretch()); SkMatrix scale; scale.setScale(SK_Scalar1 * 2, SK_Scalar1 * 4); REPORTER_ASSERT(reporter, SK_Scalar1 * 4 == scale.getMaxStretch()); SkMatrix rot90Scale; rot90Scale.setRotate(90 * SK_Scalar1); rot90Scale.postScale(SK_Scalar1 / 4, SK_Scalar1 / 2); REPORTER_ASSERT(reporter, SK_Scalar1 / 2 == rot90Scale.getMaxStretch()); SkMatrix rotate; rotate.setRotate(128 * SK_Scalar1); REPORTER_ASSERT(reporter, SkScalarAbs(SK_Scalar1 - rotate.getMaxStretch()) <= SK_ScalarNearlyZero); SkMatrix translate; translate.setTranslate(10 * SK_Scalar1, -5 * SK_Scalar1); REPORTER_ASSERT(reporter, SK_Scalar1 == translate.getMaxStretch()); SkMatrix perspX; perspX.reset(); perspX.setPerspX(SkScalarToPersp(SK_Scalar1 / 1000)); REPORTER_ASSERT(reporter, -SK_Scalar1 == perspX.getMaxStretch()); SkMatrix perspY; perspY.reset(); perspY.setPerspX(SkScalarToPersp(-SK_Scalar1 / 500)); REPORTER_ASSERT(reporter, -SK_Scalar1 == perspY.getMaxStretch()); SkMatrix baseMats[] = {scale, rot90Scale, rotate, translate, perspX, perspY}; SkMatrix mats[2*SK_ARRAY_COUNT(baseMats)]; for (size_t i = 0; i < SK_ARRAY_COUNT(baseMats); ++i) { mats[i] = baseMats[i]; bool invertable = mats[i].invert(&mats[i + SK_ARRAY_COUNT(baseMats)]); REPORTER_ASSERT(reporter, invertable); } SkMWCRandom rand; for (int m = 0; m < 1000; ++m) { SkMatrix mat; mat.reset(); for (int i = 0; i < 4; ++i) { int x = rand.nextU() % SK_ARRAY_COUNT(mats); mat.postConcat(mats[x]); } SkScalar stretch = mat.getMaxStretch(); if ((stretch < 0) != mat.hasPerspective()) { stretch = mat.getMaxStretch(); } REPORTER_ASSERT(reporter, (stretch < 0) == mat.hasPerspective()); if (mat.hasPerspective()) { m -= 1; // try another non-persp matrix continue; } // test a bunch of vectors. None should be scaled by more than stretch // (modulo some error) and we should find a vector that is scaled by // almost stretch. static const SkScalar gStretchTol = (105 * SK_Scalar1) / 100; static const SkScalar gMaxStretchTol = (97 * SK_Scalar1) / 100; SkScalar max = 0; SkVector vectors[1000]; for (size_t i = 0; i < SK_ARRAY_COUNT(vectors); ++i) { vectors[i].fX = rand.nextSScalar1(); vectors[i].fY = rand.nextSScalar1(); if (!vectors[i].normalize()) { i -= 1; continue; } } mat.mapVectors(vectors, SK_ARRAY_COUNT(vectors)); for (size_t i = 0; i < SK_ARRAY_COUNT(vectors); ++i) { SkScalar d = vectors[i].length(); REPORTER_ASSERT(reporter, SkScalarDiv(d, stretch) < gStretchTol); if (max < d) { max = d; } } REPORTER_ASSERT(reporter, SkScalarDiv(max, stretch) >= gMaxStretchTol); } }
static void TestTLList(skiatest::Reporter* reporter) { typedef SkTLList<ListElement> ElList; typedef ElList::Iter Iter; SkMWCRandom random; for (int i = 1; i <= 16; i *= 2) { ElList list1(i); ElList list2(i); Iter iter1; Iter iter2; Iter iter3; Iter iter4; #if SK_ENABLE_INST_COUNT SkASSERT(0 == ListElement::InstanceCount()); #endif REPORTER_ASSERT(reporter, list1.isEmpty()); REPORTER_ASSERT(reporter, NULL == iter1.init(list1, Iter::kHead_IterStart)); REPORTER_ASSERT(reporter, NULL == iter1.init(list1, Iter::kTail_IterStart)); // Try popping an empty list list1.popHead(); list1.popTail(); REPORTER_ASSERT(reporter, list1.isEmpty()); REPORTER_ASSERT(reporter, list1 == list2); // Create two identical lists, one by appending to head and the other to the tail. list1.addToHead(ListElement(1)); list2.addToTail(ListElement(1)); #if SK_ENABLE_INST_COUNT SkASSERT(2 == ListElement::InstanceCount()); #endif iter1.init(list1, Iter::kHead_IterStart); iter2.init(list1, Iter::kTail_IterStart); REPORTER_ASSERT(reporter, iter1.get()->fID == iter2.get()->fID); iter3.init(list2, Iter::kHead_IterStart); iter4.init(list2, Iter::kTail_IterStart); REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID); REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID); REPORTER_ASSERT(reporter, list1 == list2); list2.reset(); // use both before/after in-place construction on an empty list SkNEW_INSERT_IN_LLIST_BEFORE(&list2, list2.headIter(), ListElement, (1)); REPORTER_ASSERT(reporter, list2 == list1); list2.reset(); SkNEW_INSERT_IN_LLIST_AFTER(&list2, list2.tailIter(), ListElement, (1)); REPORTER_ASSERT(reporter, list2 == list1); // add an element to the second list, check that iters are still valid iter3.init(list2, Iter::kHead_IterStart); iter4.init(list2, Iter::kTail_IterStart); list2.addToHead(ListElement(2)); #if SK_ENABLE_INST_COUNT SkASSERT(3 == ListElement::InstanceCount()); #endif REPORTER_ASSERT(reporter, iter3.get()->fID == iter1.get()->fID); REPORTER_ASSERT(reporter, iter4.get()->fID == iter1.get()->fID); REPORTER_ASSERT(reporter, 1 == Iter(list2, Iter::kTail_IterStart).get()->fID); REPORTER_ASSERT(reporter, 2 == Iter(list2, Iter::kHead_IterStart).get()->fID); REPORTER_ASSERT(reporter, list1 != list2); list1.addToHead(ListElement(2)); REPORTER_ASSERT(reporter, list1 == list2); #if SK_ENABLE_INST_COUNT SkASSERT(4 == ListElement::InstanceCount()); #endif REPORTER_ASSERT(reporter, !list1.isEmpty()); list1.reset(); list2.reset(); #if SK_ENABLE_INST_COUNT SkASSERT(0 == ListElement::InstanceCount()); #endif REPORTER_ASSERT(reporter, list1.isEmpty() && list2.isEmpty()); // randomly perform insertions and deletions on a list and perform tests int count = 0; for (int j = 0; j < 100; ++j) { if (list1.isEmpty() || random.nextBiasedBool(3 * SK_Scalar1 / 4)) { int id = j; // Choose one of three ways to insert a new element: at the head, at the tail, // before a random element, after a random element int numValidMethods = 0 == count ? 2 : 4; int insertionMethod = random.nextULessThan(numValidMethods); switch (insertionMethod) { case 0: list1.addToHead(ListElement(id)); break; case 1: list1.addToTail(ListElement(id)); break; case 2: // fallthru to share code that picks random element. case 3: { int n = random.nextULessThan(list1.count()); Iter iter = list1.headIter(); // remember the elements before/after the insertion point. while (n--) { iter.next(); } Iter prev(iter); Iter next(iter); next.next(); prev.prev(); SkASSERT(NULL != iter.get()); // insert either before or after the iterator, then check that the // surrounding sequence is correct. if (2 == insertionMethod) { SkNEW_INSERT_IN_LLIST_BEFORE(&list1, iter, ListElement, (id)); Iter newItem(iter); newItem.prev(); REPORTER_ASSERT(reporter, newItem.get()->fID == id); if (NULL != next.get()) { REPORTER_ASSERT(reporter, next.prev()->fID == iter.get()->fID); } if (NULL != prev.get()) { REPORTER_ASSERT(reporter, prev.next()->fID == id); } } else { SkNEW_INSERT_IN_LLIST_AFTER(&list1, iter, ListElement, (id)); Iter newItem(iter); newItem.next(); REPORTER_ASSERT(reporter, newItem.get()->fID == id); if (NULL != next.get()) { REPORTER_ASSERT(reporter, next.prev()->fID == id); } if (NULL != prev.get()) { REPORTER_ASSERT(reporter, prev.next()->fID == iter.get()->fID); } } } } ++count; } else { // walk to a random place either forward or backwards and remove. int n = random.nextULessThan(list1.count()); Iter::IterStart start; ListElement* (Iter::*incrFunc)(); if (random.nextBool()) { start = Iter::kHead_IterStart; incrFunc = &Iter::next; } else { start = Iter::kTail_IterStart; incrFunc = &Iter::prev; } // find the element Iter iter(list1, start); while (n--) { REPORTER_ASSERT(reporter, NULL != iter.get()); (iter.*incrFunc)(); } REPORTER_ASSERT(reporter, NULL != iter.get()); // remember the prev and next elements from the element to be removed Iter prev = iter; Iter next = iter; prev.prev(); next.next(); list1.remove(iter.get()); // make sure the remembered next/prev iters still work Iter pn = prev; pn.next(); Iter np = next; np.prev(); // pn should match next unless the target node was the head, in which case prev // walked off the list. REPORTER_ASSERT(reporter, pn.get() == next.get() || NULL == prev.get()); // Similarly, np should match prev unless next originally walked off the tail. REPORTER_ASSERT(reporter, np.get() == prev.get() || NULL == next.get()); --count; } REPORTER_ASSERT(reporter, count == list1.count()); #if SK_ENABLE_INST_COUNT SkASSERT(count == ListElement::InstanceCount()); #endif } list1.reset(); #if SK_ENABLE_INST_COUNT SkASSERT(0 == ListElement::InstanceCount()); #endif } }
static void make_rand_rgn(SkRegion* rgn, SkMWCRandom& rand) { int count = rand.nextU() % 20; for (int i = 0; i < count; ++i) { rgn->op(rand_rect(rand, 100), SkRegion::kXOR_Op); } }
bool GrGpuGL::programUnitTest(int maxStages) { GrTextureDesc dummyDesc; dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit; dummyDesc.fConfig = kSkia8888_GrPixelConfig; dummyDesc.fWidth = 34; dummyDesc.fHeight = 18; SkAutoTUnref<GrTexture> dummyTexture1(this->createTexture(dummyDesc, NULL, 0)); dummyDesc.fFlags = kNone_GrTextureFlags; dummyDesc.fConfig = kAlpha_8_GrPixelConfig; dummyDesc.fWidth = 16; dummyDesc.fHeight = 22; SkAutoTUnref<GrTexture> dummyTexture2(this->createTexture(dummyDesc, NULL, 0)); static const int NUM_TESTS = 512; SkMWCRandom random; for (int t = 0; t < NUM_TESTS; ++t) { #if 0 GrPrintf("\nTest Program %d\n-------------\n", t); static const int stop = -1; if (t == stop) { int breakpointhere = 9; } #endif GrGLProgramDesc pdesc; int currAttribIndex = 1; // we need to always leave room for position int attribIndices[2]; GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()}; int numStages = random.nextULessThan(maxStages + 1); int numColorStages = random.nextULessThan(numStages + 1); int numCoverageStages = numStages - numColorStages; SkAutoSTMalloc<8, const GrEffectStage*> stages(numStages); for (int s = 0; s < numStages; ++s) { SkAutoTUnref<const GrEffectRef> effect(GrEffectTestFactory::CreateStage( &random, this->getContext(), *this->caps(), dummyTextures)); int numAttribs = (*effect)->numVertexAttribs(); // If adding this effect would exceed the max attrib count then generate a // new random effect. if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) { --s; continue; } for (int i = 0; i < numAttribs; ++i) { attribIndices[i] = currAttribIndex++; } GrEffectStage* stage = SkNEW_ARGS(GrEffectStage, (effect.get(), attribIndices[0], attribIndices[1])); stages[s] = stage; } const GrTexture* dstTexture = random.nextBool() ? dummyTextures[0] : dummyTextures[1]; pdesc.setRandom(&random, this, dummyTextures[0]->asRenderTarget(), dstTexture, stages.get(), numColorStages, numCoverageStages, currAttribIndex); SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this, pdesc, stages, stages + numColorStages)); for (int s = 0; s < numStages; ++s) { SkDELETE(stages[s]); } if (NULL == program.get()) { return false; } } return true; }
static void rand_array(SkMWCRandom& rand, int array[], int n) { for (int j = 0; j < n; j++) { array[j] = rand.nextS() & 0xFF; } }