1 /*
2  * Copyright 2006 The Android Open Source Project
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 #ifndef SkDescriptor_DEFINED
9 #define SkDescriptor_DEFINED
10 
11 #include <memory>
12 
13 #include "SkMacros.h"
14 #include "SkNoncopyable.h"
15 #include "SkScalerContext.h"
16 
17 class SkDescriptor : SkNoncopyable {
18 public:
ComputeOverhead(int entryCount)19     static size_t ComputeOverhead(int entryCount) {
20         SkASSERT(entryCount >= 0);
21         return sizeof(SkDescriptor) + entryCount * sizeof(Entry);
22     }
23 
24     static std::unique_ptr<SkDescriptor> Alloc(size_t length);
25 
26     // Ensure the unsized delete is called.
27     void operator delete(void* p);
init()28     void init() {
29         fLength = sizeof(SkDescriptor);
30         fCount  = 0;
31     }
getLength()32     uint32_t getLength() const { return fLength; }
33     void* addEntry(uint32_t tag, size_t length, const void* data = nullptr);
34     void computeChecksum();
35 
36 #ifdef SK_DEBUG
assertChecksum()37     void assertChecksum() const {
38         SkASSERT(SkDescriptor::ComputeChecksum(this) == fChecksum);
39     }
40 #endif
41 
42     const void* findEntry(uint32_t tag, uint32_t* length) const;
43 
44     std::unique_ptr<SkDescriptor> copy() const;
45 
46     // This assumes that all memory added has a length that is a multiple of 4. This is checked
47     // by the assert in addEntry.
48     bool operator==(const SkDescriptor& other) const;
49     bool operator!=(const SkDescriptor& other) const { return !(*this == other); }
50 
getChecksum()51     uint32_t getChecksum() const { return fChecksum; }
52 
53     struct Entry {
54         uint32_t fTag;
55         uint32_t fLen;
56     };
57 
58 #ifdef SK_DEBUG
getCount()59     uint32_t getCount() const { return fCount; }
60 #endif
61 
62 private:
63     // private so no one can create one except our factories
64     SkDescriptor() = default;
65 
66     static uint32_t ComputeChecksum(const SkDescriptor* desc);
67 
68     uint32_t fChecksum;  // must be first
69     uint32_t fLength;    // must be second
70     uint32_t fCount;
71 };
72 
73 class SkAutoDescriptor : SkNoncopyable {
74 public:
75     SkAutoDescriptor();
76     SkAutoDescriptor(size_t size);
77     SkAutoDescriptor(const SkDescriptor& desc);
78     SkAutoDescriptor(SkAutoDescriptor&&) = delete;
79     SkAutoDescriptor& operator =(SkAutoDescriptor&&) = delete;
80 
81     ~SkAutoDescriptor();
82 
83     void reset(size_t size);
84     void reset(const SkDescriptor& desc);
getDesc()85     SkDescriptor* getDesc() const { SkASSERT(fDesc); return fDesc; }
86 
87 private:
88     void free();
89     static constexpr size_t kStorageSize
90             = sizeof(SkDescriptor)
91               + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContextRec) // for rec
92               + sizeof(SkDescriptor::Entry) + sizeof(void*)              // for typeface
93               + 32;   // slop for occasional small extras
94 
95     SkDescriptor*   fDesc{nullptr};
96     std::aligned_storage<kStorageSize, alignof(uint32_t)>::type fStorage;
97 };
98 
99 #endif  //SkDescriptor_DEFINED
100