blob: efa02783be50b6b178272f8b40881e9e12ca29e3 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
epoger@google.comec3ed6a2011-07-28 14:26:00 +00008
reed@android.com8a1c16f2008-12-17 15:59:43 +00009#ifndef SkDescriptor_DEFINED
10#define SkDescriptor_DEFINED
11
mtklein4e976072016-08-08 09:06:27 -070012#include "SkOpts.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000013#include "SkTypes.h"
14
15class SkDescriptor : SkNoncopyable {
16public:
reed@google.com142e1fe2012-07-09 17:44:44 +000017 static size_t ComputeOverhead(int entryCount) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000018 SkASSERT(entryCount >= 0);
19 return sizeof(SkDescriptor) + entryCount * sizeof(Entry);
20 }
21
reed@google.com142e1fe2012-07-09 17:44:44 +000022 static SkDescriptor* Alloc(size_t length) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000023 SkASSERT(SkAlign4(length) == length);
24 SkDescriptor* desc = (SkDescriptor*)sk_malloc_throw(length);
25 return desc;
26 }
27
reed@google.com142e1fe2012-07-09 17:44:44 +000028 static void Free(SkDescriptor* desc) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000029 sk_free(desc);
30 }
31
reed@google.com142e1fe2012-07-09 17:44:44 +000032 void init() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000033 fLength = sizeof(SkDescriptor);
34 fCount = 0;
35 }
36
37 uint32_t getLength() const { return fLength; }
38
halcanary96fcdcc2015-08-27 07:41:13 -070039 void* addEntry(uint32_t tag, size_t length, const void* data = nullptr) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000040 SkASSERT(tag);
41 SkASSERT(SkAlign4(length) == length);
halcanary96fcdcc2015-08-27 07:41:13 -070042 SkASSERT(this->findEntry(tag, nullptr) == nullptr);
reed@android.com8a1c16f2008-12-17 15:59:43 +000043
bsalomonccb328d2014-12-11 13:31:06 -080044 Entry* entry = (Entry*)((char*)this + fLength);
reed@android.com8a1c16f2008-12-17 15:59:43 +000045 entry->fTag = tag;
commit-bot@chromium.org2cfa3202014-04-19 22:00:40 +000046 entry->fLen = SkToU32(length);
reed@google.com142e1fe2012-07-09 17:44:44 +000047 if (data) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000048 memcpy(entry + 1, data, length);
reed@google.com142e1fe2012-07-09 17:44:44 +000049 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000050
51 fCount += 1;
bsalomonccb328d2014-12-11 13:31:06 -080052 fLength = SkToU32(fLength + sizeof(Entry) + length);
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 return (entry + 1); // return its data
54 }
55
reed@google.com142e1fe2012-07-09 17:44:44 +000056 void computeChecksum() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000057 fChecksum = SkDescriptor::ComputeChecksum(this);
58 }
59
60#ifdef SK_DEBUG
reed@google.com142e1fe2012-07-09 17:44:44 +000061 void assertChecksum() const {
62 SkASSERT(SkDescriptor::ComputeChecksum(this) == fChecksum);
reed@android.com8a1c16f2008-12-17 15:59:43 +000063 }
64#endif
65
reed@google.com142e1fe2012-07-09 17:44:44 +000066 const void* findEntry(uint32_t tag, uint32_t* length) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000067 const Entry* entry = (const Entry*)(this + 1);
68 int count = fCount;
69
reed@google.com142e1fe2012-07-09 17:44:44 +000070 while (--count >= 0) {
71 if (entry->fTag == tag) {
72 if (length) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000073 *length = entry->fLen;
reed@google.com142e1fe2012-07-09 17:44:44 +000074 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000075 return entry + 1;
76 }
77 entry = (const Entry*)((const char*)(entry + 1) + entry->fLen);
78 }
halcanary96fcdcc2015-08-27 07:41:13 -070079 return nullptr;
reed@android.com8a1c16f2008-12-17 15:59:43 +000080 }
81
reed@google.com142e1fe2012-07-09 17:44:44 +000082 SkDescriptor* copy() const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000083 SkDescriptor* desc = SkDescriptor::Alloc(fLength);
84 memcpy(desc, this, fLength);
85 return desc;
86 }
87
bsalomonc5d07fa2016-05-17 10:17:45 -070088 bool operator==(const SkDescriptor& other) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000089 // probe to see if we have a good checksum algo
90// SkASSERT(a.fChecksum != b.fChecksum || memcmp(&a, &b, a.fLength) == 0);
91
92 // the first value we should look at is the checksum, so this loop
93 // should terminate early if they descriptors are different.
94 // NOTE: if we wrote a sentinel value at the end of each, we chould
95 // remove the aa < stop test in the loop...
96 const uint32_t* aa = (const uint32_t*)this;
97 const uint32_t* bb = (const uint32_t*)&other;
98 const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength);
99 do {
100 if (*aa++ != *bb++)
101 return false;
102 } while (aa < stop);
103 return true;
104 }
bsalomond1c71fd2016-05-19 12:51:46 -0700105 bool operator!=(const SkDescriptor& other) const { return !(*this == other); }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000106
reed@android.comf2b98d62010-12-20 18:26:13 +0000107 uint32_t getChecksum() const { return fChecksum; }
108
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109 struct Entry {
110 uint32_t fTag;
111 uint32_t fLen;
112 };
113
114#ifdef SK_DEBUG
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115 uint32_t getCount() const { return fCount; }
116#endif
117
118private:
119 uint32_t fChecksum; // must be first
120 uint32_t fLength; // must be second
121 uint32_t fCount;
122
reed@google.com142e1fe2012-07-09 17:44:44 +0000123 static uint32_t ComputeChecksum(const SkDescriptor* desc) {
junov@chromium.orgef760602012-06-27 20:03:16 +0000124 const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field
reed@google.com142e1fe2012-07-09 17:44:44 +0000125 size_t len = desc->fLength - sizeof(uint32_t);
mtklein4e976072016-08-08 09:06:27 -0700126 return SkOpts::hash(ptr, len);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 }
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000128
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129 // private so no one can create one except our factories
130 SkDescriptor() {}
131};
132
133#include "SkScalerContext.h"
134
135class SkAutoDescriptor : SkNoncopyable {
136public:
halcanary96fcdcc2015-08-27 07:41:13 -0700137 SkAutoDescriptor() : fDesc(nullptr) {}
138 SkAutoDescriptor(size_t size) : fDesc(nullptr) { this->reset(size); }
139 SkAutoDescriptor(const SkDescriptor& desc) : fDesc(nullptr) {
joshualitt73d5de52015-07-17 06:19:19 -0700140 size_t size = desc.getLength();
141 this->reset(size);
142 memcpy(fDesc, &desc, size);
143 }
joshualitt2b6acb42015-04-01 11:30:27 -0700144
145 ~SkAutoDescriptor() { this->free(); }
146
147 void reset(size_t size) {
148 this->free();
reed@google.com142e1fe2012-07-09 17:44:44 +0000149 if (size <= sizeof(fStorage)) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150 fDesc = (SkDescriptor*)(void*)fStorage;
reed@google.com142e1fe2012-07-09 17:44:44 +0000151 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152 fDesc = SkDescriptor::Alloc(size);
reed@google.com142e1fe2012-07-09 17:44:44 +0000153 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154 }
reed@google.com142e1fe2012-07-09 17:44:44 +0000155
joshualitt2b6acb42015-04-01 11:30:27 -0700156 SkDescriptor* getDesc() const { SkASSERT(fDesc); return fDesc; }
157private:
158 void free() {
reed@google.com142e1fe2012-07-09 17:44:44 +0000159 if (fDesc != (SkDescriptor*)(void*)fStorage) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160 SkDescriptor::Free(fDesc);
reed@google.com142e1fe2012-07-09 17:44:44 +0000161 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162 }
reed@google.com142e1fe2012-07-09 17:44:44 +0000163
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164 enum {
165 kStorageSize = sizeof(SkDescriptor)
166 + sizeof(SkDescriptor::Entry) + sizeof(SkScalerContext::Rec) // for rec
167 + sizeof(SkDescriptor::Entry) + sizeof(void*) // for typeface
168 + 32 // slop for occational small extras
169 };
170 SkDescriptor* fDesc;
171 uint32_t fStorage[(kStorageSize + 3) >> 2];
172};
commit-bot@chromium.orge61a86c2013-11-18 16:03:59 +0000173#define SkAutoDescriptor(...) SK_REQUIRE_LOCAL_VAR(SkAutoDescriptor)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174
175
176#endif