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