• 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 
ComputeChecksum(const SkDescriptor * desc)86 uint32_t SkDescriptor::ComputeChecksum(const SkDescriptor* desc) {
87     const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field
88     size_t len = desc->fLength - sizeof(uint32_t);
89     return SkOpts::hash(ptr, len);
90 }
91 
isValid() const92 bool SkDescriptor::isValid() const {
93     uint32_t count = fCount;
94     size_t lengthRemaining = this->fLength;
95     if (lengthRemaining < sizeof(SkDescriptor)) {
96         return false;
97     }
98     lengthRemaining -= sizeof(SkDescriptor);
99     size_t offset = sizeof(SkDescriptor);
100 
101     while (lengthRemaining > 0 && count > 0) {
102         if (lengthRemaining < sizeof(Entry)) {
103             return false;
104         }
105         lengthRemaining -= sizeof(Entry);
106 
107         const Entry* entry = (const Entry*)(reinterpret_cast<const char*>(this) + offset);
108 
109         if (lengthRemaining < entry->fLen) {
110             return false;
111         }
112         lengthRemaining -= entry->fLen;
113 
114         // rec tags are always a known size.
115         if (entry->fTag == kRec_SkDescriptorTag && entry->fLen != sizeof(SkScalerContextRec)) {
116             return false;
117         }
118 
119         offset += sizeof(Entry) + entry->fLen;
120         count--;
121     }
122     return lengthRemaining == 0 && count == 0;
123 }
124 
125 SkAutoDescriptor::SkAutoDescriptor() = default;
SkAutoDescriptor(size_t size)126 SkAutoDescriptor::SkAutoDescriptor(size_t size) { this->reset(size); }
SkAutoDescriptor(const SkDescriptor & desc)127 SkAutoDescriptor::SkAutoDescriptor(const SkDescriptor& desc) { this->reset(desc); }
SkAutoDescriptor(const SkAutoDescriptor & ad)128 SkAutoDescriptor::SkAutoDescriptor(const SkAutoDescriptor& ad) {
129     this->reset(*ad.getDesc());
130 }
operator =(const SkAutoDescriptor & ad)131 SkAutoDescriptor& SkAutoDescriptor::operator=(const SkAutoDescriptor& ad) {
132     this->reset(*ad.getDesc());
133     return *this;
134 }
135 
~SkAutoDescriptor()136 SkAutoDescriptor::~SkAutoDescriptor() { this->free(); }
137 
reset(size_t size)138 void SkAutoDescriptor::reset(size_t size) {
139     this->free();
140     if (size <= sizeof(fStorage)) {
141         fDesc = new (&fStorage) SkDescriptor{};
142     } else {
143         fDesc = SkDescriptor::Alloc(size).release();
144     }
145 }
146 
reset(const SkDescriptor & desc)147 void SkAutoDescriptor::reset(const SkDescriptor& desc) {
148     size_t size = desc.getLength();
149     this->reset(size);
150     memcpy(fDesc, &desc, size);
151 }
152 
free()153 void SkAutoDescriptor::free() {
154     if (fDesc != (SkDescriptor*)&fStorage) {
155         delete fDesc;
156     }
157 }
158 
159 
160