A bit set class. Will be used for font subsetting.
authorvandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Sat, 2 Jul 2011 01:26:37 +0000 (01:26 +0000)
committervandebo@chromium.org <vandebo@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Sat, 2 Jul 2011 01:26:37 +0000 (01:26 +0000)
Committed on behalf of arthurhsu@chromium.org with a few final nits.

Original CL: http://codereview.appspot.com/4627077

Review URL: http://codereview.appspot.com/4657070

git-svn-id: http://skia.googlecode.com/svn/trunk@1788 2bbb7eff-a529-9590-31e7-b0007b416f81

gyp/pdf.gyp
gyp/tests.gyp
include/pdf/SkBitSet.h [new file with mode: 0755]
src/pdf/SkBitSet.cpp [new file with mode: 0755]
tests/BitSetTest.cpp [new file with mode: 0644]

index 3957e481d650710090991dfddcefe6a3cdf5c13e..f0c39372ab91e333292983a73429cf5f25f29ac7 100644 (file)
@@ -13,6 +13,7 @@
         '../src/core', # needed to get SkGlyphCache.h and SkTextFormatParams.h
       ],
       'sources': [
+        '../include/pdf/SkBitSet.h',
         '../include/pdf/SkPDFCatalog.h',
         '../include/pdf/SkPDFDevice.h',
         '../include/pdf/SkPDFDocument.h',
@@ -26,6 +27,7 @@
         '../include/pdf/SkPDFTypes.h',
         '../include/pdf/SkPDFUtils.h',
 
+       '../src/pdf/SkBitSet.cpp',
         '../src/pdf/SkPDFCatalog.cpp',
         '../src/pdf/SkPDFDevice.cpp',
         '../src/pdf/SkPDFDocument.cpp',
index d4cafd254847aced5ee598b8f8ea201d3a921374..95dc9c585bd61712ff893a0eb6b3a3d1e132e732 100644 (file)
@@ -14,6 +14,7 @@
       'sources': [
         '../tests/BitmapCopyTest.cpp',
         '../tests/BitmapGetColorTest.cpp',
+       '../tests/BitSetTest.cpp',
         '../tests/BlitRowTest.cpp',
         '../tests/ClampRangeTest.cpp',
         '../tests/ClipCubicTest.cpp',
diff --git a/include/pdf/SkBitSet.h b/include/pdf/SkBitSet.h
new file mode 100755 (executable)
index 0000000..84d52e5
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+#ifndef SkBitSet_DEFINED
+#define SkBitSet_DEFINED
+
+#include "SkTypes.h"
+
+class SkBitSet {
+public:
+    /** NumberOfBits must be greater than zero.
+     */
+    explicit SkBitSet(int numberOfBits);
+    explicit SkBitSet(const SkBitSet& source);
+
+    const SkBitSet& operator=(const SkBitSet& rhs);
+    bool operator==(const SkBitSet& rhs);
+    bool operator!=(const SkBitSet& rhs);
+
+    /** Clear all data.
+     */
+    void clearAll();
+
+    /** Set the value of the index-th bit.
+     */
+    void setBit(int index, bool value);
+
+    /** Test if bit index is set.
+     */
+    bool isBitSet(int index);
+
+    /** Or bits from source.  false is returned if this doesn't have the same
+     *  bit count as source.
+     */
+    bool orBits(SkBitSet& source);
+
+private:
+    SkAutoFree fBitData;
+    // Dword (32-bit) count of the bitset.
+    size_t fDwordCount;
+    size_t fBitCount;
+
+    uint32_t* internalGet(int index) {
+        SkASSERT((size_t)index < fBitCount);
+        size_t internalIndex = index / 32;
+        SkASSERT(internalIndex < fDwordCount);
+        return (uint32_t*)fBitData.get() + internalIndex;
+    }
+};
+
+
+#endif
diff --git a/src/pdf/SkBitSet.cpp b/src/pdf/SkBitSet.cpp
new file mode 100755 (executable)
index 0000000..f19dd69
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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 <string.h>
+#include "SkBitSet.h"
+
+SkBitSet::SkBitSet(int numberOfBits)
+    : fBitData(NULL), fDwordCount(0), fBitCount(numberOfBits) {
+    SkASSERT(numberOfBits > 0);
+    // Round up size to 32-bit boundary.
+    fDwordCount = (numberOfBits + 31) / 32;
+    fBitData.set(malloc(fDwordCount * sizeof(uint32_t)));
+    clearAll();
+}
+
+SkBitSet::SkBitSet(const SkBitSet& source)
+    : fBitData(NULL), fDwordCount(0), fBitCount(0) {
+    *this = source;
+}
+
+const SkBitSet& SkBitSet::operator=(const SkBitSet& rhs) {
+    if (this == (SkBitSet*)&rhs) {
+        return *this;
+    }
+    fBitCount = rhs.fBitCount;
+    fBitData.free();
+    fDwordCount = rhs.fDwordCount;
+    fBitData.set(malloc(fDwordCount * sizeof(uint32_t)));
+    memcpy(fBitData.get(), rhs.fBitData.get(), fDwordCount * sizeof(uint32_t));
+    return *this;
+}
+
+bool SkBitSet::operator==(const SkBitSet& rhs) {
+    if (fBitCount == rhs.fBitCount) {
+        if (fBitData.get() != NULL) {
+            return (memcmp(fBitData.get(), rhs.fBitData.get(),
+                           fDwordCount * sizeof(uint32_t)) == 0);
+        }
+        return true;
+    }
+    return false;
+}
+
+bool SkBitSet::operator!=(const SkBitSet& rhs) {
+    return !(*this == rhs);
+}
+
+void SkBitSet::clearAll() {
+    if (fBitData.get() != NULL) {
+        sk_bzero(fBitData.get(), fDwordCount * sizeof(uint32_t));
+    }
+}
+
+void SkBitSet::setBit(int index, bool value) {
+    uint32_t mask = 1 << (index % 32);
+    if (value) {
+        *(internalGet(index)) |= mask;
+    } else {
+        *(internalGet(index)) &= ~mask;
+    }
+}
+
+bool SkBitSet::isBitSet(int index) {
+    uint32_t mask = 1 << (index % 32);
+    return (*internalGet(index) & mask);
+}
+
+bool SkBitSet::orBits(SkBitSet& source) {
+    if (fBitCount != source.fBitCount) {
+        return false;
+    }
+    uint32_t* targetBitmap = internalGet(0);
+    uint32_t* sourceBitmap = source.internalGet(0);
+    for (size_t i = 0; i < fDwordCount; ++i) {
+        targetBitmap[i] |= sourceBitmap[i];
+    }
+    return true;
+}
diff --git a/tests/BitSetTest.cpp b/tests/BitSetTest.cpp
new file mode 100644 (file)
index 0000000..96bf80f
--- /dev/null
@@ -0,0 +1,66 @@
+#include "Test.h"
+#include "SkBitSet.h"
+
+static void TestBitSet(skiatest::Reporter* reporter) {
+    SkBitSet set0(65536);
+    REPORTER_ASSERT(reporter, set0.isBitSet(0) == false);
+    REPORTER_ASSERT(reporter, set0.isBitSet(32767) == false);
+    REPORTER_ASSERT(reporter, set0.isBitSet(65535) == false);
+
+    SkBitSet set1(65536);
+    REPORTER_ASSERT(reporter, set0 == set1);
+
+    set0.setBit(22, true);
+    REPORTER_ASSERT(reporter, set0.isBitSet(22) == true);
+    set0.setBit(24, true);
+    REPORTER_ASSERT(reporter, set0.isBitSet(24) == true);
+    set0.setBit(35, true);  // on a different DWORD
+    REPORTER_ASSERT(reporter, set0.isBitSet(35) == true);
+    set0.setBit(22, false);
+    REPORTER_ASSERT(reporter, set0.isBitSet(22) == false);
+    REPORTER_ASSERT(reporter, set0.isBitSet(24) == true);
+    REPORTER_ASSERT(reporter, set0.isBitSet(35) == true);
+
+    set1.setBit(12345, true);
+    set1.orBits(set0);
+    REPORTER_ASSERT(reporter, set0.isBitSet(12345) == false);
+    REPORTER_ASSERT(reporter, set1.isBitSet(12345) == true);
+    REPORTER_ASSERT(reporter, set1.isBitSet(22) == false);
+    REPORTER_ASSERT(reporter, set1.isBitSet(24) == true);
+    REPORTER_ASSERT(reporter, set0.isBitSet(35) == true);
+    REPORTER_ASSERT(reporter, set1 != set0);
+
+    set1.clearAll();
+    REPORTER_ASSERT(reporter, set0.isBitSet(12345) == false);
+    REPORTER_ASSERT(reporter, set1.isBitSet(12345) == false);
+    REPORTER_ASSERT(reporter, set1.isBitSet(22) == false);
+    REPORTER_ASSERT(reporter, set1.isBitSet(24) == false);
+    REPORTER_ASSERT(reporter, set1.isBitSet(35) == false);
+
+    set1.orBits(set0);
+    REPORTER_ASSERT(reporter, set1 == set0);
+
+    SkBitSet set2(1);
+    SkBitSet set3(1);
+    SkBitSet set4(4);
+    SkBitSet set5(33);
+
+    REPORTER_ASSERT(reporter, set2 == set3);
+    REPORTER_ASSERT(reporter, set2 != set4);
+    REPORTER_ASSERT(reporter, set2 != set5);
+
+    set2.setBit(0, true);
+    REPORTER_ASSERT(reporter, set2 != set5);
+    set5.setBit(0, true);
+    REPORTER_ASSERT(reporter, set2 != set5);
+    REPORTER_ASSERT(reporter, set2 != set3);
+    set3.setBit(0, true);
+    REPORTER_ASSERT(reporter, set2 == set3);
+    set3.clearAll();
+    set3 = set2;
+    set2 = set2;
+    REPORTER_ASSERT(reporter, set2 == set3);
+}
+
+#include "TestClassDef.h"
+DEFINE_TESTCLASS("BitSet", BitSetTest, TestBitSet)