• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "src/core/SkDescriptor.h"
9 
10 #include <new>
11 
12 #include "include/core/SkTypes.h"
13 #include "include/private/SkTo.h"
14 #include "src/core/SkOpts.h"
15 
Alloc(size_t length)16 std::unique_ptr<SkDescriptor> SkDescriptor::Alloc(size_t length) {
17     SkASSERT(SkAlign4(length) == length);
18     void* allocation = ::operator new (length);
19     return std::unique_ptr<SkDescriptor>(new (allocation) SkDescriptor{});
20 }
21 
operator delete(void * p)22 void SkDescriptor::operator delete(void* p) { ::operator delete(p); }
operator new(size_t)23 void* SkDescriptor::operator new(size_t) {
24     SK_ABORT("Descriptors are created with placement new.");
25 }
26 
addEntry(uint32_t tag,size_t length,const void * data)27 void* SkDescriptor::addEntry(uint32_t tag, size_t length, const void* data) {
28     SkASSERT(tag);
29     SkASSERT(SkAlign4(length) == length);
30     SkASSERT(this->findEntry(tag, nullptr) == nullptr);
31 
32     Entry* entry = (Entry*)((char*)this + fLength);
33     entry->fTag = tag;
34     entry->fLen = SkToU32(length);
35     if (data) {
36         memcpy(entry + 1, data, length);
37     }
38 
39     fCount += 1;
40     fLength = SkToU32(fLength + sizeof(Entry) + length);
41     return (entry + 1); // return its data
42 }
43 
computeChecksum()44 void SkDescriptor::computeChecksum() {
45     fChecksum = SkDescriptor::ComputeChecksum(this);
46 }
47 
findEntry(uint32_t tag,uint32_t * length) const48 const void* SkDescriptor::findEntry(uint32_t tag, uint32_t* length) const {
49     const Entry* entry = (const Entry*)(this + 1);
50     int          count = fCount;
51 
52     while (--count >= 0) {
53         if (entry->fTag == tag) {
54             if (length) {
55                 *length = entry->fLen;
56             }
57             return entry + 1;
58         }
59         entry = (const Entry*)((const char*)(entry + 1) + entry->fLen);
60     }
61     return nullptr;
62 }
63 
copy() const64 std::unique_ptr<SkDescriptor> SkDescriptor::copy() const {
65     std::unique_ptr<SkDescriptor> desc = SkDescriptor::Alloc(fLength);
66     memcpy(desc.get(), this, fLength);
67     return desc;
68 }
69 
operator ==(const SkDescriptor & other) const70 bool SkDescriptor::operator==(const SkDescriptor& other) const {
71 
72     // the first value we should look at is the checksum, so this loop
73     // should terminate early if they descriptors are different.
74     // NOTE: if we wrote a sentinel value at the end of each, we could
75     //       remove the aa < stop test in the loop...
76     const uint32_t* aa = (const uint32_t*)this;
77     const uint32_t* bb = (const uint32_t*)&other;
78     const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength);
79     do {
80         if (*aa++ != *bb++)
81             return false;
82     } while (aa < stop);
83     return true;
84 }
85 
dumpRec() const86 SkString SkDescriptor::dumpRec() const {
87     const SkScalerContextRec* rec = static_cast<const SkScalerContextRec*>(
88             this->findEntry(kRec_SkDescriptorTag, nullptr));
89 
90     SkString result;
91     result.appendf("    Checksum: %x\n", fChecksum);
92     if (rec != nullptr) {
93         result.append(rec->dump());
94     }
95     return result;
96 }
97 
ComputeChecksum(const SkDescriptor * desc)98 uint32_t SkDescriptor::ComputeChecksum(const SkDescriptor* desc) {
99     const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field
100     size_t len = desc->fLength - sizeof(uint32_t);
101     return SkOpts::hash(ptr, len);
102 }
103 
isValid() const104 bool SkDescriptor::isValid() const {
105     uint32_t count = fCount;
106     size_t lengthRemaining = this->fLength;
107     if (lengthRemaining < sizeof(SkDescriptor)) {
108         return false;
109     }
110     lengthRemaining -= sizeof(SkDescriptor);
111     size_t offset = sizeof(SkDescriptor);
112 
113     while (lengthRemaining > 0 && count > 0) {
114         if (lengthRemaining < sizeof(Entry)) {
115             return false;
116         }
117         lengthRemaining -= sizeof(Entry);
118 
119         const Entry* entry = (const Entry*)(reinterpret_cast<const char*>(this) + offset);
120 
121         if (lengthRemaining < entry->fLen) {
122             return false;
123         }
124         lengthRemaining -= entry->fLen;
125 
126         // rec tags are always a known size.
127         if (entry->fTag == kRec_SkDescriptorTag && entry->fLen != sizeof(SkScalerContextRec)) {
128             return false;
129         }
130 
131         offset += sizeof(Entry) + entry->fLen;
132         count--;
133     }
134     return lengthRemaining == 0 && count == 0;
135 }
136 
137 SkAutoDescriptor::SkAutoDescriptor() = default;
SkAutoDescriptor(size_t size)138 SkAutoDescriptor::SkAutoDescriptor(size_t size) { this->reset(size); }
SkAutoDescriptor(const SkDescriptor & desc)139 SkAutoDescriptor::SkAutoDescriptor(const SkDescriptor& desc) { this->reset(desc); }
SkAutoDescriptor(const SkAutoDescriptor & that)140 SkAutoDescriptor::SkAutoDescriptor(const SkAutoDescriptor& that) {
141     this->reset(*that.getDesc());
142 }
operator =(const SkAutoDescriptor & that)143 SkAutoDescriptor& SkAutoDescriptor::operator=(const SkAutoDescriptor& that) {
144     this->reset(*that.getDesc());
145     return *this;
146 }
SkAutoDescriptor(SkAutoDescriptor && that)147 SkAutoDescriptor::SkAutoDescriptor(SkAutoDescriptor&& that) {
148     if (that.fDesc == (SkDescriptor*)&that.fStorage) {
149         this->reset(*that.getDesc());
150     } else {
151         fDesc = that.fDesc;
152         that.fDesc = nullptr;
153     }
154 }
operator =(SkAutoDescriptor && that)155 SkAutoDescriptor& SkAutoDescriptor::operator=(SkAutoDescriptor&& that) {
156     if (that.fDesc == (SkDescriptor*)&that.fStorage) {
157         this->reset(*that.getDesc());
158     } else {
159         this->free();
160         fDesc = that.fDesc;
161         that.fDesc = nullptr;
162     }
163     return *this;
164 }
165 
~SkAutoDescriptor()166 SkAutoDescriptor::~SkAutoDescriptor() { this->free(); }
167 
reset(size_t size)168 void SkAutoDescriptor::reset(size_t size) {
169     this->free();
170     if (size <= sizeof(fStorage)) {
171         fDesc = new (&fStorage) SkDescriptor{};
172     } else {
173         fDesc = SkDescriptor::Alloc(size).release();
174     }
175 }
176 
reset(const SkDescriptor & desc)177 void SkAutoDescriptor::reset(const SkDescriptor& desc) {
178     size_t size = desc.getLength();
179     this->reset(size);
180     memcpy(fDesc, &desc, size);
181 }
182 
free()183 void SkAutoDescriptor::free() {
184     if (fDesc == (SkDescriptor*)&fStorage) {
185         fDesc->~SkDescriptor();
186     } else {
187         delete fDesc;
188     }
189 }
190 
191 
192