Index: src/pdf/SkPDFTypes.cpp |
diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp |
index cd130cfc520b46f36918b80b016f7da5bf713da1..510b98b17f471d6148f7c709bf56d33cb3872679 100644 |
--- a/src/pdf/SkPDFTypes.cpp |
+++ b/src/pdf/SkPDFTypes.cpp |
@@ -6,7 +6,6 @@ |
* found in the LICENSE file. |
*/ |
- |
#include "SkPDFTypes.h" |
#include "SkStream.h" |
@@ -18,62 +17,271 @@ |
//////////////////////////////////////////////////////////////////////////////// |
-SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) { |
- SkSafeRef(obj); |
+SkString* pun(char* x) { return reinterpret_cast<SkString*>(x); } |
+const SkString* pun(const char* x) { |
+ return reinterpret_cast<const SkString*>(x); |
} |
-SkPDFObjRef::~SkPDFObjRef() {} |
+SkPDFUnion::SkPDFUnion(Type t) : fType(t) {} |
-void SkPDFObjRef::emitObject(SkWStream* stream, |
- const SkPDFObjNumMap& objNumMap, |
- const SkPDFSubstituteMap& substitutes) { |
- SkPDFObject* obj = substitutes.getSubstitute(fObj); |
- stream->writeDecAsText(objNumMap.getObjectNumber(obj)); |
- stream->writeText(" 0 R"); // Generation number is always 0. |
+SkPDFUnion::~SkPDFUnion() { |
+ switch (fType) { |
+ case Type::kNameSkS: |
+ case Type::kStringSkS: |
+ pun(fSkString)->~SkString(); |
+ return; |
+ case Type::kObjRef: |
+ case Type::kObject: |
+ SkSafeUnref(fObject); |
+ return; |
+ default: |
+ return; |
+ } |
} |
-void SkPDFObjRef::addResources(SkPDFObjNumMap* catalog, |
- const SkPDFSubstituteMap& substitutes) const { |
- SkPDFObject* obj = substitutes.getSubstitute(fObj); |
- SkASSERT(obj); |
- if (catalog->addObject(obj)) { |
- obj->addResources(catalog, substitutes); |
+SkPDFUnion& SkPDFUnion::operator=(SkPDFUnion&& other) { |
+ if (this != &other) { |
+ this->~SkPDFUnion(); |
+ SkNEW_PLACEMENT_ARGS(this, SkPDFUnion, (other.move())); |
} |
+ return *this; |
+} |
+ |
+SkPDFUnion::SkPDFUnion(SkPDFUnion&& other) { |
+ SkASSERT(this != &other); |
+ memcpy(this, &other, sizeof(*this)); |
+ other.fType = Type::kDestroyed; |
+} |
+ |
+#if 0 |
+SkPDFUnion SkPDFUnion::copy() const { |
+ SkPDFUnion u(fType); |
+ memcpy(&u, this, sizeof(u)); |
+ switch (fType) { |
+ case Type::kNameSkS: |
+ case Type::kStringSkS: |
+ SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, |
+ (*pun(fSkString))); |
+ return u.move(); |
+ case Type::kObjRef: |
+ case Type::kObject: |
+ SkRef(u.fObject); |
+ return u.move(); |
+ default: |
+ return u.move(); |
+ } |
+} |
+SkPDFUnion& SkPDFUnion::operator=(const SkPDFUnion& other) { |
+ return *this = other.copy(); |
} |
+SkPDFUnion::SkPDFUnion(const SkPDFUnion& other) { |
+ *this = other.copy(); |
+} |
+#endif |
-//////////////////////////////////////////////////////////////////////////////// |
+bool SkPDFUnion::isName() const { |
+ return Type::kName == fType || Type::kNameSkS == fType; |
+} |
-SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {} |
-SkPDFInt::~SkPDFInt() {} |
+#ifdef SK_DEBUG |
+// Most names need no escaping. Such names are handled as static |
+// const strings. |
+bool is_valid_name(const char* n) { |
+ static const char kControlChars[] = "/%()<>[]{}"; |
+ while (*n) { |
+ if (*n < '!' || *n > '~' || strchr(kControlChars, *n)) { |
+ return false; |
+ } |
+ ++n; |
+ } |
+ return true; |
+} |
+#endif // SK_DEBUG |
-void SkPDFInt::emitObject(SkWStream* stream, |
- const SkPDFObjNumMap&, |
- const SkPDFSubstituteMap&) { |
- stream->writeDecAsText(fValue); |
+// Given an arbitrary string, convert it to a valid name. |
+static SkString escape_name(const char* name, size_t len) { |
+ static const char kToEscape[] = "#/%()<>[]{}"; |
+ int count = 0; |
+ const char* const end = &name[len]; |
+ for (const char* n = name; n != end; ++n) { |
+ if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) { |
+ count += 2; |
+ } |
+ ++count; |
+ } |
+ SkString result(count); |
+ char* s = result.writable_str(); |
+ static const char kHex[] = "0123456789ABCDEF"; |
+ for (const char* n = name; n != end; ++n) { |
+ if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) { |
+ *s++ = '#'; |
+ *s++ = kHex[(*n >> 4) & 0xF]; |
+ *s++ = kHex[*n & 0xF]; |
+ } else { |
+ *s++ = *n; |
+ } |
+ } |
+ SkASSERT(&result.writable_str()[count] == s); // don't over-write |
+ return result; // allocated space |
} |
-//////////////////////////////////////////////////////////////////////////////// |
+static SkString escape_name(const SkString& name) { |
+ return escape_name(name.c_str(), name.size()); |
+} |
-SkPDFBool::SkPDFBool(bool value) : fValue(value) {} |
-SkPDFBool::~SkPDFBool() {} |
+static void write_string(SkWStream* o, const SkString& s) { |
+ o->write(s.c_str(), s.size()); |
+} |
-void SkPDFBool::emitObject(SkWStream* stream, |
- const SkPDFObjNumMap&, |
- const SkPDFSubstituteMap&) { |
- stream->writeText(fValue ? "true" : "false"); |
+static SkString format_string(const SkString& s) { |
+ return SkPDFString::FormatString(s.c_str(), s.size()); |
} |
-//////////////////////////////////////////////////////////////////////////////// |
+static SkString format_string(const char* s) { |
+ return SkPDFString::FormatString(s, strlen(s)); |
+} |
-SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {} |
-SkPDFScalar::~SkPDFScalar() {} |
+void SkPDFUnion::emitObject(SkWStream* stream, |
+ const SkPDFObjNumMap& objNumMap, |
+ const SkPDFSubstituteMap& substitutes) const { |
+ switch (fType) { |
+ case Type::kInt: |
+ stream->writeDecAsText(fIntValue); |
+ return; |
+ case Type::kBool: |
+ stream->writeText(fBoolValue ? "true" : "false"); |
+ return; |
+ case Type::kScalar: |
+ SkPDFScalar::Append(fScalarValue, stream); |
+ return; |
+ case Type::kName: |
+ stream->writeText("/"); |
+ SkASSERT(is_valid_name(fStaticString)); |
+ stream->writeText(fStaticString); |
+ return; |
+ case Type::kString: |
+ SkASSERT(fStaticString); |
+ write_string(stream, format_string(fStaticString)); |
+ return; |
+ case Type::kNameSkS: |
+ stream->writeText("/"); |
+ write_string(stream, escape_name(*pun(fSkString))); |
+ return; |
+ case Type::kStringSkS: |
+ write_string(stream, format_string(*pun(fSkString))); |
+ return; |
+ case Type::kObjRef: |
+ stream->writeDecAsText(objNumMap.getObjectNumber( |
+ substitutes.getSubstitute(fObject))); |
+ stream->writeText(" 0 R"); // Generation number is always 0. |
+ return; |
+ case Type::kObject: |
+ fObject->emitObject(stream, objNumMap, substitutes); |
+ return; |
+ default: |
+ SkDEBUGFAIL("SkPDFUnion::emitObject with bad type"); |
+ } |
+} |
+ |
+void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap, |
+ const SkPDFSubstituteMap& substituteMap) const { |
+ switch (fType) { |
+ case Type::kInt: |
+ case Type::kBool: |
+ case Type::kScalar: |
+ case Type::kName: |
+ case Type::kString: |
+ case Type::kNameSkS: |
+ case Type::kStringSkS: |
+ return; // These have no resources. |
+ case Type::kObjRef: { |
+ SkPDFObject* obj = substituteMap.getSubstitute(fObject); |
+ if (objNumMap->addObject(obj)) { |
+ obj->addResources(objNumMap, substituteMap); |
+ } |
+ return; |
+ } |
+ case Type::kObject: |
+ fObject->addResources(objNumMap, substituteMap); |
+ return; |
+ default: |
+ SkDEBUGFAIL("SkPDFUnion::addResources with bad type"); |
+ } |
+} |
+ |
+SkPDFUnion SkPDFUnion::Int(int32_t value) { |
+ SkPDFUnion u(Type::kInt); |
+ u.fIntValue = value; |
+ return u.move(); |
+} |
+ |
+SkPDFUnion SkPDFUnion::Bool(bool value) { |
+ SkPDFUnion u(Type::kBool); |
+ u.fBoolValue = value; |
+ return u.move(); |
+} |
-void SkPDFScalar::emitObject(SkWStream* stream, |
- const SkPDFObjNumMap&, |
- const SkPDFSubstituteMap&) { |
- SkPDFScalar::Append(fValue, stream); |
+SkPDFUnion SkPDFUnion::Scalar(SkScalar value) { |
+ SkPDFUnion u(Type::kScalar); |
+ u.fScalarValue = value; |
+ return u.move(); |
} |
+SkPDFUnion SkPDFUnion::Name(const char* value) { |
+ SkPDFUnion u(Type::kName); |
+ SkASSERT(value); |
+ SkASSERT(is_valid_name(value)); |
+ u.fStaticString = value; |
+ return u.move(); |
+} |
+ |
+SkPDFUnion SkPDFUnion::String(const char* value) { |
+ SkPDFUnion u(Type::kString); |
+ SkASSERT(value); |
+ u.fStaticString = value; |
+ return u.move(); |
+} |
+ |
+SkPDFUnion SkPDFUnion::Name(const SkString& s) { |
+ SkPDFUnion u(Type::kNameSkS); |
+ SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, (s)); |
+ return u.move(); |
+} |
+ |
+SkPDFUnion SkPDFUnion::String(const SkString& s) { |
+ SkPDFUnion u(Type::kStringSkS); |
+ SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, (s)); |
+ return u.move(); |
+} |
+ |
+SkPDFUnion SkPDFUnion::ObjRef(SkPDFObject* ptr) { |
+ SkPDFUnion u(Type::kObjRef); |
+ SkASSERT(ptr); |
+ u.fObject = ptr; |
+ return u.move(); |
+} |
+ |
+SkPDFUnion SkPDFUnion::Object(SkPDFObject* ptr) { |
+ SkPDFUnion u(Type::kObject); |
+ SkASSERT(ptr); |
+ u.fObject = ptr; |
+ return u.move(); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+ |
+void SkPDFAtom::emitObject(SkWStream* stream, |
+ const SkPDFObjNumMap& objNumMap, |
+ const SkPDFSubstituteMap& substitutes) { |
+ fValue.emitObject(stream, objNumMap, substitutes); |
+} |
+void SkPDFAtom::addResources(SkPDFObjNumMap* map, |
+ const SkPDFSubstituteMap& substitutes) const { |
+ fValue.addResources(map, substitutes); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+ |
// static |
void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { |
// The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and |
@@ -125,23 +333,8 @@ void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { |
//////////////////////////////////////////////////////////////////////////////// |
-SkPDFString::SkPDFString(const char value[]) |
- : fValue(FormatString(value, strlen(value))) { |
-} |
- |
-SkPDFString::SkPDFString(const SkString& value) |
- : fValue(FormatString(value.c_str(), value.size())) { |
-} |
- |
-SkPDFString::~SkPDFString() {} |
- |
-void SkPDFString::emitObject(SkWStream* stream, |
- const SkPDFObjNumMap&, |
- const SkPDFSubstituteMap&) { |
- stream->write(fValue.c_str(), fValue.size()); |
-} |
- |
// static |
+ |
SkString SkPDFString::FormatString(const char* cin, size_t len) { |
SkASSERT(len <= kMaxLen); |
@@ -187,55 +380,25 @@ SkString SkPDFString::FormatString(const char* cin, size_t len) { |
//////////////////////////////////////////////////////////////////////////////// |
-SkPDFName::SkPDFName(const char name[]) : fValue(FormatName(SkString(name))) {} |
-SkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {} |
-SkPDFName::~SkPDFName() {} |
- |
-bool SkPDFName::operator==(const SkPDFName& b) const { |
- return fValue == b.fValue; |
-} |
- |
-void SkPDFName::emitObject(SkWStream* stream, |
- const SkPDFObjNumMap&, |
- const SkPDFSubstituteMap&) { |
- stream->write(fValue.c_str(), fValue.size()); |
-} |
- |
-// static |
-SkString SkPDFName::FormatName(const SkString& input) { |
- SkASSERT(input.size() <= kMaxLen); |
- // TODO(vandebo) If more escaping is needed, improve the linear scan. |
- static const char escaped[] = "#/%()<>[]{}"; |
- |
- SkString result("/"); |
- for (size_t i = 0; i < input.size(); i++) { |
- if (input[i] & 0x80 || input[i] < '!' || strchr(escaped, input[i])) { |
- result.append("#"); |
- // Mask with 0xFF to avoid sign extension. i.e. #FFFFFF81 |
- result.appendHex(input[i] & 0xFF, 2); |
- } else { |
- result.append(input.c_str() + i, 1); |
- } |
+SkPDFArray::SkPDFArray() {} |
+SkPDFArray::~SkPDFArray() { |
+ for (SkPDFUnion& value : fValues) { |
+ value.~SkPDFUnion(); |
} |
- |
- return result; |
+ fValues.reset(); |
} |
-//////////////////////////////////////////////////////////////////////////////// |
+int SkPDFArray::size() const { return fValues.count(); } |
-SkPDFArray::SkPDFArray() {} |
-SkPDFArray::~SkPDFArray() { |
- fValue.unrefAll(); |
-} |
+void SkPDFArray::reserve(int length) { fValues.setReserve(length); } |
void SkPDFArray::emitObject(SkWStream* stream, |
const SkPDFObjNumMap& objNumMap, |
const SkPDFSubstituteMap& substitutes) { |
stream->writeText("["); |
- for (int i = 0; i < fValue.count(); i++) { |
- SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); |
- fValue[i]->emitObject(stream, objNumMap, substitutes); |
- if (i + 1 < fValue.count()) { |
+ for (int i = 0; i < fValues.count(); i++) { |
+ fValues[i].emitObject(stream, objNumMap, substitutes); |
+ if (i + 1 < fValues.count()) { |
stream->writeText(" "); |
} |
} |
@@ -244,68 +407,74 @@ void SkPDFArray::emitObject(SkWStream* stream, |
void SkPDFArray::addResources(SkPDFObjNumMap* catalog, |
const SkPDFSubstituteMap& substitutes) const { |
- for (int i = 0; i < fValue.count(); i++) { |
- SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); |
- fValue[i]->addResources(catalog, substitutes); |
+ for (const SkPDFUnion& value : fValues) { |
+ value.addResources(catalog, substitutes); |
} |
} |
-void SkPDFArray::reserve(int length) { |
- SkASSERT(length <= kMaxLen); |
- fValue.setReserve(length); |
+void SkPDFArray::append(SkPDFUnion&& value) { |
+ SkNEW_PLACEMENT_ARGS(fValues.append(), SkPDFUnion, (value.move())); |
} |
SkPDFObject* SkPDFArray::append(SkPDFObject* value) { |
- SkASSERT(fValue.count() < kMaxLen); |
- value->ref(); |
- fValue.push(value); |
+ // DEPRECATED |
+ this->append(SkPDFUnion::Object(SkRef(value))); |
return value; |
} |
void SkPDFArray::appendInt(int32_t value) { |
- SkASSERT(fValue.count() < kMaxLen); |
- fValue.push(new SkPDFInt(value)); |
+ this->append(SkPDFUnion::Int(value)); |
+} |
+ |
+void SkPDFArray::appendBool(bool value) { |
+ this->append(SkPDFUnion::Bool(value)); |
} |
void SkPDFArray::appendScalar(SkScalar value) { |
- SkASSERT(fValue.count() < kMaxLen); |
- fValue.push(new SkPDFScalar(value)); |
+ this->append(SkPDFUnion::Scalar(value)); |
} |
void SkPDFArray::appendName(const char name[]) { |
- SkASSERT(fValue.count() < kMaxLen); |
- fValue.push(new SkPDFName(name)); |
+ this->append(SkPDFUnion::Name(SkString(name))); |
} |
-/////////////////////////////////////////////////////////////////////////////// |
+void SkPDFArray::appendName(const SkString& name) { |
+ this->append(SkPDFUnion::Name(name)); |
+} |
-SkPDFDict::SkPDFDict() {} |
+void SkPDFArray::appendString(const SkString& value) { |
+ this->append(SkPDFUnion::String(value)); |
+} |
-SkPDFDict::SkPDFDict(const char type[]) { |
- insertName("Type", type); |
+void SkPDFArray::appendString(const char value[]) { |
+ this->append(SkPDFUnion::String(value)); |
} |
-SkPDFDict::~SkPDFDict() { |
- clear(); |
+void SkPDFArray::appendObject(SkPDFObject* value) { |
+ this->append(SkPDFUnion::Object(value)); |
} |
-int SkPDFDict::size() const { |
- return fValue.count(); |
+void SkPDFArray::appendObjRef(SkPDFObject* value) { |
+ this->append(SkPDFUnion::ObjRef(value)); |
} |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
+SkPDFDict::SkPDFDict() {} |
+ |
+SkPDFDict::~SkPDFDict() { this->clear(); } |
+ |
+SkPDFDict::SkPDFDict(const char type[]) { this->insertName("Type", type); } |
+ |
void SkPDFDict::emitObject(SkWStream* stream, |
const SkPDFObjNumMap& objNumMap, |
const SkPDFSubstituteMap& substitutes) { |
stream->writeText("<<"); |
- for (int i = 0; i < fValue.count(); i++) { |
- SkASSERT(fValue[i].key); |
- SkASSERT(fValue[i].value); |
- SkASSERT(substitutes.getSubstitute(fValue[i].key) == fValue[i].key); |
- SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value); |
- fValue[i].key->emitObject(stream, objNumMap, substitutes); |
+ for (int i = 0; i < fRecords.count(); i++) { |
+ fRecords[i].fKey.emitObject(stream, objNumMap, substitutes); |
stream->writeText(" "); |
- fValue[i].value->emitObject(stream, objNumMap, substitutes); |
- if (i + 1 < fValue.count()) { |
+ fRecords[i].fValue.emitObject(stream, objNumMap, substitutes); |
+ if (i + 1 < fRecords.count()) { |
stream->writeText("\n"); |
} |
} |
@@ -314,72 +483,75 @@ void SkPDFDict::emitObject(SkWStream* stream, |
void SkPDFDict::addResources(SkPDFObjNumMap* catalog, |
const SkPDFSubstituteMap& substitutes) const { |
- for (int i = 0; i < fValue.count(); i++) { |
- SkASSERT(fValue[i].key); |
- SkASSERT(fValue[i].value); |
- fValue[i].key->addResources(catalog, substitutes); |
- SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value); |
- fValue[i].value->addResources(catalog, substitutes); |
+ for (int i = 0; i < fRecords.count(); i++) { |
+ fRecords[i].fKey.addResources(catalog, substitutes); |
+ fRecords[i].fValue.addResources(catalog, substitutes); |
} |
} |
-SkPDFObject* SkPDFDict::append(SkPDFName* key, SkPDFObject* value) { |
- SkASSERT(key); |
- SkASSERT(value); |
- *(fValue.append()) = Rec(key, value); |
- return value; |
+void SkPDFDict::set(SkPDFUnion&& name, SkPDFUnion&& value) { |
+ Record* rec = fRecords.append(); |
+ SkASSERT(name.isName()); |
+ SkNEW_PLACEMENT_ARGS(&rec->fKey, SkPDFUnion, (name.move())); |
+ SkNEW_PLACEMENT_ARGS(&rec->fValue, SkPDFUnion, (value.move())); |
+} |
+ |
+int SkPDFDict::size() const { return fRecords.count(); } |
+ |
+void SkPDFDict::insertObjRef(const char key[], SkPDFObject* value) { |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value)); |
+} |
+void SkPDFDict::insertObjRef(const SkString& key, SkPDFObject* value) { |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value)); |
} |
-SkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) { |
- return this->append(SkRef(key), SkRef(value)); |
+void SkPDFDict::insertObject(const char key[], SkPDFObject* value) { |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value)); |
+} |
+void SkPDFDict::insertObject(const SkString& key, SkPDFObject* value) { |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value)); |
} |
+// DEPRECATED |
SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) { |
- return this->append(new SkPDFName(key), SkRef(value)); |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(SkRef(value))); |
+ return value; |
} |
void SkPDFDict::insertInt(const char key[], int32_t value) { |
- (void)this->append(new SkPDFName(key), new SkPDFInt(value)); |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::Int(value)); |
+} |
+ |
+void SkPDFDict::insertInt(const char key[], size_t value) { |
+ this->insertInt(key, SkToS32(value)); |
} |
void SkPDFDict::insertScalar(const char key[], SkScalar value) { |
- (void)this->append(new SkPDFName(key), new SkPDFScalar(value)); |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::Scalar(value)); |
} |
void SkPDFDict::insertName(const char key[], const char name[]) { |
- (void)this->append(new SkPDFName(key), new SkPDFName(name)); |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name)); |
} |
-void SkPDFDict::clear() { |
- for (int i = 0; i < fValue.count(); i++) { |
- SkASSERT(fValue[i].key); |
- SkASSERT(fValue[i].value); |
- fValue[i].key->unref(); |
- fValue[i].value->unref(); |
- } |
- fValue.reset(); |
-} |
- |
-void SkPDFDict::remove(const char key[]) { |
- SkASSERT(key); |
- SkPDFName name(key); |
- for (int i = 0; i < fValue.count(); i++) { |
- SkASSERT(fValue[i].key); |
- if (*(fValue[i].key) == name) { |
- fValue[i].key->unref(); |
- SkASSERT(fValue[i].value); |
- fValue[i].value->unref(); |
- fValue.removeShuffle(i); |
- return; |
- } |
- } |
+void SkPDFDict::insertName(const char key[], const SkString& name) { |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name)); |
+} |
+ |
+void SkPDFDict::insertString(const char key[], const char value[]) { |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value)); |
+} |
+ |
+void SkPDFDict::insertString(const char key[], const SkString& value) { |
+ this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value)); |
} |
-void SkPDFDict::mergeFrom(const SkPDFDict& other) { |
- for (int i = 0; i < other.fValue.count(); i++) { |
- *(fValue.append()) = |
- Rec(SkRef(other.fValue[i].key), SkRef(other.fValue[i].value)); |
+void SkPDFDict::clear() { |
+ for (Record& rec : fRecords) { |
+ rec.fKey.~SkPDFUnion(); |
+ rec.fValue.~SkPDFUnion(); |
} |
+ fRecords.reset(); |
} |
//////////////////////////////////////////////////////////////////////////////// |