• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SkDescriptor_DEFINED
18 #define SkDescriptor_DEFINED
19 
20 #include "SkTypes.h"
21 
22 class SkDescriptor : SkNoncopyable {
23 public:
ComputeOverhead(int entryCount)24     static size_t ComputeOverhead(int entryCount)
25     {
26         SkASSERT(entryCount >= 0);
27         return sizeof(SkDescriptor) + entryCount * sizeof(Entry);
28     }
29 
Alloc(size_t length)30     static SkDescriptor* Alloc(size_t length)
31     {
32         SkASSERT(SkAlign4(length) == length);
33         SkDescriptor* desc = (SkDescriptor*)sk_malloc_throw(length);
34         return desc;
35     }
36 
Free(SkDescriptor * desc)37     static void Free(SkDescriptor* desc)
38     {
39         sk_free(desc);
40     }
41 
init()42     void init()
43     {
44         fLength = sizeof(SkDescriptor);
45         fCount  = 0;
46     }
47 
getLength()48     uint32_t getLength() const { return fLength; }
49 
50     void* addEntry(uint32_t tag, uint32_t length, const void* data = NULL)
51     {
52         SkASSERT(tag);
53         SkASSERT(SkAlign4(length) == length);
54         SkASSERT(this->findEntry(tag, NULL) == NULL);
55 
56         Entry*  entry = (Entry*)((char*)this + fLength);
57         entry->fTag = tag;
58         entry->fLen = length;
59         if (data)
60             memcpy(entry + 1, data, length);
61 
62         fCount += 1;
63         fLength += sizeof(Entry) + length;
64         return (entry + 1); // return its data
65     }
66 
computeChecksum()67     void computeChecksum()
68     {
69         fChecksum = SkDescriptor::ComputeChecksum(this);
70     }
71 
72 #ifdef SK_DEBUG
assertChecksum()73     void assertChecksum() const
74     {
75         SkASSERT(fChecksum == SkDescriptor::ComputeChecksum(this));
76     }
77 #endif
78 
findEntry(uint32_t tag,uint32_t * length)79     const void* findEntry(uint32_t tag, uint32_t* length) const
80     {
81         const Entry* entry = (const Entry*)(this + 1);
82         int          count = fCount;
83 
84         while (--count >= 0)
85         {
86             if (entry->fTag == tag)
87             {
88                 if (length)
89                     *length = entry->fLen;
90                 return entry + 1;
91             }
92             entry = (const Entry*)((const char*)(entry + 1) + entry->fLen);
93         }
94         return NULL;
95     }
96 
copy()97     SkDescriptor* copy() const
98     {
99         SkDescriptor* desc = SkDescriptor::Alloc(fLength);
100         memcpy(desc, this, fLength);
101         return desc;
102     }
103 
equals(const SkDescriptor & other)104     bool equals(const SkDescriptor& other) const
105     {
106         // probe to see if we have a good checksum algo
107 //        SkASSERT(a.fChecksum != b.fChecksum || memcmp(&a, &b, a.fLength) == 0);
108 
109         // the first value we should look at is the checksum, so this loop
110         // should terminate early if they descriptors are different.
111         // NOTE: if we wrote a sentinel value at the end of each, we chould
112         //       remove the aa < stop test in the loop...
113         const uint32_t* aa = (const uint32_t*)this;
114         const uint32_t* bb = (const uint32_t*)&other;
115         const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength);
116         do {
117             if (*aa++ != *bb++)
118                 return false;
119         } while (aa < stop);
120         return true;
121     }
122 
123     struct Entry {
124         uint32_t fTag;
125         uint32_t fLen;
126     };
127 
128 #ifdef SK_DEBUG
getChecksum()129     uint32_t getChecksum() const { return fChecksum; }
getCount()130     uint32_t getCount() const { return fCount; }
131 #endif
132 
133 private:
134     uint32_t fChecksum;  // must be first
135     uint32_t fLength;    // must be second
136     uint32_t fCount;
137 
ComputeChecksum(const SkDescriptor * desc)138     static uint32_t ComputeChecksum(const SkDescriptor* desc)
139     {
140         const uint32_t*  ptr = (const uint32_t*)desc + 1; // skip the checksum field
141         const uint32_t*  stop = (const uint32_t*)((const char*)desc + desc->fLength);
142         uint32_t         sum = 0;
143 
144         SkASSERT(ptr < stop);
145         do {
146             sum = (sum << 1) | (sum >> 31);
147             sum ^= *ptr++;
148         } while (ptr < stop);
149 
150         return sum;
151     }
152 
153     // private so no one can create one except our factories
SkDescriptor()154     SkDescriptor() {}
155 };
156 
157 #include "SkScalerContext.h"
158 
159 class SkAutoDescriptor : SkNoncopyable {
160 public:
SkAutoDescriptor(size_t size)161     SkAutoDescriptor(size_t size)
162     {
163         if (size <= sizeof(fStorage))
164             fDesc = (SkDescriptor*)(void*)fStorage;
165         else
166             fDesc = SkDescriptor::Alloc(size);
167     }
~SkAutoDescriptor()168     ~SkAutoDescriptor()
169     {
170         if (fDesc != (SkDescriptor*)(void*)fStorage)
171             SkDescriptor::Free(fDesc);
172     }
getDesc()173     SkDescriptor* getDesc() const { return fDesc; }
174 private:
175     enum {
176         kStorageSize =  sizeof(SkDescriptor)
177                         + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContext::Rec)    // for rec
178                         + sizeof(SkDescriptor::Entry) + sizeof(void*)                   // for typeface
179                         + 32   // slop for occational small extras
180     };
181     SkDescriptor*   fDesc;
182     uint32_t        fStorage[(kStorageSize + 3) >> 2];
183 };
184 
185 
186 #endif
187 
188