/*
Copyright 2010 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 "GrDrawTarget.h"
#include "GrTDArray.h"
#include "GrTBSearch.h"
#include "GrMatrix.h"
#include "GrRedBlackTree.h"
#include "GrPath.h"
#include "GrBinHashKey.h"
static void dump(const GrTDArray<int>& array) {
#if 0
for (int i = 0; i < array.count(); i++) {
printf(" %d", array[i]);
}
printf("\n");
#endif
}
static void test_tdarray() {
GrTDArray<int> array;
*array.append() = 0; dump(array);
*array.append() = 2; dump(array);
*array.append() = 4; dump(array);
*array.append() = 6; dump(array);
GrAssert(array.count() == 4);
*array.insert(0) = -1; dump(array);
*array.insert(2) = 1; dump(array);
*array.insert(4) = 3; dump(array);
*array.insert(7) = 7; dump(array);
GrAssert(array.count() == 8);
array.remove(3); dump(array);
array.remove(0); dump(array);
array.removeShuffle(4); dump(array);
array.removeShuffle(1); dump(array);
GrAssert(array.count() == 4);
}
static bool LT(const int& elem, int value) {
return elem < value;
}
static bool EQ(const int& elem, int value) {
return elem == value;
}
static void test_bsearch() {
const int array[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99
};
for (size_t n = 0; n < GR_ARRAY_COUNT(array); n++) {
for (size_t i = 0; i < n; i++) {
int index = GrTBSearch<int, int>(array, n, array[i]);
GrAssert(index == (int) i);
index = GrTBSearch<int, int>(array, n, -array[i]);
GrAssert(index < 0);
}
}
}
// bogus empty class for GrBinHashKey
class BogusEntry {};
static void test_binHashKey()
{
const char* testStringA = "abcdABCD";
const char* testStringB = "abcdBBCD";
enum {
kDataLenUsedForKey = 8
};
typedef GrBinHashKey<BogusEntry, kDataLenUsedForKey> KeyType;
KeyType keyA;
int passCnt = 0;
while (keyA.doPass()) {
++passCnt;
keyA.keyData(reinterpret_cast<const uint32_t*>(testStringA), kDataLenUsedForKey);
}
GrAssert(passCnt == 1); //We expect the static allocation to suffice
GrBinHashKey<BogusEntry, kDataLenUsedForKey-1> keyBust;
passCnt = 0;
while (keyBust.doPass()) {
++passCnt;
// Exceed static storage by 1
keyBust.keyData(reinterpret_cast<const uint32_t*>(testStringA), kDataLenUsedForKey);
}
GrAssert(passCnt == 2); //We expect dynamic allocation to be necessary
GrAssert(keyA.getHash() == keyBust.getHash());
// Test that adding keyData in chunks gives
// the same hash as with one chunk
KeyType keyA2;
while (keyA2.doPass()) {
keyA2.keyData(reinterpret_cast<const uint32_t*>(testStringA), 4);
keyA2.keyData(&reinterpret_cast<const uint32_t*>(testStringA)[4], kDataLenUsedForKey-4);
}
GrAssert(keyA.getHash() == keyA2.getHash());
KeyType keyB;
while (keyB.doPass()){
keyB.keyData(reinterpret_cast<const uint32_t*>(testStringB), kDataLenUsedForKey);
}
GrAssert(keyA.compare(keyB) < 0);
GrAssert(keyA.compare(keyA2) == 0);
//Test ownership tranfer and copying
keyB.copyAndTakeOwnership(keyA);
GrAssert(keyA.fIsValid == false);
GrAssert(keyB.fIsValid);
GrAssert(keyB.getHash() == keyA2.getHash());
GrAssert(keyB.compare(keyA2) == 0);
keyA.deepCopyFrom(keyB);
GrAssert(keyA.fIsValid);
GrAssert(keyB.fIsValid);
GrAssert(keyA.getHash() == keyA2.getHash());
GrAssert(keyA.compare(keyA2) == 0);
//Test ownership tranfer and copying with key on heap
GrBinHashKey<BogusEntry, kDataLenUsedForKey-1> keyBust2;
keyBust2.deepCopyFrom(keyBust);
GrAssert(keyBust.fIsValid);
GrAssert(keyBust2.fIsValid);
GrAssert(keyBust.getHash() == keyBust2.getHash());
GrAssert(keyBust.compare(keyBust2) == 0);
GrBinHashKey<BogusEntry, kDataLenUsedForKey-1> keyBust3;
keyBust3.deepCopyFrom(keyBust);
GrAssert(keyBust.fIsValid == false);
GrAssert(keyBust3.fIsValid);
GrAssert(keyBust3.getHash() == keyBust2.getHash());
GrAssert(keyBust3.compare(keyBust2) == 0);
}
static void test_convex() {
#if 0
GrPath testPath;
GrPath::Iter testIter;
GrPath pt;
pt.moveTo(0, 0);
pt.close();
testIter.reset(pt);
testPath.resetFromIter(&testIter);
GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
GrPath line;
line.moveTo(GrIntToScalar(12), GrIntToScalar(20));
line.lineTo(GrIntToScalar(-12), GrIntToScalar(-20));
line.close();
testIter.reset(line);
testPath.resetFromIter(&testIter);
GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
GrPath triLeft;
triLeft.moveTo(0, 0);
triLeft.lineTo(1, 0);
triLeft.lineTo(1, 1);
triLeft.close();
testIter.reset(triLeft);
testPath.resetFromIter(&testIter);
GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
GrPath triRight;
triRight.moveTo(0, 0);
triRight.lineTo(-1, 0);
triRight.lineTo(1, 1);
triRight.close();
testIter.reset(triRight);
testPath.resetFromIter(&testIter);
GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
GrPath square;
square.moveTo(0, 0);
square.lineTo(1, 0);
square.lineTo(1, 1);
square.lineTo(0, 1);
square.close();
testIter.reset(square);
testPath.resetFromIter(&testIter);
GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
GrPath redundantSquare;
square.moveTo(0, 0);
square.lineTo(0, 0);
square.lineTo(0, 0);
square.lineTo(1, 0);
square.lineTo(1, 0);
square.lineTo(1, 0);
square.lineTo(1, 1);
square.lineTo(1, 1);
square.lineTo(1, 1);
square.lineTo(0, 1);
square.lineTo(0, 1);
square.lineTo(0, 1);
square.close();
testIter.reset(redundantSquare);
testPath.resetFromIter(&testIter);
GrAssert(kConvex_ConvexHint == testPath.getConvexHint());
GrPath 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();
testIter.reset(bowTie);
testPath.resetFromIter(&testIter);
GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
GrPath 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();
testIter.reset(spiral);
testPath.resetFromIter(&testIter);
GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
GrPath dent;
dent.moveTo(0, 0);
dent.lineTo(1, 1);
dent.lineTo(0, 1);
dent.lineTo(-.5,2);
dent.lineTo(-2, 1);
dent.close();
testIter.reset(dent);
testPath.resetFromIter(&testIter);
GrAssert(kConcave_ConvexHint == testPath.getConvexHint());
#endif
}
void gr_run_unittests() {
test_tdarray();
test_bsearch();
test_binHashKey();
test_convex();
GrRedBlackTree<int>::UnitTest();
GrDrawTarget::VertexLayoutUnitTest();
}