1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 #include "SkPDFCatalog.h" 11 #include "SkPDFTypes.h" 12 #include "SkStream.h" 13 14 #ifdef SK_BUILD_FOR_WIN 15 #define SNPRINTF _snprintf 16 #else 17 #define SNPRINTF snprintf 18 #endif 19 20 SkPDFObject::SkPDFObject() {} 21 SkPDFObject::~SkPDFObject() {} 22 23 void SkPDFObject::emit(SkWStream* stream, SkPDFCatalog* catalog, 24 bool indirect) { 25 SkPDFObject* realObject = catalog->getSubstituteObject(this); 26 return realObject->emitObject(stream, catalog, indirect); 27 } 28 29 size_t SkPDFObject::getOutputSize(SkPDFCatalog* catalog, bool indirect) { 30 SkDynamicMemoryWStream buffer; 31 emit(&buffer, catalog, indirect); 32 return buffer.getOffset(); 33 } 34 35 void SkPDFObject::getResources(SkTDArray<SkPDFObject*>* resourceList) {} 36 37 void SkPDFObject::emitIndirectObject(SkWStream* stream, SkPDFCatalog* catalog) { 38 catalog->emitObjectNumber(stream, this); 39 stream->writeText(" obj\n"); 40 emit(stream, catalog, false); 41 stream->writeText("\nendobj\n"); 42 } 43 44 size_t SkPDFObject::getIndirectOutputSize(SkPDFCatalog* catalog) { 45 return catalog->getObjectNumberSize(this) + strlen(" obj\n") + 46 this->getOutputSize(catalog, false) + strlen("\nendobj\n"); 47 } 48 49 void SkPDFObject::AddResourceHelper(SkPDFObject* resource, 50 SkTDArray<SkPDFObject*>* list) { 51 list->push(resource); 52 resource->ref(); 53 } 54 55 void SkPDFObject::GetResourcesHelper(SkTDArray<SkPDFObject*>* resources, 56 SkTDArray<SkPDFObject*>* result) { 57 if (resources->count()) { 58 result->setReserve(result->count() + resources->count()); 59 for (int i = 0; i < resources->count(); i++) { 60 result->push((*resources)[i]); 61 (*resources)[i]->ref(); 62 (*resources)[i]->getResources(result); 63 } 64 } 65 } 66 67 SkPDFObjRef::SkPDFObjRef(SkPDFObject* obj) : fObj(obj) {} 68 SkPDFObjRef::~SkPDFObjRef() {} 69 70 void SkPDFObjRef::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 71 bool indirect) { 72 SkASSERT(!indirect); 73 catalog->emitObjectNumber(stream, fObj.get()); 74 stream->writeText(" R"); 75 } 76 77 size_t SkPDFObjRef::getOutputSize(SkPDFCatalog* catalog, bool indirect) { 78 SkASSERT(!indirect); 79 return catalog->getObjectNumberSize(fObj.get()) + strlen(" R"); 80 } 81 82 SkPDFInt::SkPDFInt(int32_t value) : fValue(value) {} 83 SkPDFInt::~SkPDFInt() {} 84 85 void SkPDFInt::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 86 bool indirect) { 87 if (indirect) { 88 return emitIndirectObject(stream, catalog); 89 } 90 stream->writeDecAsText(fValue); 91 } 92 93 SkPDFBool::SkPDFBool(bool value) : fValue(value) {} 94 SkPDFBool::~SkPDFBool() {} 95 96 void SkPDFBool::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 97 bool indirect) { 98 SkASSERT(!indirect); 99 if (fValue) { 100 stream->writeText("true"); 101 } else { 102 stream->writeText("false"); 103 } 104 } 105 106 size_t SkPDFBool::getOutputSize(SkPDFCatalog* catalog, bool indirect) { 107 SkASSERT(!indirect); 108 if (fValue) { 109 return strlen("true"); 110 } 111 return strlen("false"); 112 } 113 114 SkPDFScalar::SkPDFScalar(SkScalar value) : fValue(value) {} 115 SkPDFScalar::~SkPDFScalar() {} 116 117 void SkPDFScalar::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 118 bool indirect) { 119 if (indirect) { 120 return emitIndirectObject(stream, catalog); 121 } 122 123 Append(fValue, stream); 124 } 125 126 // static 127 void SkPDFScalar::Append(SkScalar value, SkWStream* stream) { 128 // The range of reals in PDF/A is the same as SkFixed: +/- 32,767 and 129 // +/- 1/65,536 (though integers can range from 2^31 - 1 to -2^31). 130 // When using floats that are outside the whole value range, we can use 131 // integers instead. 132 133 134 #if defined(SK_SCALAR_IS_FIXED) 135 stream->writeScalarAsText(value); 136 return; 137 #endif // SK_SCALAR_IS_FIXED 138 139 #if !defined(SK_ALLOW_LARGE_PDF_SCALARS) 140 if (value > 32767 || value < -32767) { 141 stream->writeDecAsText(SkScalarRound(value)); 142 return; 143 } 144 145 char buffer[SkStrAppendScalar_MaxSize]; 146 char* end = SkStrAppendFixed(buffer, SkScalarToFixed(value)); 147 stream->write(buffer, end - buffer); 148 return; 149 #endif // !SK_ALLOW_LARGE_PDF_SCALARS 150 151 #if defined(SK_SCALAR_IS_FLOAT) && defined(SK_ALLOW_LARGE_PDF_SCALARS) 152 // Floats have 24bits of significance, so anything outside that range is 153 // no more precise than an int. (Plus PDF doesn't support scientific 154 // notation, so this clamps to SK_Max/MinS32). 155 if (value > (1 << 24) || value < -(1 << 24)) { 156 stream->writeDecAsText(value); 157 return; 158 } 159 // Continue to enforce the PDF limits for small floats. 160 if (value < 1.0f/65536 && value > -1.0f/65536) { 161 stream->writeDecAsText(0); 162 return; 163 } 164 // SkStrAppendFloat might still use scientific notation, so use snprintf 165 // directly.. 166 static const int kFloat_MaxSize = 19; 167 char buffer[kFloat_MaxSize]; 168 int len = SNPRINTF(buffer, kFloat_MaxSize, "%#.8f", value); 169 // %f always prints trailing 0s, so strip them. 170 for (; buffer[len - 1] == '0' && len > 0; len--) { 171 buffer[len - 1] = '\0'; 172 } 173 if (buffer[len - 1] == '.') { 174 buffer[len - 1] = '\0'; 175 } 176 stream->writeText(buffer); 177 return; 178 #endif // SK_SCALAR_IS_FLOAT && SK_ALLOW_LARGE_PDF_SCALARS 179 } 180 181 SkPDFString::SkPDFString(const char value[]) 182 : fValue(FormatString(value, strlen(value))) { 183 } 184 185 SkPDFString::SkPDFString(const SkString& value) 186 : fValue(FormatString(value.c_str(), value.size())) { 187 } 188 189 SkPDFString::SkPDFString(const uint16_t* value, size_t len, bool wideChars) 190 : fValue(FormatString(value, len, wideChars)) { 191 } 192 193 SkPDFString::~SkPDFString() {} 194 195 void SkPDFString::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 196 bool indirect) { 197 if (indirect) 198 return emitIndirectObject(stream, catalog); 199 stream->write(fValue.c_str(), fValue.size()); 200 } 201 202 size_t SkPDFString::getOutputSize(SkPDFCatalog* catalog, bool indirect) { 203 if (indirect) 204 return getIndirectOutputSize(catalog); 205 return fValue.size(); 206 } 207 208 // static 209 SkString SkPDFString::FormatString(const char* input, size_t len) { 210 return DoFormatString(input, len, false, false); 211 } 212 213 SkString SkPDFString::FormatString(const uint16_t* input, size_t len, 214 bool wideChars) { 215 return DoFormatString(input, len, true, wideChars); 216 } 217 218 // static 219 SkString SkPDFString::DoFormatString(const void* input, size_t len, 220 bool wideInput, bool wideOutput) { 221 SkASSERT(len <= kMaxLen); 222 const uint16_t* win = (const uint16_t*) input; 223 const char* cin = (const char*) input; 224 225 if (wideOutput) { 226 SkASSERT(wideInput); 227 SkString result; 228 result.append("<"); 229 for (size_t i = 0; i < len; i++) { 230 result.appendHex(win[i], 4); 231 } 232 result.append(">"); 233 return result; 234 } 235 236 // 7-bit clean is a heuristic to decide what string format to use; 237 // a 7-bit clean string should require little escaping. 238 bool sevenBitClean = true; 239 for (size_t i = 0; i < len; i++) { 240 SkASSERT(!wideInput || !(win[i] & ~0xFF)); 241 char val = wideInput ? win[i] : cin[i]; 242 if (val > '~' || val < ' ') { 243 sevenBitClean = false; 244 break; 245 } 246 } 247 248 SkString result; 249 if (sevenBitClean) { 250 result.append("("); 251 for (size_t i = 0; i < len; i++) { 252 SkASSERT(!wideInput || !(win[i] & ~0xFF)); 253 char val = wideInput ? win[i] : cin[i]; 254 if (val == '\\' || val == '(' || val == ')') { 255 result.append("\\"); 256 } 257 result.append(&val, 1); 258 } 259 result.append(")"); 260 } else { 261 result.append("<"); 262 for (size_t i = 0; i < len; i++) { 263 SkASSERT(!wideInput || !(win[i] & ~0xFF)); 264 unsigned char val = wideInput ? win[i] : cin[i]; 265 result.appendHex(val, 2); 266 } 267 result.append(">"); 268 } 269 270 return result; 271 } 272 273 SkPDFName::SkPDFName(const char name[]) : fValue(FormatName(SkString(name))) {} 274 SkPDFName::SkPDFName(const SkString& name) : fValue(FormatName(name)) {} 275 SkPDFName::~SkPDFName() {} 276 277 bool SkPDFName::operator==(const SkPDFName& b) const { 278 return fValue == b.fValue; 279 } 280 281 void SkPDFName::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 282 bool indirect) { 283 SkASSERT(!indirect); 284 stream->write(fValue.c_str(), fValue.size()); 285 } 286 287 size_t SkPDFName::getOutputSize(SkPDFCatalog* catalog, bool indirect) { 288 SkASSERT(!indirect); 289 return fValue.size(); 290 } 291 292 // static 293 SkString SkPDFName::FormatName(const SkString& input) { 294 SkASSERT(input.size() <= kMaxLen); 295 296 SkString result("/"); 297 for (size_t i = 0; i < input.size(); i++) { 298 if (input[i] & 0x80 || input[i] < '!' || input[i] == '#') { 299 result.append("#"); 300 result.appendHex(input[i], 2); 301 } else { 302 result.append(input.c_str() + i, 1); 303 } 304 } 305 306 return result; 307 } 308 309 SkPDFArray::SkPDFArray() {} 310 SkPDFArray::~SkPDFArray() { 311 fValue.unrefAll(); 312 } 313 314 void SkPDFArray::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 315 bool indirect) { 316 if (indirect) { 317 return emitIndirectObject(stream, catalog); 318 } 319 320 stream->writeText("["); 321 for (int i = 0; i < fValue.count(); i++) { 322 fValue[i]->emit(stream, catalog, false); 323 if (i + 1 < fValue.count()) { 324 stream->writeText(" "); 325 } 326 } 327 stream->writeText("]"); 328 } 329 330 size_t SkPDFArray::getOutputSize(SkPDFCatalog* catalog, bool indirect) { 331 if (indirect) { 332 return getIndirectOutputSize(catalog); 333 } 334 335 size_t result = strlen("[]"); 336 if (fValue.count()) { 337 result += fValue.count() - 1; 338 } 339 for (int i = 0; i < fValue.count(); i++) { 340 result += fValue[i]->getOutputSize(catalog, false); 341 } 342 return result; 343 } 344 345 void SkPDFArray::reserve(int length) { 346 SkASSERT(length <= kMaxLen); 347 fValue.setReserve(length); 348 } 349 350 SkPDFObject* SkPDFArray::setAt(int offset, SkPDFObject* value) { 351 SkASSERT(offset < fValue.count()); 352 value->ref(); 353 fValue[offset]->unref(); 354 fValue[offset] = value; 355 return value; 356 } 357 358 SkPDFObject* SkPDFArray::append(SkPDFObject* value) { 359 SkASSERT(fValue.count() < kMaxLen); 360 value->ref(); 361 fValue.push(value); 362 return value; 363 } 364 365 void SkPDFArray::appendInt(int32_t value) { 366 SkASSERT(fValue.count() < kMaxLen); 367 fValue.push(new SkPDFInt(value)); 368 } 369 370 void SkPDFArray::appendScalar(SkScalar value) { 371 SkASSERT(fValue.count() < kMaxLen); 372 fValue.push(new SkPDFScalar(value)); 373 } 374 375 void SkPDFArray::appendName(const char name[]) { 376 SkASSERT(fValue.count() < kMaxLen); 377 fValue.push(new SkPDFName(name)); 378 } 379 380 /////////////////////////////////////////////////////////////////////////////// 381 382 SkPDFDict::SkPDFDict() {} 383 384 SkPDFDict::SkPDFDict(const char type[]) { 385 insertName("Type", type); 386 } 387 388 SkPDFDict::~SkPDFDict() { 389 clear(); 390 } 391 392 void SkPDFDict::emitObject(SkWStream* stream, SkPDFCatalog* catalog, 393 bool indirect) { 394 if (indirect) { 395 return emitIndirectObject(stream, catalog); 396 } 397 398 stream->writeText("<<"); 399 for (int i = 0; i < fValue.count(); i++) { 400 fValue[i].key->emitObject(stream, catalog, false); 401 stream->writeText(" "); 402 fValue[i].value->emit(stream, catalog, false); 403 stream->writeText("\n"); 404 } 405 stream->writeText(">>"); 406 } 407 408 size_t SkPDFDict::getOutputSize(SkPDFCatalog* catalog, bool indirect) { 409 if (indirect) { 410 return getIndirectOutputSize(catalog); 411 } 412 413 size_t result = strlen("<<>>") + (fValue.count() * 2); 414 for (int i = 0; i < fValue.count(); i++) { 415 result += fValue[i].key->getOutputSize(catalog, false); 416 result += fValue[i].value->getOutputSize(catalog, false); 417 } 418 return result; 419 } 420 421 SkPDFObject* SkPDFDict::insert(SkPDFName* key, SkPDFObject* value) { 422 key->ref(); 423 value->ref(); 424 struct Rec* newEntry = fValue.append(); 425 newEntry->key = key; 426 newEntry->value = value; 427 return value; 428 } 429 430 SkPDFObject* SkPDFDict::insert(const char key[], SkPDFObject* value) { 431 value->ref(); 432 struct Rec* newEntry = fValue.append(); 433 newEntry->key = new SkPDFName(key); 434 newEntry->value = value; 435 return value; 436 } 437 438 void SkPDFDict::insertInt(const char key[], int32_t value) { 439 struct Rec* newEntry = fValue.append(); 440 newEntry->key = new SkPDFName(key); 441 newEntry->value = new SkPDFInt(value); 442 } 443 444 void SkPDFDict::insertScalar(const char key[], SkScalar value) { 445 struct Rec* newEntry = fValue.append(); 446 newEntry->key = new SkPDFName(key); 447 newEntry->value = new SkPDFScalar(value); 448 } 449 450 void SkPDFDict::insertName(const char key[], const char name[]) { 451 struct Rec* newEntry = fValue.append(); 452 newEntry->key = new SkPDFName(key); 453 newEntry->value = new SkPDFName(name); 454 } 455 456 void SkPDFDict::clear() { 457 for (int i = 0; i < fValue.count(); i++) { 458 fValue[i].key->unref(); 459 fValue[i].value->unref(); 460 } 461 fValue.reset(); 462 } 463 464 SkPDFDict::Iter::Iter(const SkPDFDict& dict) 465 : fIter(dict.fValue.begin()), 466 fStop(dict.fValue.end()) { 467 } 468 469 SkPDFName* SkPDFDict::Iter::next(SkPDFObject** value) { 470 if (fIter != fStop) { 471 Rec* cur = fIter; 472 fIter++; 473 *value = cur->value; 474 return cur->key; 475 } 476 *value = NULL; 477 return NULL; 478 } 479