Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | |
| 10 #include "SkPDFTypes.h" | 9 #include "SkPDFTypes.h" |
| 11 #include "SkStream.h" | 10 #include "SkStream.h" |
| 12 | 11 |
| 13 #ifdef SK_BUILD_FOR_WIN | 12 #ifdef SK_BUILD_FOR_WIN |
| 14 #define SNPRINTF _snprintf | 13 #define SNPRINTF _snprintf |
| 15 #else | 14 #else |
| 16 #define SNPRINTF snprintf | 15 #define SNPRINTF snprintf |
| 17 #endif | 16 #endif |
| 18 | 17 |
| 19 //////////////////////////////////////////////////////////////////////////////// | 18 //////////////////////////////////////////////////////////////////////////////// |
| 20 | 19 |
| 21 SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) { | 20 SkString* pun(char* x) { return reinterpret_cast<SkString*>(x); } |
| 22 SkSafeRef(obj); | 21 const SkString* pun(const char* x) { |
| 23 } | 22 return reinterpret_cast<const SkString*>(x); |
| 24 | 23 } |
| 25 SkPDFObjRef::~SkPDFObjRef() {} | 24 |
| 26 | 25 SkPDFUnion::SkPDFUnion(Type t) : fType(t) {} |
| 27 void SkPDFObjRef::emitObject(SkWStream* stream, | 26 |
| 28 const SkPDFObjNumMap& objNumMap, | 27 SkPDFUnion::~SkPDFUnion() { |
| 29 const SkPDFSubstituteMap& substitutes) { | 28 switch (fType) { |
| 30 SkPDFObject* obj = substitutes.getSubstitute(fObj); | 29 case Type::kNameSkS: |
| 31 stream->writeDecAsText(objNumMap.getObjectNumber(obj)); | 30 case Type::kStringSkS: |
| 32 stream->writeText(" 0 R"); // Generation number is always 0. | 31 pun(fSkString)->~SkString(); |
| 33 } | 32 return; |
| 34 | 33 case Type::kObjRef: |
| 35 void SkPDFObjRef::addResources(SkPDFObjNumMap* catalog, | 34 case Type::kObject: |
| 36 const SkPDFSubstituteMap& substitutes) const { | 35 SkSafeUnref(fObject); |
| 37 SkPDFObject* obj = substitutes.getSubstitute(fObj); | 36 return; |
| 38 SkASSERT(obj); | 37 default: |
| 39 if (catalog->addObject(obj)) { | 38 return; |
| 40 obj->addResources(catalog, substitutes); | 39 } |
| 41 } | 40 } |
| 41 | |
| 42 SkPDFUnion& SkPDFUnion::operator=(SkPDFUnion&& other) { | |
| 43 if (this != &other) { | |
|
tomhudson
2015/04/24 21:32:29
Never worked with && before, so I'm assuming you'v
hal.canary
2015/04/24 21:51:46
It is not isomorphic to **.
This is C++11 notatio
| |
| 44 this->~SkPDFUnion(); | |
| 45 SkNEW_PLACEMENT_ARGS(this, SkPDFUnion, (other.move())); | |
| 46 } | |
| 47 return *this; | |
| 48 } | |
| 49 | |
| 50 SkPDFUnion::SkPDFUnion(SkPDFUnion&& other) { | |
| 51 SkASSERT(this != &other); | |
| 52 memcpy(this, &other, sizeof(*this)); | |
| 53 other.fType = Type::kDestroyed; | |
| 54 } | |
| 55 | |
| 56 #if 0 | |
| 57 SkPDFUnion SkPDFUnion::copy() const { | |
| 58 SkPDFUnion u(fType); | |
| 59 memcpy(&u, this, sizeof(u)); | |
| 60 switch (fType) { | |
| 61 case Type::kNameSkS: | |
| 62 case Type::kStringSkS: | |
| 63 SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, | |
| 64 (*pun(fSkString))); | |
| 65 return u.move(); | |
| 66 case Type::kObjRef: | |
| 67 case Type::kObject: | |
| 68 SkRef(u.fObject); | |
| 69 return u.move(); | |
| 70 default: | |
| 71 return u.move(); | |
| 72 } | |
| 73 } | |
| 74 SkPDFUnion& SkPDFUnion::operator=(const SkPDFUnion& other) { | |
| 75 return *this = other.copy(); | |
| 76 } | |
| 77 SkPDFUnion::SkPDFUnion(const SkPDFUnion& other) { | |
| 78 *this = other.copy(); | |
| 79 } | |
| 80 #endif | |
| 81 | |
| 82 bool SkPDFUnion::isName() const { | |
| 83 return Type::kName == fType || Type::kNameSkS == fType; | |
| 84 } | |
| 85 | |
| 86 bool SkPDFUnion::IsValidName(const char* n) { | |
| 87 static const char kControlChars[] = "/%()<>[]{}"; | |
| 88 while (*n) { | |
| 89 if (*n < '!' || *n > '~' || strchr(kControlChars, *n)) { | |
| 90 return false; | |
| 91 } | |
| 92 ++n; | |
| 93 } | |
| 94 return true; | |
| 95 } | |
| 96 | |
| 97 SkString SkPDFUnion::EscapeName(const char* name, size_t len) { | |
| 98 static const char kToEscape[] = "#/%()<>[]{}"; | |
| 99 int count = 0; | |
| 100 const char* const end = &name[len]; | |
| 101 for (const char* n = name; n != end; ++n) { | |
| 102 if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) { | |
| 103 count += 2; | |
| 104 } | |
| 105 ++count; | |
| 106 } | |
| 107 SkString result(count); | |
| 108 char* s = result.writable_str(); | |
| 109 static const char kHex[] = "0123456789ABCDEF"; | |
| 110 for (const char* n = name; n != end; ++n) { | |
| 111 if (*n < '!' || *n > '~' || strchr(kToEscape, *n)) { | |
| 112 *s++ = '#'; | |
| 113 *s++ = kHex[(*n >> 4) & 0xF]; | |
| 114 *s++ = kHex[*n & 0xF]; | |
| 115 } else { | |
| 116 *s++ = *n; | |
| 117 } | |
| 118 } | |
| 119 SkASSERT(&result.writable_str()[count] == s); // don't over-write | |
| 120 return result; // allocated space | |
| 121 } | |
| 122 | |
| 123 static void write_string(SkWStream* o, const SkString& s) { | |
| 124 o->write(s.c_str(), s.size()); | |
| 125 } | |
| 126 | |
| 127 static SkString format_string(const SkString& s) { | |
| 128 return SkPDFString::FormatString(s.c_str(), s.size()); | |
| 129 } | |
| 130 | |
| 131 static SkString format_string(const char* s) { | |
| 132 return SkPDFString::FormatString(s, strlen(s)); | |
| 133 } | |
| 134 | |
| 135 SkString escape_name(const SkString& name) { | |
| 136 return SkPDFUnion::EscapeName(name.c_str(), name.size()); | |
| 137 } | |
| 138 | |
| 139 void SkPDFUnion::emitObject(SkWStream* stream, | |
| 140 const SkPDFObjNumMap& objNumMap, | |
| 141 const SkPDFSubstituteMap& substitutes) const { | |
| 142 switch (fType) { | |
| 143 case Type::kInt: | |
| 144 stream->writeDecAsText(fIntValue); | |
| 145 return; | |
| 146 case Type::kBool: | |
| 147 stream->writeText(fBoolValue ? "true" : "false"); | |
| 148 return; | |
| 149 case Type::kScalar: | |
| 150 SkPDFScalar::Append(fScalarValue, stream); | |
| 151 return; | |
| 152 case Type::kName: | |
| 153 stream->writeText("/"); | |
| 154 SkASSERT(SkPDFUnion::IsValidName(fStaticString)); | |
| 155 stream->writeText(fStaticString); | |
| 156 return; | |
| 157 case Type::kString: | |
| 158 SkASSERT(fStaticString); | |
| 159 write_string(stream, format_string(fStaticString)); | |
| 160 return; | |
| 161 case Type::kNameSkS: | |
| 162 stream->writeText("/"); | |
| 163 write_string(stream, escape_name(*pun(fSkString))); | |
| 164 return; | |
| 165 case Type::kStringSkS: | |
| 166 write_string(stream, format_string(*pun(fSkString))); | |
| 167 return; | |
| 168 case Type::kObjRef: | |
| 169 stream->writeDecAsText(objNumMap.getObjectNumber( | |
| 170 substitutes.getSubstitute(fObject))); | |
| 171 stream->writeText(" 0 R"); // Generation number is always 0. | |
| 172 return; | |
| 173 case Type::kObject: | |
| 174 fObject->emitObject(stream, objNumMap, substitutes); | |
| 175 return; | |
| 176 default: | |
| 177 SkDEBUGFAIL("SkPDFUnion::emitObject with bad type"); | |
| 178 } | |
| 179 } | |
| 180 | |
| 181 void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap, | |
| 182 const SkPDFSubstituteMap& substituteMap) const { | |
| 183 switch (fType) { | |
| 184 case Type::kInt: | |
| 185 case Type::kBool: | |
| 186 case Type::kScalar: | |
| 187 case Type::kName: | |
| 188 case Type::kString: | |
| 189 case Type::kNameSkS: | |
| 190 case Type::kStringSkS: | |
| 191 return; // These have no resources. | |
| 192 case Type::kObjRef: { | |
| 193 SkPDFObject* obj = substituteMap.getSubstitute(fObject); | |
| 194 if (objNumMap->addObject(obj)) { | |
| 195 obj->addResources(objNumMap, substituteMap); | |
| 196 } | |
| 197 return; | |
| 198 } | |
| 199 case Type::kObject: | |
| 200 fObject->addResources(objNumMap, substituteMap); | |
| 201 return; | |
| 202 default: | |
| 203 SkDEBUGFAIL("SkPDFUnion::addResources with bad type"); | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 SkPDFUnion SkPDFUnion::Int(int32_t value) { | |
| 208 SkPDFUnion u(Type::kInt); | |
| 209 u.fIntValue = value; | |
| 210 return u.move(); | |
| 211 } | |
| 212 | |
| 213 SkPDFUnion SkPDFUnion::Bool(bool value) { | |
| 214 SkPDFUnion u(Type::kBool); | |
| 215 u.fBoolValue = value; | |
| 216 return u.move(); | |
| 217 } | |
| 218 | |
| 219 SkPDFUnion SkPDFUnion::Scalar(SkScalar value) { | |
| 220 SkPDFUnion u(Type::kScalar); | |
| 221 u.fScalarValue = value; | |
| 222 return u.move(); | |
| 223 } | |
| 224 | |
| 225 SkPDFUnion SkPDFUnion::Name(const char* value) { | |
| 226 SkPDFUnion u(Type::kName); | |
| 227 SkASSERT(value); | |
| 228 SkASSERT(SkPDFUnion::IsValidName(value)); | |
| 229 u.fStaticString = value; | |
| 230 return u.move(); | |
| 231 } | |
| 232 | |
| 233 SkPDFUnion SkPDFUnion::String(const char* value) { | |
| 234 SkPDFUnion u(Type::kString); | |
| 235 SkASSERT(value); | |
| 236 u.fStaticString = value; | |
| 237 return u.move(); | |
| 238 } | |
| 239 | |
| 240 SkPDFUnion SkPDFUnion::Name(const SkString& s) { | |
| 241 SkPDFUnion u(Type::kNameSkS); | |
| 242 SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, (s)); | |
| 243 return u.move(); | |
| 244 } | |
| 245 | |
| 246 SkPDFUnion SkPDFUnion::String(const SkString& s) { | |
| 247 SkPDFUnion u(Type::kStringSkS); | |
| 248 SkNEW_PLACEMENT_ARGS(pun(u.fSkString), SkString, (s)); | |
| 249 return u.move(); | |
| 250 } | |
| 251 | |
| 252 SkPDFUnion SkPDFUnion::ObjRef(SkPDFObject* ptr) { | |
| 253 SkPDFUnion u(Type::kObjRef); | |
| 254 SkASSERT(ptr); | |
| 255 u.fObject = ptr; | |
| 256 return u.move(); | |
| 257 } | |
| 258 | |
| 259 SkPDFUnion SkPDFUnion::Object(SkPDFObject* ptr) { | |
| 260 SkPDFUnion u(Type::kObject); | |
| 261 SkASSERT(ptr); | |
| 262 u.fObject = ptr; | |
| 263 return u.move(); | |
| 42 } | 264 } |
| 43 | 265 |
| 44 //////////////////////////////////////////////////////////////////////////////// | 266 //////////////////////////////////////////////////////////////////////////////// |
| 45 | 267 |
| 46 SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {} | 268 void SkPDFAtom::emitObject(SkWStream* stream, |
| 47 SkPDFInt::~SkPDFInt() {} | 269 const SkPDFObjNumMap& objNumMap, |
| 48 | 270 const SkPDFSubstituteMap& substitutes) { |
| 49 void SkPDFInt::emitObject(SkWStream* stream, | 271 fValue.emitObject(stream, objNumMap, substitutes); |
| 50 const SkPDFObjNumMap&, | 272 } |
| 51 const SkPDFSubstituteMap&) { | 273 void SkPDFAtom::addResources(SkPDFObjNumMap* map, |
| 52 stream->writeDecAsText(fValue); | 274 const SkPDFSubstituteMap& substitutes) const { |
| 275 fValue.addResources(map, substitutes); | |
| 53 } | 276 } |
| 54 | 277 |
| 55 //////////////////////////////////////////////////////////////////////////////// | 278 //////////////////////////////////////////////////////////////////////////////// |
| 56 | 279 |
| 57 SkPDFBool::SkPDFBool(bool value) : fValue(value) {} | |
| 58 SkPDFBool::~SkPDFBool() {} | |
| 59 | |
| 60 void SkPDFBool::emitObject(SkWStream* stream, | |
| 61 const SkPDFObjNumMap&, | |
| 62 const SkPDFSubstituteMap&) { | |
| 63 stream->writeText(fValue ? "true" : "false"); | |
| 64 } | |
| 65 | |
| 66 //////////////////////////////////////////////////////////////////////////////// | |
| 67 | |
| 68 SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {} | |
| 69 SkPDFScalar::~SkPDFScalar() {} | |
| 70 | |
| 71 void SkPDFScalar::emitObject(SkWStream* stream, | |
| 72 const SkPDFObjNumMap&, | |
| 73 const SkPDFSubstituteMap&) { | |
| 74 SkPDFScalar::Append(fValue, stream); | |
| 75 } | |
| 76 | |
| 77 // static | 280 // static |
| 78 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { | 281 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { |
| 79 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and | 282 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and |
| 80 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31). | 283 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31). |
| 81 // When using floats that are outside the whole value range, we can use | 284 // When using floats that are outside the whole value range, we can use |
| 82 // integers instead. | 285 // integers instead. |
| 83 | 286 |
| 84 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS) | 287 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS) |
| 85 if (value > 32767 || value < -32767) { | 288 if (value > 32767 || value < -32767) { |
| 86 stream->writeDecAsText(SkScalarRoundToInt(value)); | 289 stream->writeDecAsText(SkScalarRoundToInt(value)); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 if (buffer[len - 1] == '.') { | 321 if (buffer[len - 1] == '.') { |
| 119 buffer[len - 1] = '\0'; | 322 buffer[len - 1] = '\0'; |
| 120 } | 323 } |
| 121 stream->writeText(buffer); | 324 stream->writeText(buffer); |
| 122 return; | 325 return; |
| 123 #endif // SK_ALLOW_LARGE_PDF_SCALARS | 326 #endif // SK_ALLOW_LARGE_PDF_SCALARS |
| 124 } | 327 } |
| 125 | 328 |
| 126 //////////////////////////////////////////////////////////////////////////////// | 329 //////////////////////////////////////////////////////////////////////////////// |
| 127 | 330 |
| 128 SkPDFString::SkPDFString(const char value[]) | 331 // static |
| 129 : fValue(FormatString(value, strlen(value))) { | |
| 130 } | |
| 131 | 332 |
| 132 SkPDFString::SkPDFString(const SkString& value) | |
| 133 : fValue(FormatString(value.c_str(), value.size())) { | |
| 134 } | |
| 135 | |
| 136 SkPDFString::~SkPDFString() {} | |
| 137 | |
| 138 void SkPDFString::emitObject(SkWStream* stream, | |
| 139 const SkPDFObjNumMap&, | |
| 140 const SkPDFSubstituteMap&) { | |
| 141 stream->write(fValue.c_str(), fValue.size()); | |
| 142 } | |
| 143 | |
| 144 // static | |
| 145 SkString SkPDFString::FormatString(const char* cin, size_t len) { | 333 SkString SkPDFString::FormatString(const char* cin, size_t len) { |
| 146 SkASSERT(len <= kMaxLen); | 334 SkASSERT(len <= kMaxLen); |
| 147 | 335 |
| 148 // 7-bit clean is a heuristic to decide what string format to use; | 336 // 7-bit clean is a heuristic to decide what string format to use; |
| 149 // a 7-bit clean string should require little escaping. | 337 // a 7-bit clean string should require little escaping. |
| 150 bool sevenBitClean = true; | 338 bool sevenBitClean = true; |
| 151 size_t characterCount = 2 + len; | 339 size_t characterCount = 2 + len; |
| 152 for (size_t i = 0; i < len; i++) { | 340 for (size_t i = 0; i < len; i++) { |
| 153 if (cin[i] > '~' || cin[i] < ' ') { | 341 if (cin[i] > '~' || cin[i] < ' ') { |
| 154 sevenBitClean = false; | 342 sevenBitClean = false; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 180 *str++ = gHex[(c >> 4) & 0xF]; | 368 *str++ = gHex[(c >> 4) & 0xF]; |
| 181 *str++ = gHex[(c ) & 0xF]; | 369 *str++ = gHex[(c ) & 0xF]; |
| 182 } | 370 } |
| 183 *str++ = '>'; | 371 *str++ = '>'; |
| 184 } | 372 } |
| 185 return result; | 373 return result; |
| 186 } | 374 } |
| 187 | 375 |
| 188 //////////////////////////////////////////////////////////////////////////////// | 376 //////////////////////////////////////////////////////////////////////////////// |
| 189 | 377 |
| 190 SkPDFName::SkPDFName(const char name[]) : fValue(FormatName(SkString(name))) {} | |
| 191 SkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {} | |
| 192 SkPDFName::~SkPDFName() {} | |
| 193 | |
| 194 bool SkPDFName::operator==(const SkPDFName& b) const { | |
| 195 return fValue == b.fValue; | |
| 196 } | |
| 197 | |
| 198 void SkPDFName::emitObject(SkWStream* stream, | |
| 199 const SkPDFObjNumMap&, | |
| 200 const SkPDFSubstituteMap&) { | |
| 201 stream->write(fValue.c_str(), fValue.size()); | |
| 202 } | |
| 203 | |
| 204 // static | |
| 205 SkString SkPDFName::FormatName(const SkString& input) { | |
| 206 SkASSERT(input.size() <= kMaxLen); | |
| 207 // TODO(vandebo) If more escaping is needed, improve the linear scan. | |
| 208 static const char escaped[] = "#/%()<>[]{}"; | |
| 209 | |
| 210 SkString result("/"); | |
| 211 for (size_t i = 0; i < input.size(); i++) { | |
| 212 if (input[i] & 0x80 || input[i] < '!' || strchr(escaped, input[i])) { | |
| 213 result.append("#"); | |
| 214 // Mask with 0xFF to avoid sign extension. i.e. #FFFFFF81 | |
| 215 result.appendHex(input[i] & 0xFF, 2); | |
| 216 } else { | |
| 217 result.append(input.c_str() + i, 1); | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 return result; | |
| 222 } | |
| 223 | |
| 224 //////////////////////////////////////////////////////////////////////////////// | |
| 225 | |
| 226 SkPDFArray::SkPDFArray() {} | 378 SkPDFArray::SkPDFArray() {} |
| 227 SkPDFArray::~SkPDFArray() { | 379 SkPDFArray::~SkPDFArray() { |
| 228 fValue.unrefAll(); | 380 for (SkPDFUnion& value : fValues) { |
| 381 value.~SkPDFUnion(); | |
| 382 } | |
| 383 fValues.reset(); | |
| 229 } | 384 } |
| 230 | 385 |
| 386 int SkPDFArray::size() const { return fValues.count(); } | |
| 387 | |
| 388 void SkPDFArray::reserve(int length) { fValues.setReserve(length); } | |
| 389 | |
| 231 void SkPDFArray::emitObject(SkWStream* stream, | 390 void SkPDFArray::emitObject(SkWStream* stream, |
| 232 const SkPDFObjNumMap& objNumMap, | 391 const SkPDFObjNumMap& objNumMap, |
| 233 const SkPDFSubstituteMap& substitutes) { | 392 const SkPDFSubstituteMap& substitutes) { |
| 234 stream->writeText("["); | 393 stream->writeText("["); |
| 235 for (int i = 0; i < fValue.count(); i++) { | 394 for (int i = 0; i < fValues.count(); i++) { |
| 236 SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); | 395 fValues[i].emitObject(stream, objNumMap, substitutes); |
|
tomhudson
2015/04/24 21:32:29
Not worth maintaining this invariant?
hal.canary
2015/04/25 13:41:02
Only top level objects (referred to via ObjRefs) s
| |
| 237 fValue[i]->emitObject(stream, objNumMap, substitutes); | 396 if (i + 1 < fValues.count()) { |
| 238 if (i + 1 < fValue.count()) { | |
| 239 stream->writeText(" "); | 397 stream->writeText(" "); |
| 240 } | 398 } |
| 241 } | 399 } |
| 242 stream->writeText("]"); | 400 stream->writeText("]"); |
| 243 } | 401 } |
| 244 | 402 |
| 245 void SkPDFArray::addResources(SkPDFObjNumMap* catalog, | 403 void SkPDFArray::addResources(SkPDFObjNumMap* catalog, |
| 246 const SkPDFSubstituteMap& substitutes) const { | 404 const SkPDFSubstituteMap& substitutes) const { |
| 247 for (int i = 0; i < fValue.count(); i++) { | 405 for (const SkPDFUnion& value : fValues) { |
| 248 SkASSERT(substitutes.getSubstitute(fValue[i]) == fValue[i]); | 406 value.addResources(catalog, substitutes); |
| 249 fValue[i]->addResources(catalog, substitutes); | |
| 250 } | 407 } |
| 251 } | 408 } |
| 252 | 409 |
| 253 void SkPDFArray::reserve(int length) { | 410 // void SkPDFArray::append(const SkPDFUnion& value) { |
| 254 SkASSERT(length <= kMaxLen); | 411 // SkNEW_PLACEMENT_ARGS(fValues.append(), SkPDFUnion, (value)); |
| 255 fValue.setReserve(length); | 412 // } |
|
tomhudson
2015/04/24 21:32:29
Commented out code - delete?
hal.canary
2015/04/25 13:41:02
Done.
| |
| 413 | |
| 414 void SkPDFArray::append(SkPDFUnion&& value) { | |
| 415 SkNEW_PLACEMENT_ARGS(fValues.append(), SkPDFUnion, (value.move())); | |
| 256 } | 416 } |
| 257 | 417 |
| 258 SkPDFObject* SkPDFArray::append(SkPDFObject* value) { | 418 SkPDFObject* SkPDFArray::append(SkPDFObject* value) { |
| 259 SkASSERT(fValue.count() < kMaxLen); | 419 // DEPRECATED |
| 260 value->ref(); | 420 this->append(SkPDFUnion::Object(SkRef(value))); |
| 261 fValue.push(value); | |
| 262 return value; | 421 return value; |
| 263 } | 422 } |
| 264 | 423 |
| 265 void SkPDFArray::appendInt(int32_t value) { | 424 void SkPDFArray::appendInt(int32_t value) { |
| 266 SkASSERT(fValue.count() < kMaxLen); | 425 this->append(SkPDFUnion::Int(value)); |
| 267 fValue.push(new SkPDFInt(value)); | 426 } |
| 427 | |
| 428 void SkPDFArray::appendBool(bool value) { | |
| 429 this->append(SkPDFUnion::Bool(value)); | |
| 268 } | 430 } |
| 269 | 431 |
| 270 void SkPDFArray::appendScalar(SkScalar value) { | 432 void SkPDFArray::appendScalar(SkScalar value) { |
| 271 SkASSERT(fValue.count() < kMaxLen); | 433 this->append(SkPDFUnion::Scalar(value)); |
| 272 fValue.push(new SkPDFScalar(value)); | |
| 273 } | 434 } |
| 274 | 435 |
| 275 void SkPDFArray::appendName(const char name[]) { | 436 void SkPDFArray::appendName(const char name[]) { |
| 276 SkASSERT(fValue.count() < kMaxLen); | 437 this->append(SkPDFUnion::Name(SkString(name))); |
| 277 fValue.push(new SkPDFName(name)); | 438 } |
| 439 | |
| 440 void SkPDFArray::appendName(const SkString& name) { | |
| 441 this->append(SkPDFUnion::Name(name)); | |
| 442 } | |
| 443 | |
| 444 void SkPDFArray::appendString(const SkString& value) { | |
| 445 this->append(SkPDFUnion::String(value)); | |
| 446 } | |
| 447 | |
| 448 void SkPDFArray::appendString(const char value[]) { | |
| 449 this->append(SkPDFUnion::String(value)); | |
| 450 } | |
| 451 | |
| 452 void SkPDFArray::appendObject(SkPDFObject* value) { | |
| 453 this->append(SkPDFUnion::Object(value)); | |
| 454 } | |
| 455 | |
| 456 void SkPDFArray::appendObjRef(SkPDFObject* value) { | |
| 457 this->append(SkPDFUnion::ObjRef(value)); | |
| 278 } | 458 } |
| 279 | 459 |
| 280 /////////////////////////////////////////////////////////////////////////////// | 460 /////////////////////////////////////////////////////////////////////////////// |
| 281 | 461 |
| 282 SkPDFDict::SkPDFDict() {} | 462 SkPDFDict::SkPDFDict() {} |
| 283 | 463 |
| 284 SkPDFDict::SkPDFDict(const char type[]) { | 464 SkPDFDict::~SkPDFDict() { this->clear(); } |
| 285 insertName("Type", type); | |
| 286 } | |
| 287 | 465 |
| 288 SkPDFDict::~SkPDFDict() { | 466 SkPDFDict::SkPDFDict(const char type[]) { this->insertName("Type", type); } |
| 289 clear(); | |
| 290 } | |
| 291 | |
| 292 int SkPDFDict::size() const { | |
| 293 return fValue.count(); | |
| 294 } | |
| 295 | 467 |
| 296 void SkPDFDict::emitObject(SkWStream* stream, | 468 void SkPDFDict::emitObject(SkWStream* stream, |
| 297 const SkPDFObjNumMap& objNumMap, | 469 const SkPDFObjNumMap& objNumMap, |
| 298 const SkPDFSubstituteMap& substitutes) { | 470 const SkPDFSubstituteMap& substitutes) { |
| 299 stream->writeText("<<"); | 471 stream->writeText("<<"); |
| 300 for (int i = 0; i < fValue.count(); i++) { | 472 for (int i = 0; i < fRecords.count(); i++) { |
| 301 SkASSERT(fValue[i].key); | 473 fRecords[i].fKey.emitObject(stream, objNumMap, substitutes); |
| 302 SkASSERT(fValue[i].value); | |
| 303 SkASSERT(substitutes.getSubstitute(fValue[i].key) == fValue[i].key); | |
| 304 SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value); | |
| 305 fValue[i].key->emitObject(stream, objNumMap, substitutes); | |
| 306 stream->writeText(" "); | 474 stream->writeText(" "); |
| 307 fValue[i].value->emitObject(stream, objNumMap, substitutes); | 475 fRecords[i].fValue.emitObject(stream, objNumMap, substitutes); |
| 308 if (i + 1 < fValue.count()) { | 476 if (i + 1 < fRecords.count()) { |
| 309 stream->writeText("\n"); | 477 stream->writeText("\n"); |
| 310 } | 478 } |
| 311 } | 479 } |
| 312 stream->writeText(">>"); | 480 stream->writeText(">>"); |
| 313 } | 481 } |
| 314 | 482 |
| 315 void SkPDFDict::addResources(SkPDFObjNumMap* catalog, | 483 void SkPDFDict::addResources(SkPDFObjNumMap* catalog, |
| 316 const SkPDFSubstituteMap& substitutes) const { | 484 const SkPDFSubstituteMap& substitutes) const { |
| 317 for (int i = 0; i < fValue.count(); i++) { | 485 for (int i = 0; i < fRecords.count(); i++) { |
| 318 SkASSERT(fValue[i].key); | 486 fRecords[i].fKey.addResources(catalog, substitutes); |
| 319 SkASSERT(fValue[i].value); | 487 fRecords[i].fValue.addResources(catalog, substitutes); |
| 320 fValue[i].key->addResources(catalog, substitutes); | |
| 321 SkASSERT(substitutes.getSubstitute(fValue[i].value) == fValue[i].value); | |
| 322 fValue[i].value->addResources(catalog, substitutes); | |
| 323 } | 488 } |
| 324 } | 489 } |
| 325 | 490 |
| 326 SkPDFObject* SkPDFDict::append(SkPDFName* key, SkPDFObject* value) { | 491 void SkPDFDict::set(SkPDFUnion&& name, SkPDFUnion&& value) { |
| 327 SkASSERT(key); | 492 Record* rec = fRecords.append(); |
| 328 SkASSERT(value); | 493 SkASSERT(name.isName()); |
| 329 *(fValue.append()) = Rec(key, value); | 494 SkNEW_PLACEMENT_ARGS(&rec->fKey, SkPDFUnion, (name.move())); |
| 495 SkNEW_PLACEMENT_ARGS(&rec->fValue, SkPDFUnion, (value.move())); | |
| 496 } | |
| 497 | |
| 498 int SkPDFDict::size() const { return fRecords.count(); } | |
| 499 | |
| 500 void SkPDFDict::insertObjRef(const char key[], SkPDFObject* value) { | |
| 501 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value)); | |
| 502 } | |
| 503 void SkPDFDict::insertObjRef(const SkString& key, SkPDFObject* value) { | |
| 504 this->set(SkPDFUnion::Name(key), SkPDFUnion::ObjRef(value)); | |
| 505 } | |
| 506 | |
| 507 void SkPDFDict::insertObject(const char key[], SkPDFObject* value) { | |
| 508 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value)); | |
| 509 } | |
| 510 void SkPDFDict::insertObject(const SkString& key, SkPDFObject* value) { | |
| 511 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(value)); | |
| 512 } | |
| 513 | |
| 514 // DEPRECATED | |
| 515 SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) { | |
| 516 this->set(SkPDFUnion::Name(key), SkPDFUnion::Object(SkRef(value))); | |
| 330 return value; | 517 return value; |
| 331 } | 518 } |
| 332 | 519 |
| 333 SkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) { | 520 void SkPDFDict::insertInt(const char key[], int32_t value) { |
| 334 return this->append(SkRef(key), SkRef(value)); | 521 this->set(SkPDFUnion::Name(key), SkPDFUnion::Int(value)); |
| 335 } | 522 } |
| 336 | 523 |
| 337 SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) { | 524 void SkPDFDict::insertInt(const char key[], size_t value) { |
| 338 return this->append(new SkPDFName(key), SkRef(value)); | 525 this->insertInt(key, SkToS32(value)); |
| 339 } | |
| 340 | |
| 341 void SkPDFDict::insertInt(const char key[], int32_t value) { | |
| 342 (void)this->append(new SkPDFName(key), new SkPDFInt(value)); | |
| 343 } | 526 } |
| 344 | 527 |
| 345 void SkPDFDict::insertScalar(const char key[], SkScalar value) { | 528 void SkPDFDict::insertScalar(const char key[], SkScalar value) { |
| 346 (void)this->append(new SkPDFName(key), new SkPDFScalar(value)); | 529 this->set(SkPDFUnion::Name(key), SkPDFUnion::Scalar(value)); |
| 347 } | 530 } |
| 348 | 531 |
| 349 void SkPDFDict::insertName(const char key[], const char name[]) { | 532 void SkPDFDict::insertName(const char key[], const char name[]) { |
| 350 (void)this->append(new SkPDFName(key), new SkPDFName(name)); | 533 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name)); |
| 534 } | |
| 535 | |
| 536 void SkPDFDict::insertName(const char key[], const SkString& name) { | |
| 537 this->set(SkPDFUnion::Name(key), SkPDFUnion::Name(name)); | |
| 538 } | |
| 539 | |
| 540 void SkPDFDict::insertString(const char key[], const char value[]) { | |
| 541 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value)); | |
| 542 } | |
| 543 | |
| 544 void SkPDFDict::insertString(const char key[], const SkString& value) { | |
| 545 this->set(SkPDFUnion::Name(key), SkPDFUnion::String(value)); | |
| 351 } | 546 } |
| 352 | 547 |
| 353 void SkPDFDict::clear() { | 548 void SkPDFDict::clear() { |
| 354 for (int i = 0; i < fValue.count(); i++) { | 549 for (Record& rec : fRecords) { |
| 355 SkASSERT(fValue[i].key); | 550 rec.fKey.~SkPDFUnion(); |
| 356 SkASSERT(fValue[i].value); | 551 rec.fValue.~SkPDFUnion(); |
| 357 fValue[i].key->unref(); | |
| 358 fValue[i].value->unref(); | |
| 359 } | 552 } |
| 360 fValue.reset(); | 553 fRecords.reset(); |
| 361 } | |
| 362 | |
| 363 void SkPDFDict::remove(const char key[]) { | |
| 364 SkASSERT(key); | |
| 365 SkPDFName name(key); | |
| 366 for (int i = 0; i < fValue.count(); i++) { | |
| 367 SkASSERT(fValue[i].key); | |
| 368 if (*(fValue[i].key) == name) { | |
| 369 fValue[i].key->unref(); | |
| 370 SkASSERT(fValue[i].value); | |
| 371 fValue[i].value->unref(); | |
| 372 fValue.removeShuffle(i); | |
| 373 return; | |
| 374 } | |
| 375 } | |
| 376 } | |
| 377 | |
| 378 void SkPDFDict::mergeFrom(const SkPDFDict& other) { | |
| 379 for (int i = 0; i < other.fValue.count(); i++) { | |
| 380 *(fValue.append()) = | |
| 381 Rec(SkRef(other.fValue[i].key), SkRef(other.fValue[i].value)); | |
| 382 } | |
| 383 } | 554 } |
| 384 | 555 |
| 385 //////////////////////////////////////////////////////////////////////////////// | 556 //////////////////////////////////////////////////////////////////////////////// |
| 386 | 557 |
| 387 SkPDFSubstituteMap::~SkPDFSubstituteMap() { | 558 SkPDFSubstituteMap::~SkPDFSubstituteMap() { |
| 388 fSubstituteMap.foreach( | 559 fSubstituteMap.foreach( |
| 389 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); }); | 560 [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); }); |
| 390 } | 561 } |
| 391 | 562 |
| 392 void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original, | 563 void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original, |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 411 fObjects.push(obj); | 582 fObjects.push(obj); |
| 412 return true; | 583 return true; |
| 413 } | 584 } |
| 414 | 585 |
| 415 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { | 586 int32_t SkPDFObjNumMap::getObjectNumber(SkPDFObject* obj) const { |
| 416 int32_t* objectNumberFound = fObjectNumbers.find(obj); | 587 int32_t* objectNumberFound = fObjectNumbers.find(obj); |
| 417 SkASSERT(objectNumberFound); | 588 SkASSERT(objectNumberFound); |
| 418 return *objectNumberFound; | 589 return *objectNumberFound; |
| 419 } | 590 } |
| 420 | 591 |
| OLD | NEW |