1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2019 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "src/core/SkDescriptor.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include <new> 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 13cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 14cb93a386Sopenharmony_ci#include "src/core/SkOpts.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_cistd::unique_ptr<SkDescriptor> SkDescriptor::Alloc(size_t length) { 17cb93a386Sopenharmony_ci SkASSERT(SkAlign4(length) == length); 18cb93a386Sopenharmony_ci void* allocation = ::operator new (length); 19cb93a386Sopenharmony_ci return std::unique_ptr<SkDescriptor>(new (allocation) SkDescriptor{}); 20cb93a386Sopenharmony_ci} 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_civoid SkDescriptor::operator delete(void* p) { ::operator delete(p); } 23cb93a386Sopenharmony_civoid* SkDescriptor::operator new(size_t) { 24cb93a386Sopenharmony_ci SK_ABORT("Descriptors are created with placement new."); 25cb93a386Sopenharmony_ci} 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_civoid* SkDescriptor::addEntry(uint32_t tag, size_t length, const void* data) { 28cb93a386Sopenharmony_ci SkASSERT(tag); 29cb93a386Sopenharmony_ci SkASSERT(SkAlign4(length) == length); 30cb93a386Sopenharmony_ci SkASSERT(this->findEntry(tag, nullptr) == nullptr); 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci Entry* entry = (Entry*)((char*)this + fLength); 33cb93a386Sopenharmony_ci entry->fTag = tag; 34cb93a386Sopenharmony_ci entry->fLen = SkToU32(length); 35cb93a386Sopenharmony_ci if (data) { 36cb93a386Sopenharmony_ci memcpy(entry + 1, data, length); 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci fCount += 1; 40cb93a386Sopenharmony_ci fLength = SkToU32(fLength + sizeof(Entry) + length); 41cb93a386Sopenharmony_ci return (entry + 1); // return its data 42cb93a386Sopenharmony_ci} 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_civoid SkDescriptor::computeChecksum() { 45cb93a386Sopenharmony_ci fChecksum = SkDescriptor::ComputeChecksum(this); 46cb93a386Sopenharmony_ci} 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ciconst void* SkDescriptor::findEntry(uint32_t tag, uint32_t* length) const { 49cb93a386Sopenharmony_ci const Entry* entry = (const Entry*)(this + 1); 50cb93a386Sopenharmony_ci int count = fCount; 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ci while (--count >= 0) { 53cb93a386Sopenharmony_ci if (entry->fTag == tag) { 54cb93a386Sopenharmony_ci if (length) { 55cb93a386Sopenharmony_ci *length = entry->fLen; 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci return entry + 1; 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci entry = (const Entry*)((const char*)(entry + 1) + entry->fLen); 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci return nullptr; 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_cistd::unique_ptr<SkDescriptor> SkDescriptor::copy() const { 65cb93a386Sopenharmony_ci std::unique_ptr<SkDescriptor> desc = SkDescriptor::Alloc(fLength); 66cb93a386Sopenharmony_ci memcpy(desc.get(), this, fLength); 67cb93a386Sopenharmony_ci return desc; 68cb93a386Sopenharmony_ci} 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_cibool SkDescriptor::operator==(const SkDescriptor& other) const { 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci // the first value we should look at is the checksum, so this loop 73cb93a386Sopenharmony_ci // should terminate early if they descriptors are different. 74cb93a386Sopenharmony_ci // NOTE: if we wrote a sentinel value at the end of each, we could 75cb93a386Sopenharmony_ci // remove the aa < stop test in the loop... 76cb93a386Sopenharmony_ci const uint32_t* aa = (const uint32_t*)this; 77cb93a386Sopenharmony_ci const uint32_t* bb = (const uint32_t*)&other; 78cb93a386Sopenharmony_ci const uint32_t* stop = (const uint32_t*)((const char*)aa + fLength); 79cb93a386Sopenharmony_ci do { 80cb93a386Sopenharmony_ci if (*aa++ != *bb++) 81cb93a386Sopenharmony_ci return false; 82cb93a386Sopenharmony_ci } while (aa < stop); 83cb93a386Sopenharmony_ci return true; 84cb93a386Sopenharmony_ci} 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ciSkString SkDescriptor::dumpRec() const { 87cb93a386Sopenharmony_ci const SkScalerContextRec* rec = static_cast<const SkScalerContextRec*>( 88cb93a386Sopenharmony_ci this->findEntry(kRec_SkDescriptorTag, nullptr)); 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci SkString result; 91cb93a386Sopenharmony_ci result.appendf(" Checksum: %x\n", fChecksum); 92cb93a386Sopenharmony_ci if (rec != nullptr) { 93cb93a386Sopenharmony_ci result.append(rec->dump()); 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci return result; 96cb93a386Sopenharmony_ci} 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ciuint32_t SkDescriptor::ComputeChecksum(const SkDescriptor* desc) { 99cb93a386Sopenharmony_ci const uint32_t* ptr = (const uint32_t*)desc + 1; // skip the checksum field 100cb93a386Sopenharmony_ci size_t len = desc->fLength - sizeof(uint32_t); 101cb93a386Sopenharmony_ci return SkOpts::hash(ptr, len); 102cb93a386Sopenharmony_ci} 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_cibool SkDescriptor::isValid() const { 105cb93a386Sopenharmony_ci uint32_t count = fCount; 106cb93a386Sopenharmony_ci size_t lengthRemaining = this->fLength; 107cb93a386Sopenharmony_ci if (lengthRemaining < sizeof(SkDescriptor)) { 108cb93a386Sopenharmony_ci return false; 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci lengthRemaining -= sizeof(SkDescriptor); 111cb93a386Sopenharmony_ci size_t offset = sizeof(SkDescriptor); 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci while (lengthRemaining > 0 && count > 0) { 114cb93a386Sopenharmony_ci if (lengthRemaining < sizeof(Entry)) { 115cb93a386Sopenharmony_ci return false; 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci lengthRemaining -= sizeof(Entry); 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci const Entry* entry = (const Entry*)(reinterpret_cast<const char*>(this) + offset); 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci if (lengthRemaining < entry->fLen) { 122cb93a386Sopenharmony_ci return false; 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci lengthRemaining -= entry->fLen; 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci // rec tags are always a known size. 127cb93a386Sopenharmony_ci if (entry->fTag == kRec_SkDescriptorTag && entry->fLen != sizeof(SkScalerContextRec)) { 128cb93a386Sopenharmony_ci return false; 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci offset += sizeof(Entry) + entry->fLen; 132cb93a386Sopenharmony_ci count--; 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci return lengthRemaining == 0 && count == 0; 135cb93a386Sopenharmony_ci} 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor() = default; 138cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor(size_t size) { this->reset(size); } 139cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor(const SkDescriptor& desc) { this->reset(desc); } 140cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor(const SkAutoDescriptor& that) { 141cb93a386Sopenharmony_ci this->reset(*that.getDesc()); 142cb93a386Sopenharmony_ci} 143cb93a386Sopenharmony_ciSkAutoDescriptor& SkAutoDescriptor::operator=(const SkAutoDescriptor& that) { 144cb93a386Sopenharmony_ci this->reset(*that.getDesc()); 145cb93a386Sopenharmony_ci return *this; 146cb93a386Sopenharmony_ci} 147cb93a386Sopenharmony_ciSkAutoDescriptor::SkAutoDescriptor(SkAutoDescriptor&& that) { 148cb93a386Sopenharmony_ci if (that.fDesc == (SkDescriptor*)&that.fStorage) { 149cb93a386Sopenharmony_ci this->reset(*that.getDesc()); 150cb93a386Sopenharmony_ci } else { 151cb93a386Sopenharmony_ci fDesc = that.fDesc; 152cb93a386Sopenharmony_ci that.fDesc = nullptr; 153cb93a386Sopenharmony_ci } 154cb93a386Sopenharmony_ci} 155cb93a386Sopenharmony_ciSkAutoDescriptor& SkAutoDescriptor::operator=(SkAutoDescriptor&& that) { 156cb93a386Sopenharmony_ci if (that.fDesc == (SkDescriptor*)&that.fStorage) { 157cb93a386Sopenharmony_ci this->reset(*that.getDesc()); 158cb93a386Sopenharmony_ci } else { 159cb93a386Sopenharmony_ci this->free(); 160cb93a386Sopenharmony_ci fDesc = that.fDesc; 161cb93a386Sopenharmony_ci that.fDesc = nullptr; 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ci return *this; 164cb93a386Sopenharmony_ci} 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ciSkAutoDescriptor::~SkAutoDescriptor() { this->free(); } 167cb93a386Sopenharmony_ci 168cb93a386Sopenharmony_civoid SkAutoDescriptor::reset(size_t size) { 169cb93a386Sopenharmony_ci this->free(); 170cb93a386Sopenharmony_ci if (size <= sizeof(fStorage)) { 171cb93a386Sopenharmony_ci fDesc = new (&fStorage) SkDescriptor{}; 172cb93a386Sopenharmony_ci } else { 173cb93a386Sopenharmony_ci fDesc = SkDescriptor::Alloc(size).release(); 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci} 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_civoid SkAutoDescriptor::reset(const SkDescriptor& desc) { 178cb93a386Sopenharmony_ci size_t size = desc.getLength(); 179cb93a386Sopenharmony_ci this->reset(size); 180cb93a386Sopenharmony_ci memcpy(fDesc, &desc, size); 181cb93a386Sopenharmony_ci} 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_civoid SkAutoDescriptor::free() { 184cb93a386Sopenharmony_ci if (fDesc == (SkDescriptor*)&fStorage) { 185cb93a386Sopenharmony_ci fDesc->~SkDescriptor(); 186cb93a386Sopenharmony_ci } else { 187cb93a386Sopenharmony_ci delete fDesc; 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci} 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_ci 192