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
18class SkDescriptor : SkNoncopyable {
19public:
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
66private:
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
78class SkAutoDescriptor {
79public:
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
94private:
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