| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkCanvas.h" | 8 #include "SkCanvas.h" |
| 9 #include "SkDevice.h" | 9 #include "SkDevice.h" |
| 10 #include "SkForceLinking.h" | 10 #include "SkForceLinking.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 // TODO(edisonn): tool, show what objects were read at least, show the ones not
even read | 31 // TODO(edisonn): tool, show what objects were read at least, show the ones not
even read |
| 32 // keep for each object pos in file | 32 // keep for each object pos in file |
| 33 // plug in for VS? syntax coloring, show selected object ... from the text, or f
rom rendered x,y | 33 // plug in for VS? syntax coloring, show selected object ... from the text, or f
rom rendered x,y |
| 34 | 34 |
| 35 // TODO(edisonn): security - validate all the user input, all pdf! | 35 // TODO(edisonn): security - validate all the user input, all pdf! |
| 36 | 36 |
| 37 // TODO(edisonn): put drawtext in #ifdefs, so comparations will ignore minor cha
nges in text positioning and font | 37 // TODO(edisonn): put drawtext in #ifdefs, so comparations will ignore minor cha
nges in text positioning and font |
| 38 // this way, we look more at other features and layout in diffs | 38 // this way, we look more at other features and layout in diffs |
| 39 | 39 |
| 40 // TODO(edisonn): move trace dump in the get functions, and mapper ones too so i
t ghappens automatically |
| 41 /* |
| 42 #ifdef PDF_TRACE |
| 43 std::string str; |
| 44 pdfContext->fGraphicsState.fResources->podofo()->ToString(str); |
| 45 printf("Print Tf Resources: %s\n", str.c_str()); |
| 46 #endif |
| 47 */ |
| 48 |
| 40 #include "SkPdfHeaders_autogen.h" | 49 #include "SkPdfHeaders_autogen.h" |
| 41 #include "SkPdfPodofoMapper_autogen.h" | 50 #include "SkPdfMapper_autogen.h" |
| 42 #include "SkPdfParser.h" | 51 #include "SkPdfParser.h" |
| 43 | 52 |
| 44 #include "SkPdfBasics.h" | 53 #include "SkPdfBasics.h" |
| 45 #include "SkPdfUtils.h" | 54 #include "SkPdfUtils.h" |
| 46 | 55 |
| 47 #include "SkPdfFont.h" | 56 #include "SkPdfFont.h" |
| 48 | 57 |
| 49 bool skpdfmap(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdf
Object** out) { | |
| 50 return mapObject(podofoDoc, podofoObj, out); | |
| 51 } | |
| 52 | |
| 53 | |
| 54 /* | 58 /* |
| 55 * TODO(edisonn): | 59 * TODO(edisonn): |
| 56 * - all font types and all ppdf font features | 60 * - all font types and all ppdf font features |
| 57 * - word spacing | 61 * - word spacing |
| 58 * - load font for baidu.pdf | 62 * - load font for baidu.pdf |
| 59 * - load font for youtube.pdf | 63 * - load font for youtube.pdf |
| 60 * - parser for pdf from the definition already available in pdfspec_autoge
n.py | 64 * - parser for pdf from the definition already available in pdfspec_autoge
n.py |
| 61 * - all docs from ~/work | 65 * - all docs from ~/work |
| 62 * - encapsulate podofo in the pdf api so the skpdf does not know anything about
podofo ... in progress | 66 * - encapsulate podofo in the pdf api so the skpdf does not know anything about
podofo ... in progress |
| 63 * - load gs/ especially smask and already known prop (skp) ... in progress | 67 * - load gs/ especially smask and already known prop (skp) ... in progress |
| (...skipping 26 matching lines...) Expand all Loading... |
| 90 return 1; | 94 return 1; |
| 91 } else if (colorSpace == "DeviceRGB" || | 95 } else if (colorSpace == "DeviceRGB" || |
| 92 colorSpace == "CalRGB" || | 96 colorSpace == "CalRGB" || |
| 93 colorSpace == "Lab") { | 97 colorSpace == "Lab") { |
| 94 return 3; | 98 return 3; |
| 95 } else { | 99 } else { |
| 96 return 0; | 100 return 0; |
| 97 } | 101 } |
| 98 } | 102 } |
| 99 | 103 |
| 100 const PdfObject* resolveReferenceObject(const PdfMemDocument* pdfDoc, | 104 SkMatrix SkMatrixFromPdfMatrix(double array[6]) { |
| 101 const PdfObject* obj, | |
| 102 bool resolveOneElementArrays) { | |
| 103 while (obj && (obj->IsReference() || (resolveOneElementArrays && | |
| 104 obj->IsArray() && | |
| 105 obj->GetArray().GetSize() == 1))) { | |
| 106 if (obj->IsReference()) { | |
| 107 // We need to force the non const, the only update we will do is for
recurssion checks. | |
| 108 PdfReference& ref = (PdfReference&)obj->GetReference(); | |
| 109 obj = pdfDoc->GetObjects().GetObject(ref); | |
| 110 } else { | |
| 111 obj = &obj->GetArray()[0]; | |
| 112 } | |
| 113 } | |
| 114 | |
| 115 return obj; | |
| 116 } | |
| 117 | |
| 118 static SkMatrix SkMatrixFromPdfMatrix(double array[6]) { | |
| 119 SkMatrix matrix; | 105 SkMatrix matrix; |
| 120 matrix.setAll(SkDoubleToScalar(array[0]), | 106 matrix.setAll(SkDoubleToScalar(array[0]), |
| 121 SkDoubleToScalar(array[2]), | 107 SkDoubleToScalar(array[2]), |
| 122 SkDoubleToScalar(array[4]), | 108 SkDoubleToScalar(array[4]), |
| 123 SkDoubleToScalar(array[1]), | 109 SkDoubleToScalar(array[1]), |
| 124 SkDoubleToScalar(array[3]), | 110 SkDoubleToScalar(array[3]), |
| 125 SkDoubleToScalar(array[5]), | 111 SkDoubleToScalar(array[5]), |
| 126 SkDoubleToScalar(0), | 112 SkDoubleToScalar(0), |
| 127 SkDoubleToScalar(0), | 113 SkDoubleToScalar(0), |
| 128 SkDoubleToScalar(1)); | 114 SkDoubleToScalar(1)); |
| 129 | 115 |
| 130 return matrix; | 116 return matrix; |
| 131 } | 117 } |
| 132 | 118 |
| 133 SkMatrix SkMatrixFromPdfArray(SkPdfArray* pdfArray) { | 119 SkMatrix SkMatrixFromPdfArray(SkPdfArray* pdfArray) { |
| 134 double array[6]; | 120 double array[6]; |
| 135 | 121 |
| 136 // TODO(edisonn): security issue, ret if size() != 6 | 122 // TODO(edisonn): security issue, ret if size() != 6 |
| 137 for (int i = 0; i < 6; i++) { | 123 for (int i = 0; i < 6; i++) { |
| 138 const PdfObject* elem = resolveReferenceObject(pdfArray->doc(), (*pdfArr
ay)[i]->podofo()); | 124 const SkPdfObject* elem = pdfArray->operator [](i); |
| 139 if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) { | 125 if (elem == NULL || (!elem->asNumber() && !elem->asInteger())) { |
| 140 return SkMatrix::I(); // TODO(edisonn): report issue | 126 return SkMatrix::I(); // TODO(edisonn): report issue |
| 141 } | 127 } |
| 142 array[i] = elem->GetReal(); | 128 array[i] = elem->asNumber() ? elem->asNumber()->value() : elem->asIntege
r()->value(); |
| 143 } | 129 } |
| 144 | 130 |
| 145 return SkMatrixFromPdfMatrix(array); | 131 return SkMatrixFromPdfMatrix(array); |
| 146 } | 132 } |
| 147 | 133 |
| 148 PdfContext* gPdfContext = NULL; | |
| 149 SkBitmap* gDumpBitmap = NULL; | 134 SkBitmap* gDumpBitmap = NULL; |
| 150 SkCanvas* gDumpCanvas = NULL; | 135 SkCanvas* gDumpCanvas = NULL; |
| 151 char gLastKeyword[100] = ""; | 136 char gLastKeyword[100] = ""; |
| 152 int gLastOpKeyword = -1; | 137 int gLastOpKeyword = -1; |
| 153 char allOpWithVisualEffects[100] = ",S,s,f,F,f*,B,B*,b,b*,n,Tj,TJ,\',\",d0,d1,sh
,EI,Do,EX,"; | 138 char allOpWithVisualEffects[100] = ",S,s,f,F,f*,B,B*,b,b*,n,Tj,TJ,\',\",d0,d1,sh
,EI,Do,EX,"; |
| 154 int gReadOp = 0; | 139 int gReadOp = 0; |
| 155 | 140 |
| 156 | 141 |
| 157 | 142 |
| 158 bool hasVisualEffect(const char* pdfOp) { | 143 bool hasVisualEffect(const char* pdfOp) { |
| 159 return true; | 144 return true; |
| 160 if (*pdfOp == '\0') return false; | 145 if (*pdfOp == '\0') return false; |
| 161 | 146 |
| 162 char markedPdfOp[100] = ","; | 147 char markedPdfOp[100] = ","; |
| 163 strcat(markedPdfOp, pdfOp); | 148 strcat(markedPdfOp, pdfOp); |
| 164 strcat(markedPdfOp, ","); | 149 strcat(markedPdfOp, ","); |
| 165 | 150 |
| 166 return (strstr(allOpWithVisualEffects, markedPdfOp) != NULL); | 151 return (strstr(allOpWithVisualEffects, markedPdfOp) != NULL); |
| 167 } | 152 } |
| 168 | 153 |
| 169 // TODO(edisonn): Pass PdfContext and SkCanvasd only with the define for instrum
entation. | 154 // TODO(edisonn): Pass PdfContext and SkCanvasd only with the define for instrum
entation. |
| 170 static bool readToken(SkPdfTokenizer* fTokenizer, PdfToken* token) { | 155 static bool readToken(SkPdfPodofoTokenizer* fTokenizer, PdfToken* token) { |
| 171 bool ret = fTokenizer->readToken(token); | 156 bool ret = fTokenizer->readToken(token); |
| 172 | 157 |
| 173 gReadOp++; | 158 gReadOp++; |
| 174 | 159 |
| 175 #ifdef PDF_TRACE_DIFF_IN_PNG | 160 #ifdef PDF_TRACE_DIFF_IN_PNG |
| 176 // TODO(edisonn): compare with old bitmap, and save only new bits are availa
ble, and save | 161 // TODO(edisonn): compare with old bitmap, and save only new bits are availa
ble, and save |
| 177 // the numbar and name of last operation, so the file name will reflect op t
hat changed. | 162 // the numbar and name of last operation, so the file name will reflect op t
hat changed. |
| 178 if (hasVisualEffect(gLastKeyword)) { // TODO(edisonn): and has dirty bits. | 163 if (hasVisualEffect(gLastKeyword)) { // TODO(edisonn): and has dirty bits. |
| 179 gDumpCanvas->flush(); | 164 gDumpCanvas->flush(); |
| 180 | 165 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 #endif | 311 #endif |
| 327 | 312 |
| 328 // TODO(edisonn): Report Warning, NYI | 313 // TODO(edisonn): Report Warning, NYI |
| 329 return SkTypeface::CreateFromName( | 314 return SkTypeface::CreateFromName( |
| 330 "Times New Roman", | 315 "Times New Roman", |
| 331 SkTypeface::Style((font->IsBold() ? SkTypeface::kBold : 0) | | 316 SkTypeface::Style((font->IsBold() ? SkTypeface::kBold : 0) | |
| 332 (font->IsItalic() ? SkTypeface::kItalic : 0)))
; | 317 (font->IsItalic() ? SkTypeface::kItalic : 0)))
; |
| 333 } | 318 } |
| 334 | 319 |
| 335 PdfResult DrawText(PdfContext* pdfContext, | 320 PdfResult DrawText(PdfContext* pdfContext, |
| 336 const SkPdfObject* str, | 321 const SkPdfObject* _str, |
| 337 SkCanvas* canvas) | 322 SkCanvas* canvas) |
| 338 { | 323 { |
| 339 | 324 |
| 340 SkPdfFont* skfont = pdfContext->fGraphicsState.fSkFont; | 325 SkPdfFont* skfont = pdfContext->fGraphicsState.fSkFont; |
| 341 if (skfont == NULL) { | 326 if (skfont == NULL) { |
| 342 skfont = SkPdfFont::Default(); | 327 skfont = SkPdfFont::Default(); |
| 343 } | 328 } |
| 344 | 329 |
| 330 const SkPdfString* str = _str->asString(); |
| 331 |
| 332 if (str == NULL) { |
| 333 // TODO(edisonn): report warning |
| 334 return kIgnoreError_PdfResult; |
| 335 } |
| 336 |
| 345 SkUnencodedText binary(str); | 337 SkUnencodedText binary(str); |
| 346 | 338 |
| 347 SkDecodedText decoded; | 339 SkDecodedText decoded; |
| 348 | 340 |
| 349 if (skfont->encoding() == NULL) { | 341 if (skfont->encoding() == NULL) { |
| 350 // TODO(edisonn): report warning | 342 // TODO(edisonn): report warning |
| 351 return kNYI_PdfResult; | 343 return kNYI_PdfResult; |
| 352 } | 344 } |
| 353 | 345 |
| 354 skfont->encoding()->decodeText(binary, &decoded); | 346 skfont->encoding()->decodeText(binary, &decoded); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 | 385 |
| 394 return kPartial_PdfResult; | 386 return kPartial_PdfResult; |
| 395 } | 387 } |
| 396 | 388 |
| 397 // TODO(edisonn): create header files with declarations! | 389 // TODO(edisonn): create header files with declarations! |
| 398 PdfResult PdfOp_q(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per); | 390 PdfResult PdfOp_q(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per); |
| 399 PdfResult PdfOp_Q(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per); | 391 PdfResult PdfOp_Q(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per); |
| 400 PdfResult PdfOp_Tw(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper); | 392 PdfResult PdfOp_Tw(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper); |
| 401 PdfResult PdfOp_Tc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper); | 393 PdfResult PdfOp_Tc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper); |
| 402 | 394 |
| 403 // TODO(edisonn): deal with synonyms (/BPC == /BitsPerComponent), here or in Get
Key? | |
| 404 // Always pass long form in key, and have a map of long -> short key | |
| 405 bool LongFromDictionary(const PdfMemDocument* pdfDoc, | |
| 406 const PdfDictionary& dict, | |
| 407 const char* key, | |
| 408 long* data) { | |
| 409 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 410 dict.GetKey(PdfName(key))); | |
| 411 | |
| 412 if (value == NULL || !value->IsNumber()) { | |
| 413 return false; | |
| 414 } | |
| 415 if (data == NULL) { | |
| 416 return true; | |
| 417 } | |
| 418 | |
| 419 *data = value->GetNumber(); | |
| 420 return true; | |
| 421 } | |
| 422 | |
| 423 bool LongFromDictionary(const PdfMemDocument* pdfDoc, | |
| 424 const PdfDictionary& dict, | |
| 425 const char* key, | |
| 426 const char* abr, | |
| 427 long* data) { | |
| 428 if (LongFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 429 if (abr == NULL || *abr == '\0') return false; | |
| 430 return LongFromDictionary(pdfDoc, dict, abr, data); | |
| 431 } | |
| 432 | |
| 433 bool DoubleFromDictionary(const PdfMemDocument* pdfDoc, | |
| 434 const PdfDictionary& dict, | |
| 435 const char* key, | |
| 436 double* data) { | |
| 437 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 438 dict.GetKey(PdfName(key))); | |
| 439 | |
| 440 if (value == NULL || (!value->IsReal() && !value->IsNumber())) { | |
| 441 return false; | |
| 442 } | |
| 443 if (data == NULL) { | |
| 444 return true; | |
| 445 } | |
| 446 | |
| 447 *data = value->GetReal(); | |
| 448 return true; | |
| 449 } | |
| 450 | |
| 451 bool DoubleFromDictionary(const PdfMemDocument* pdfDoc, | |
| 452 const PdfDictionary& dict, | |
| 453 const char* key, | |
| 454 const char* abr, | |
| 455 double* data) { | |
| 456 if (DoubleFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 457 if (abr == NULL || *abr == '\0') return false; | |
| 458 return DoubleFromDictionary(pdfDoc, dict, abr, data); | |
| 459 } | |
| 460 | |
| 461 | |
| 462 bool BoolFromDictionary(const PdfMemDocument* pdfDoc, | |
| 463 const PdfDictionary& dict, | |
| 464 const char* key, | |
| 465 bool* data) { | |
| 466 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 467 dict.GetKey(PdfName(key))); | |
| 468 | |
| 469 if (value == NULL || !value->IsBool()) { | |
| 470 return false; | |
| 471 } | |
| 472 if (data == NULL) { | |
| 473 return true; | |
| 474 } | |
| 475 | |
| 476 *data = value->GetBool(); | |
| 477 return true; | |
| 478 } | |
| 479 | |
| 480 bool BoolFromDictionary(const PdfMemDocument* pdfDoc, | |
| 481 const PdfDictionary& dict, | |
| 482 const char* key, | |
| 483 const char* abr, | |
| 484 bool* data) { | |
| 485 if (BoolFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 486 if (abr == NULL || *abr == '\0') return false; | |
| 487 return BoolFromDictionary(pdfDoc, dict, abr, data); | |
| 488 } | |
| 489 | |
| 490 bool NameFromDictionary(const PdfMemDocument* pdfDoc, | |
| 491 const PdfDictionary& dict, | |
| 492 const char* key, | |
| 493 std::string* data) { | |
| 494 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 495 dict.GetKey(PdfName(key)), | |
| 496 true); | |
| 497 if (value == NULL || !value->IsName()) { | |
| 498 return false; | |
| 499 } | |
| 500 if (data == NULL) { | |
| 501 return true; | |
| 502 } | |
| 503 | |
| 504 *data = value->GetName().GetName(); | |
| 505 return true; | |
| 506 } | |
| 507 | |
| 508 bool NameFromDictionary(const PdfMemDocument* pdfDoc, | |
| 509 const PdfDictionary& dict, | |
| 510 const char* key, | |
| 511 const char* abr, | |
| 512 std::string* data) { | |
| 513 if (NameFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 514 if (abr == NULL || *abr == '\0') return false; | |
| 515 return NameFromDictionary(pdfDoc, dict, abr, data); | |
| 516 } | |
| 517 | |
| 518 bool StringFromDictionary(const PdfMemDocument* pdfDoc, | |
| 519 const PdfDictionary& dict, | |
| 520 const char* key, | |
| 521 std::string* data) { | |
| 522 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 523 dict.GetKey(PdfName(key)), | |
| 524 true); | |
| 525 if (value == NULL || (!value->IsString() && !value->IsHexString())) { | |
| 526 return false; | |
| 527 } | |
| 528 if (data == NULL) { | |
| 529 return true; | |
| 530 } | |
| 531 | |
| 532 *data = value->GetString().GetString(); | |
| 533 return true; | |
| 534 } | |
| 535 | |
| 536 bool StringFromDictionary(const PdfMemDocument* pdfDoc, | |
| 537 const PdfDictionary& dict, | |
| 538 const char* key, | |
| 539 const char* abr, | |
| 540 std::string* data) { | |
| 541 if (StringFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 542 if (abr == NULL || *abr == '\0') return false; | |
| 543 return StringFromDictionary(pdfDoc, dict, abr, data); | |
| 544 } | |
| 545 | |
| 546 /* | |
| 547 bool ArrayFromDictionary(const PdfMemDocument* pdfDoc, | |
| 548 const PdfDictionary& dict, | |
| 549 const char* key, | |
| 550 SkPdfArray** data) { | |
| 551 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 552 dict.GetKey(PdfName(key)), | |
| 553 true); | |
| 554 if (value == NULL || !value->IsArray()) { | |
| 555 return false; | |
| 556 } | |
| 557 if (data == NULL) { | |
| 558 return true; | |
| 559 } | |
| 560 | |
| 561 return mapArray(*pdfDoc, *value, data); | |
| 562 } | |
| 563 | |
| 564 | |
| 565 bool ArrayFromDictionary(const PdfMemDocument* pdfDoc, | |
| 566 const PdfDictionary& dict, | |
| 567 const char* key, | |
| 568 const char* abr, | |
| 569 SkPdfArray** data) { | |
| 570 if (ArrayFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 571 if (abr == NULL || *abr == '\0') return false; | |
| 572 return ArrayFromDictionary(pdfDoc, dict, abr, data); | |
| 573 } | |
| 574 | |
| 575 | |
| 576 bool DictionaryFromDictionary(const PdfMemDocument* pdfDoc, | |
| 577 const PdfDictionary& dict, | |
| 578 const char* key, | |
| 579 SkPdfDictionary** data) { | |
| 580 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 581 dict.GetKey(PdfName(key)), | |
| 582 true); | |
| 583 if (value == NULL || !value->IsDictionary()) { | |
| 584 return false; | |
| 585 } | |
| 586 if (data == NULL) { | |
| 587 return true; | |
| 588 } | |
| 589 | |
| 590 return mapDictionary(*pdfDoc, *value, data); | |
| 591 } | |
| 592 | |
| 593 bool DictionaryFromDictionary(const PdfMemDocument* pdfDoc, | |
| 594 const PdfDictionary& dict, | |
| 595 const char* key, | |
| 596 const char* abr, | |
| 597 SkPdfDictionary** data) { | |
| 598 if (DictionaryFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 599 if (abr == NULL || *abr == '\0') return false; | |
| 600 return DictionaryFromDictionary(pdfDoc, dict, abr, data); | |
| 601 } | |
| 602 | |
| 603 | |
| 604 bool ObjectFromDictionary(const PdfMemDocument* pdfDoc, | |
| 605 const PdfDictionary& dict, | |
| 606 const char* key, | |
| 607 SkPdfObject** data) { | |
| 608 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 609 dict.GetKey(PdfName(key)), | |
| 610 true); | |
| 611 if (value == NULL) { | |
| 612 return false; | |
| 613 } | |
| 614 if (data == NULL) { | |
| 615 return true; | |
| 616 } | |
| 617 return mapObject(*pdfDoc, *value, data); | |
| 618 } | |
| 619 | |
| 620 bool ObjectFromDictionary(const PdfMemDocument* pdfDoc, | |
| 621 const PdfDictionary& dict, | |
| 622 const char* key, | |
| 623 const char* abr, | |
| 624 SkPdfObject** data) { | |
| 625 if (ObjectFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 626 if (abr == NULL || *abr == '\0') return false; | |
| 627 return ObjectFromDictionary(pdfDoc, dict, abr, data); | |
| 628 } | |
| 629 | |
| 630 bool StreamFromDictionary(const PdfMemDocument* pdfDoc, | |
| 631 const PdfDictionary& dict, | |
| 632 const char* key, | |
| 633 SkPdfStream** data) { | |
| 634 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 635 dict.GetKey(PdfName(key)), | |
| 636 true); | |
| 637 if (value == NULL) { | |
| 638 return false; | |
| 639 } | |
| 640 if (data == NULL) { | |
| 641 return true; | |
| 642 } | |
| 643 return mapStream(*pdfDoc, *value, data); | |
| 644 } | |
| 645 | |
| 646 bool StreamFromDictionary(const PdfMemDocument* pdfDoc, | |
| 647 const PdfDictionary& dict, | |
| 648 const char* key, | |
| 649 const char* abr, | |
| 650 SkPdfStream** data) { | |
| 651 if (StreamFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 652 if (abr == NULL || *abr == '\0') return false; | |
| 653 return StreamFromDictionary(pdfDoc, dict, abr, data); | |
| 654 } | |
| 655 */ | |
| 656 | |
| 657 // TODO(edisonn): perf!!! | 395 // TODO(edisonn): perf!!! |
| 658 | 396 |
| 659 static SkColorTable* getGrayColortable() { | 397 static SkColorTable* getGrayColortable() { |
| 660 static SkColorTable* grayColortable = NULL; | 398 static SkColorTable* grayColortable = NULL; |
| 661 if (grayColortable == NULL) { | 399 if (grayColortable == NULL) { |
| 662 SkPMColor* colors = new SkPMColor[256]; | 400 SkPMColor* colors = new SkPMColor[256]; |
| 663 for (int i = 0 ; i < 256; i++) { | 401 for (int i = 0 ; i < 256; i++) { |
| 664 colors[i] = SkPreMultiplyARGB(255, i, i, i); | 402 colors[i] = SkPreMultiplyARGB(255, i, i, i); |
| 665 } | 403 } |
| 666 grayColortable = new SkColorTable(colors, 256); | 404 grayColortable = new SkColorTable(colors, 256); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 774 // utils | 512 // utils |
| 775 | 513 |
| 776 // TODO(edisonn): add cache, or put the bitmap property directly on the PdfObjec
t | 514 // TODO(edisonn): add cache, or put the bitmap property directly on the PdfObjec
t |
| 777 // TODO(edisonn): deal with colorSpaces, we could add them to SkBitmap::Config | 515 // TODO(edisonn): deal with colorSpaces, we could add them to SkBitmap::Config |
| 778 // TODO(edisonn): preserve A1 format that skia knows, + fast convert from 111, 2
22, 444 to closest | 516 // TODO(edisonn): preserve A1 format that skia knows, + fast convert from 111, 2
22, 444 to closest |
| 779 // skia format, through a table | 517 // skia format, through a table |
| 780 | 518 |
| 781 // this functions returns the image, it does not look at the smask. | 519 // this functions returns the image, it does not look at the smask. |
| 782 | 520 |
| 783 SkBitmap getImageFromObject(PdfContext* pdfContext, const SkPdfImageDictionary*
image, bool transparencyMask) { | 521 SkBitmap getImageFromObject(PdfContext* pdfContext, const SkPdfImageDictionary*
image, bool transparencyMask) { |
| 784 if (image == NULL || !image->valid()) { | 522 if (image == NULL) { |
| 785 // TODO(edisonn): report warning to be used in testing. | 523 // TODO(edisonn): report warning to be used in testing. |
| 786 return SkBitmap(); | 524 return SkBitmap(); |
| 787 } | 525 } |
| 788 | 526 |
| 789 // TODO (edisonn): Fast Jpeg(DCTDecode) draw, or fast PNG(FlateDecode) draw
... | 527 // TODO (edisonn): Fast Jpeg(DCTDecode) draw, or fast PNG(FlateDecode) draw
... |
| 790 // PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc, | 528 // PdfObject* value = resolveReferenceObject(pdfContext->fPdfDoc, |
| 791 // obj.GetDictionary().GetKey(PdfNa
me("Filter"))); | 529 // obj.GetDictionary().GetKey(PdfNa
me("Filter"))); |
| 792 // if (value && value->IsArray() && value->GetArray().GetSize() == 1) { | 530 // if (value && value->IsArray() && value->GetArray().GetSize() == 1) { |
| 793 // value = resolveReferenceObject(pdfContext->fPdfDoc, | 531 // value = resolveReferenceObject(pdfContext->fPdfDoc, |
| 794 // &value->GetArray()[0]); | 532 // &value->GetArray()[0]); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 813 | 551 |
| 814 if (imageMask) { | 552 if (imageMask) { |
| 815 if (bpc != 0 && bpc != 1) { | 553 if (bpc != 0 && bpc != 1) { |
| 816 // TODO(edisonn): report warning to be used in testing. | 554 // TODO(edisonn): report warning to be used in testing. |
| 817 return SkBitmap(); | 555 return SkBitmap(); |
| 818 } | 556 } |
| 819 bpc = 1; | 557 bpc = 1; |
| 820 } | 558 } |
| 821 */ | 559 */ |
| 822 | 560 |
| 823 const PdfObject* obj = image->podofo(); | |
| 824 | |
| 825 char* uncompressedStream = NULL; | 561 char* uncompressedStream = NULL; |
| 826 pdf_long uncompressedStreamLength = 0; | 562 pdf_long uncompressedStreamLength = 0; |
| 827 | 563 |
| 828 PdfResult ret = kPartial_PdfResult; | 564 PdfResult ret = kPartial_PdfResult; |
| 829 // TODO(edisonn): get rid of try/catch exceptions! We should not throw on us
er data! | 565 SkPdfStream* stream = NULL; |
| 830 try { | 566 image->doc()->mapper()->mapStream(image, &stream); |
| 831 obj->GetStream()->GetFilteredCopy(&uncompressedStream, &uncompressedStre
amLength); | 567 |
| 832 } catch (PdfError& e) { | 568 if (!stream || !stream->GetFilteredCopy(&uncompressedStream, &uncompressedSt
reamLength) || |
| 569 uncompressedStream == NULL || uncompressedStreamLength == 0) { |
| 833 // TODO(edisonn): report warning to be used in testing. | 570 // TODO(edisonn): report warning to be used in testing. |
| 834 return SkBitmap(); | 571 return SkBitmap(); |
| 835 } | 572 } |
| 836 | 573 |
| 837 int bytesPerLine = uncompressedStreamLength / height; | 574 int bytesPerLine = uncompressedStreamLength / height; |
| 838 #ifdef PDF_TRACE | 575 #ifdef PDF_TRACE |
| 839 if (uncompressedStreamLength % height != 0) { | 576 if (uncompressedStreamLength % height != 0) { |
| 840 printf("Warning uncompressedStreamLength % height != 0 !!!\n"); | 577 printf("Warning uncompressedStreamLength % height != 0 !!!\n"); |
| 841 } | 578 } |
| 842 #endif | 579 #endif |
| 843 | 580 |
| 844 SkBitmap bitmap = transferImageStreamToBitmap( | 581 SkBitmap bitmap = transferImageStreamToBitmap( |
| 845 (unsigned char*)uncompressedStream, uncompressedStreamLength, | 582 (unsigned char*)uncompressedStream, uncompressedStreamLength, |
| 846 width, height, bytesPerLine, | 583 width, height, bytesPerLine, |
| 847 bpc, colorSpace, | 584 bpc, colorSpace, |
| 848 transparencyMask); | 585 transparencyMask); |
| 849 | 586 |
| 850 free(uncompressedStream); | 587 free(uncompressedStream); |
| 851 | 588 |
| 852 return bitmap; | 589 return bitmap; |
| 853 } | 590 } |
| 854 | 591 |
| 855 SkBitmap getSmaskFromObject(PdfContext* pdfContext, const SkPdfImageDictionary*
obj) { | 592 SkBitmap getSmaskFromObject(PdfContext* pdfContext, const SkPdfImageDictionary*
obj) { |
| 856 const PdfObject* sMask = resolveReferenceObject(&pdfContext->fPdfDoc->podofo
(), | 593 const SkPdfImageDictionary* sMask = obj->SMask(); |
| 857 obj->podofo()->GetDictionary().Get
Key(PdfName("SMask"))); | |
| 858 | |
| 859 #ifdef PDF_TRACE | |
| 860 std::string str; | |
| 861 if (sMask) { | |
| 862 sMask->ToString(str); | |
| 863 printf("/SMask of /Subtype /Image: %s\n", str.c_str()); | |
| 864 } | |
| 865 #endif | |
| 866 | 594 |
| 867 if (sMask) { | 595 if (sMask) { |
| 868 SkPdfImageDictionary skxobjmask(&pdfContext->fPdfDoc->podofo(), sMask); | 596 return getImageFromObject(pdfContext, sMask, true); |
| 869 return getImageFromObject(pdfContext, &skxobjmask, true); | |
| 870 } | 597 } |
| 871 | 598 |
| 872 // TODO(edisonn): implement GS SMask. Default to empty right now. | 599 // TODO(edisonn): implement GS SMask. Default to empty right now. |
| 873 return pdfContext->fGraphicsState.fSMask; | 600 return pdfContext->fGraphicsState.fSMask; |
| 874 } | 601 } |
| 875 | 602 |
| 876 PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfI
mageDictionary* skpdfimage) { | 603 PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfI
mageDictionary* skpdfimage) { |
| 877 if (skpdfimage == NULL || !skpdfimage->valid()) { | 604 if (skpdfimage == NULL) { |
| 878 return kIgnoreError_PdfResult; | 605 return kIgnoreError_PdfResult; |
| 879 } | 606 } |
| 880 | 607 |
| 881 SkBitmap image = getImageFromObject(pdfContext, skpdfimage, false); | 608 SkBitmap image = getImageFromObject(pdfContext, skpdfimage, false); |
| 882 SkBitmap sMask = getSmaskFromObject(pdfContext, skpdfimage); | 609 SkBitmap sMask = getSmaskFromObject(pdfContext, skpdfimage); |
| 883 | 610 |
| 884 canvas->save(); | 611 canvas->save(); |
| 885 canvas->setMatrix(pdfContext->fGraphicsState.fMatrix); | 612 canvas->setMatrix(pdfContext->fGraphicsState.fMatrix); |
| 886 SkRect dst = SkRect::MakeXYWH(SkDoubleToScalar(0.0), SkDoubleToScalar(0.0),
SkDoubleToScalar(1.0), SkDoubleToScalar(1.0)); | 613 SkRect dst = SkRect::MakeXYWH(SkDoubleToScalar(0.0), SkDoubleToScalar(0.0),
SkDoubleToScalar(1.0), SkDoubleToScalar(1.0)); |
| 887 | 614 |
| 888 if (sMask.empty()) { | 615 if (sMask.empty()) { |
| 889 canvas->drawBitmapRect(image, dst, NULL); | 616 canvas->drawBitmapRect(image, dst, NULL); |
| 890 } else { | 617 } else { |
| 891 canvas->saveLayer(&dst, NULL); | 618 canvas->saveLayer(&dst, NULL); |
| 892 canvas->drawBitmapRect(image, dst, NULL); | 619 canvas->drawBitmapRect(image, dst, NULL); |
| 893 SkPaint xfer; | 620 SkPaint xfer; |
| 894 pdfContext->fGraphicsState.applyGraphicsState(&xfer, false); | 621 pdfContext->fGraphicsState.applyGraphicsState(&xfer, false); |
| 895 xfer.setXfermodeMode(SkXfermode::kSrcOut_Mode); // SkXfermode::kSdtOut_M
ode | 622 xfer.setXfermodeMode(SkXfermode::kSrcOut_Mode); // SkXfermode::kSdtOut_M
ode |
| 896 canvas->drawBitmapRect(sMask, dst, &xfer); | 623 canvas->drawBitmapRect(sMask, dst, &xfer); |
| 897 canvas->restore(); | 624 canvas->restore(); |
| 898 } | 625 } |
| 899 | 626 |
| 900 canvas->restore(); | 627 canvas->restore(); |
| 901 | 628 |
| 902 return kPartial_PdfResult; | 629 return kPartial_PdfResult; |
| 903 } | 630 } |
| 904 | 631 |
| 905 bool SkMatrixFromDictionary(const PdfMemDocument* pdfDoc, | |
| 906 const PdfDictionary& dict, | |
| 907 const char* key, | |
| 908 SkMatrix** matrix) { | |
| 909 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 910 dict.GetKey(PdfName(key))); | |
| 911 | |
| 912 if (value == NULL || !value->IsArray()) { | |
| 913 return false; | |
| 914 } | |
| 915 | |
| 916 if (value->GetArray().GetSize() != 6) { | |
| 917 return false; | |
| 918 } | |
| 919 | |
| 920 double array[6]; | |
| 921 for (int i = 0; i < 6; i++) { | |
| 922 const PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray(
)[i]); | |
| 923 if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) { | |
| 924 return false; | |
| 925 } | |
| 926 array[i] = elem->GetReal(); | |
| 927 } | |
| 928 | |
| 929 *matrix = new SkMatrix(); | |
| 930 **matrix = SkMatrixFromPdfMatrix(array); | |
| 931 return true; | |
| 932 } | |
| 933 | |
| 934 bool SkMatrixFromDictionary(const PdfMemDocument* pdfDoc, | |
| 935 const PdfDictionary& dict, | |
| 936 const char* key, | |
| 937 const char* abr, | |
| 938 SkMatrix** data) { | |
| 939 if (SkMatrixFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 940 if (abr == NULL || *abr == '\0') return false; | |
| 941 return SkMatrixFromDictionary(pdfDoc, dict, abr, data); | |
| 942 | |
| 943 } | |
| 944 | |
| 945 bool SkRectFromDictionary(const PdfMemDocument* pdfDoc, | |
| 946 const PdfDictionary& dict, | |
| 947 const char* key, | |
| 948 SkRect** rect) { | |
| 949 const PdfObject* value = resolveReferenceObject(pdfDoc, | |
| 950 dict.GetKey(PdfName(key))); | |
| 951 | |
| 952 if (value == NULL || !value->IsArray()) { | |
| 953 return false; | |
| 954 } | |
| 955 | |
| 956 if (value->GetArray().GetSize() != 4) { | |
| 957 return false; | |
| 958 } | |
| 959 | |
| 960 double array[4]; | |
| 961 for (int i = 0; i < 4; i++) { | |
| 962 const PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray(
)[i]); | |
| 963 if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) { | |
| 964 return false; | |
| 965 } | |
| 966 array[i] = elem->GetReal(); | |
| 967 } | |
| 968 | |
| 969 *rect = new SkRect(); | |
| 970 **rect = SkRect::MakeLTRB(SkDoubleToScalar(array[0]), | |
| 971 SkDoubleToScalar(array[1]), | |
| 972 SkDoubleToScalar(array[2]), | |
| 973 SkDoubleToScalar(array[3])); | |
| 974 return true; | |
| 975 } | |
| 976 | |
| 977 bool SkRectFromDictionary(const PdfMemDocument* pdfDoc, | |
| 978 const PdfDictionary& dict, | |
| 979 const char* key, | |
| 980 const char* abr, | |
| 981 SkRect** data) { | |
| 982 if (SkRectFromDictionary(pdfDoc, dict, key, data)) return true; | |
| 983 if (abr == NULL || *abr == '\0') return false; | |
| 984 return SkRectFromDictionary(pdfDoc, dict, abr, data); | |
| 985 | |
| 986 } | |
| 987 | 632 |
| 988 | 633 |
| 989 SkPdfObject* get(const SkPdfObject* obj, const char* key, const char* abr = "")
{ | |
| 990 SkPdfObject* ret = NULL; | |
| 991 if (obj == NULL) return NULL; | |
| 992 const SkPdfDictionary* dict = obj->asDictionary(); | |
| 993 if (dict == NULL) return NULL; | |
| 994 if (!dict->podofo()->IsDictionary()) return NULL; | |
| 995 ObjectFromDictionary(dict->doc(), dict->podofo()->GetDictionary(), key, abr,
&ret); | |
| 996 return ret; | |
| 997 } | |
| 998 | 634 |
| 999 PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, SkPdfType1For
mDictionary* skobj) { | 635 PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, SkPdfType1For
mDictionary* skobj) { |
| 1000 if (!skobj || !skobj->podofo() || !skobj->podofo()->HasStream() || skobj->po
dofo()->GetStream() == NULL || skobj->podofo()->GetStream()->GetLength() == 0) { | 636 if (!skobj) { |
| 1001 return kOK_PdfResult; | 637 return kIgnoreError_PdfResult; |
| 1002 } | 638 } |
| 1003 | 639 |
| 1004 PdfOp_q(pdfContext, canvas, NULL); | 640 PdfOp_q(pdfContext, canvas, NULL); |
| 1005 canvas->save(); | 641 canvas->save(); |
| 1006 | 642 |
| 1007 | 643 |
| 1008 if (skobj->Resources()) { | 644 if (skobj->Resources()) { |
| 1009 pdfContext->fGraphicsState.fResources = skobj->Resources(); | 645 pdfContext->fGraphicsState.fResources = skobj->Resources(); |
| 1010 } | 646 } |
| 1011 | 647 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1022 | 658 |
| 1023 canvas->setMatrix(pdfContext->fGraphicsState.fMatrix); | 659 canvas->setMatrix(pdfContext->fGraphicsState.fMatrix); |
| 1024 | 660 |
| 1025 if (skobj->BBox()) { | 661 if (skobj->BBox()) { |
| 1026 canvas->clipRect(*skobj->BBox(), SkRegion::kIntersect_Op, true); // TOD
O(edisonn): AA from settings. | 662 canvas->clipRect(*skobj->BBox(), SkRegion::kIntersect_Op, true); // TOD
O(edisonn): AA from settings. |
| 1027 } | 663 } |
| 1028 | 664 |
| 1029 // TODO(edisonn): iterate smart on the stream even if it is compressed, toke
nize it as we go. | 665 // TODO(edisonn): iterate smart on the stream even if it is compressed, toke
nize it as we go. |
| 1030 // For this PdfContentsTokenizer needs to be extended. | 666 // For this PdfContentsTokenizer needs to be extended. |
| 1031 | 667 |
| 1032 PdfResult ret = kPartial_PdfResult; | 668 SkPdfStream* stream = NULL; |
| 1033 SkPdfTokenizer tokenizer(skobj); | 669 skobj->doc()->mapper()->mapStream(skobj, &stream); |
| 1034 PdfMainLooper looper(NULL, &tokenizer, pdfContext, canvas); | 670 |
| 1035 looper.loop(); | 671 SkPdfPodofoTokenizer* tokenizer = skobj->doc()->tokenizerOfStream(stream); |
| 672 if (tokenizer != NULL) { |
| 673 PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); |
| 674 looper.loop(); |
| 675 delete tokenizer; |
| 676 } |
| 1036 | 677 |
| 1037 // TODO(edisonn): should we restore the variable stack at the same state? | 678 // TODO(edisonn): should we restore the variable stack at the same state? |
| 1038 // There could be operands left, that could be consumed by a parent tokenize
r when we pop. | 679 // There could be operands left, that could be consumed by a parent tokenize
r when we pop. |
| 1039 canvas->restore(); | 680 canvas->restore(); |
| 1040 PdfOp_Q(pdfContext, canvas, NULL); | 681 PdfOp_Q(pdfContext, canvas, NULL); |
| 1041 return ret; | 682 return kPartial_PdfResult; |
| 1042 } | 683 } |
| 1043 | 684 |
| 1044 PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject
& obj) { | 685 PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject
& obj) { |
| 1045 return kNYI_PdfResult; | 686 return kNYI_PdfResult; |
| 1046 } | 687 } |
| 1047 | 688 |
| 1048 PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, SkPdfObject* sko
bj, SkRect bBox, SkMatrix matrix, double textSize) { | 689 PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, SkPdfObject* sko
bj, SkRect bBox, SkMatrix matrix, double textSize) { |
| 1049 if (!skobj || !skobj->podofo() || !skobj->podofo()->HasStream() || skobj->po
dofo()->GetStream() == NULL || skobj->podofo()->GetStream()->GetLength() == 0) { | 690 if (!skobj) { |
| 1050 return kOK_PdfResult; | 691 return kIgnoreError_PdfResult; |
| 1051 } | 692 } |
| 1052 | 693 |
| 1053 PdfOp_q(pdfContext, canvas, NULL); | 694 PdfOp_q(pdfContext, canvas, NULL); |
| 1054 canvas->save(); | 695 canvas->save(); |
| 1055 | 696 |
| 1056 pdfContext->fGraphicsState.fMatrixTm.preConcat(matrix); | 697 pdfContext->fGraphicsState.fMatrixTm.preConcat(matrix); |
| 1057 pdfContext->fGraphicsState.fMatrixTm.preScale(SkDoubleToScalar(textSize), Sk
DoubleToScalar(textSize)); | 698 pdfContext->fGraphicsState.fMatrixTm.preScale(SkDoubleToScalar(textSize), Sk
DoubleToScalar(textSize)); |
| 1058 | 699 |
| 1059 pdfContext->fGraphicsState.fMatrix = pdfContext->fGraphicsState.fMatrixTm; | 700 pdfContext->fGraphicsState.fMatrix = pdfContext->fGraphicsState.fMatrixTm; |
| 1060 pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fMatrix; | 701 pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fMatrix; |
| 1061 | 702 |
| 1062 SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "Total matrix"); | 703 SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "Total matrix"); |
| 1063 | 704 |
| 1064 canvas->setMatrix(pdfContext->fGraphicsState.fMatrix); | 705 canvas->setMatrix(pdfContext->fGraphicsState.fMatrix); |
| 1065 | 706 |
| 1066 SkRect rm = bBox; | 707 SkRect rm = bBox; |
| 1067 pdfContext->fGraphicsState.fMatrix.mapRect(&rm); | 708 pdfContext->fGraphicsState.fMatrix.mapRect(&rm); |
| 1068 | 709 |
| 1069 SkTraceRect(rm, "bbox mapped"); | 710 SkTraceRect(rm, "bbox mapped"); |
| 1070 | 711 |
| 1071 canvas->clipRect(bBox, SkRegion::kIntersect_Op, true); // TODO(edisonn): AA
from settings. | 712 canvas->clipRect(bBox, SkRegion::kIntersect_Op, true); // TODO(edisonn): AA
from settings. |
| 1072 | 713 |
| 1073 // TODO(edisonn): iterate smart on the stream even if it is compressed, toke
nize it as we go. | 714 // TODO(edisonn): iterate smart on the stream even if it is compressed, toke
nize it as we go. |
| 1074 // For this PdfContentsTokenizer needs to be extended. | 715 // For this PdfContentsTokenizer needs to be extended. |
| 1075 | 716 |
| 1076 PdfResult ret = kPartial_PdfResult; | 717 SkPdfStream* stream = NULL; |
| 1077 SkPdfTokenizer tokenizer(skobj); | 718 skobj->doc()->mapper()->mapStream(skobj, &stream); |
| 1078 PdfMainLooper looper(NULL, &tokenizer, pdfContext, canvas); | 719 |
| 1079 looper.loop(); | 720 SkPdfPodofoTokenizer* tokenizer = skobj->doc()->tokenizerOfStream(stream); |
| 721 if (tokenizer != NULL) { |
| 722 PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); |
| 723 looper.loop(); |
| 724 delete tokenizer; |
| 725 } |
| 1080 | 726 |
| 1081 // TODO(edisonn): should we restore the variable stack at the same state? | 727 // TODO(edisonn): should we restore the variable stack at the same state? |
| 1082 // There could be operands left, that could be consumed by a parent tokenize
r when we pop. | 728 // There could be operands left, that could be consumed by a parent tokenize
r when we pop. |
| 1083 canvas->restore(); | 729 canvas->restore(); |
| 1084 PdfOp_Q(pdfContext, canvas, NULL); | 730 PdfOp_Q(pdfContext, canvas, NULL); |
| 1085 return ret; | 731 |
| 732 return kPartial_PdfResult; |
| 1086 } | 733 } |
| 1087 | 734 |
| 1088 | 735 |
| 1089 // TODO(edisonn): faster, have the property on the SkPdfObject itself? | 736 // TODO(edisonn): faster, have the property on the SkPdfObject itself? |
| 1090 std::set<const PdfObject*> gInRendering; | 737 std::set<const void*> gInRendering; |
| 1091 | 738 |
| 1092 class CheckRecursiveRendering { | 739 class CheckRecursiveRendering { |
| 1093 const PdfObject& fObj; | 740 const void* fUniqueData; |
| 1094 public: | 741 public: |
| 1095 CheckRecursiveRendering(const PdfObject& obj) : fObj(obj) { | 742 CheckRecursiveRendering(const SkPdfObject* obj) : fUniqueData(obj->data()) { |
| 1096 gInRendering.insert(&obj); | 743 gInRendering.insert(obj); |
| 1097 } | 744 } |
| 1098 | 745 |
| 1099 ~CheckRecursiveRendering() { | 746 ~CheckRecursiveRendering() { |
| 1100 //SkASSERT(fObj.fInRendering); | 747 //SkASSERT(fObj.fInRendering); |
| 1101 gInRendering.erase(&fObj); | 748 gInRendering.erase(fUniqueData); |
| 1102 } | 749 } |
| 1103 | 750 |
| 1104 static bool IsInRendering(const PdfObject& obj) { | 751 static bool IsInRendering(const SkPdfObject* obj) { |
| 1105 return gInRendering.find(&obj) != gInRendering.end(); | 752 return gInRendering.find(obj->data()) != gInRendering.end(); |
| 1106 } | 753 } |
| 1107 }; | 754 }; |
| 1108 | 755 |
| 1109 PdfResult doXObject(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObject&
obj) { | 756 PdfResult doXObject(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObject&
obj) { |
| 1110 if (CheckRecursiveRendering::IsInRendering(*obj.podofo())) { | 757 if (CheckRecursiveRendering::IsInRendering(&obj)) { |
| 1111 // Oops, corrupt PDF! | 758 // Oops, corrupt PDF! |
| 1112 return kIgnoreError_PdfResult; | 759 return kIgnoreError_PdfResult; |
| 1113 } | 760 } |
| 1114 | 761 |
| 1115 CheckRecursiveRendering checkRecursion(*obj.podofo()); | 762 CheckRecursiveRendering checkRecursion(&obj); |
| 1116 | 763 |
| 1117 // TODO(edisonn): check type | 764 // TODO(edisonn): check type |
| 1118 SkPdfXObjectDictionary* skobj = NULL; | 765 SkPdfXObjectDictionary* skobj = NULL; |
| 1119 if (!mapXObjectDictionary(obj, &skobj)) return kIgnoreError_PdfResult; | 766 if (!obj.doc()->mapper()->mapXObjectDictionary(&obj, &skobj)) return kIgnore
Error_PdfResult; |
| 1120 | 767 |
| 1121 if (!skobj || !skobj->valid()) return kIgnoreError_PdfResult; | 768 if (!skobj) return kIgnoreError_PdfResult; |
| 1122 | 769 |
| 1123 PdfResult ret = kIgnoreError_PdfResult; | 770 PdfResult ret = kIgnoreError_PdfResult; |
| 1124 switch (skobj->getType()) | 771 switch (skobj->getType()) |
| 1125 { | 772 { |
| 1126 case kImageDictionary_SkPdfObjectType: | 773 case kImageDictionary_SkPdfObjectType: |
| 1127 ret = doXObject_Image(pdfContext, canvas, skobj->asImageDictionary()
); | 774 ret = doXObject_Image(pdfContext, canvas, skobj->asImageDictionary()
); |
| 1128 break; | 775 break; |
| 1129 case kType1FormDictionary_SkPdfObjectType: | 776 case kType1FormDictionary_SkPdfObjectType: |
| 1130 ret = doXObject_Form(pdfContext, canvas, skobj->asType1FormDictionar
y()); | 777 ret = doXObject_Form(pdfContext, canvas, skobj->asType1FormDictionar
y()); |
| 1131 break; | 778 break; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 SkMatrix matrix = SkMatrixFromPdfMatrix(array); | 818 SkMatrix matrix = SkMatrixFromPdfMatrix(array); |
| 1172 | 819 |
| 1173 pdfContext->fGraphicsState.fMatrix.preConcat(matrix); | 820 pdfContext->fGraphicsState.fMatrix.preConcat(matrix); |
| 1174 | 821 |
| 1175 #ifdef PDF_TRACE | 822 #ifdef PDF_TRACE |
| 1176 printf("cm "); | 823 printf("cm "); |
| 1177 for (int i = 0 ; i < 6 ; i++) { | 824 for (int i = 0 ; i < 6 ; i++) { |
| 1178 printf("%f ", array[i]); | 825 printf("%f ", array[i]); |
| 1179 } | 826 } |
| 1180 printf("\n"); | 827 printf("\n"); |
| 1181 SkTraceMatrix(pdfContext->fGraphicsState.fMatrix); | 828 SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "cm"); |
| 1182 #endif | 829 #endif |
| 1183 | 830 |
| 1184 return kOK_PdfResult; | 831 return kOK_PdfResult; |
| 1185 } | 832 } |
| 1186 | 833 |
| 1187 //leading TL Set the text leading, Tl | 834 //leading TL Set the text leading, Tl |
| 1188 //, to leading, which is a number expressed in unscaled text | 835 //, to leading, which is a number expressed in unscaled text |
| 1189 //space units. Text leading is used only by the T*, ', and " operators. Initial
value: 0. | 836 //space units. Text leading is used only by the T*, ', and " operators. Initial
value: 0. |
| 1190 PdfResult PdfOp_TL(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 837 PdfResult PdfOp_TL(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1191 double ty = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext-
>fObjectStack.pop(); | 838 double ty = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext-
>fObjectStack.pop(); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1206 pdfContext->fGraphicsState.fMatrixTlm.preConcat(matrix); | 853 pdfContext->fGraphicsState.fMatrixTlm.preConcat(matrix); |
| 1207 | 854 |
| 1208 return kPartial_PdfResult; | 855 return kPartial_PdfResult; |
| 1209 } | 856 } |
| 1210 | 857 |
| 1211 PdfResult PdfOp_TD(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 858 PdfResult PdfOp_TD(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1212 double ty = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext-
>fObjectStack.pop(); | 859 double ty = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext-
>fObjectStack.pop(); |
| 1213 double tx = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext-
>fObjectStack.pop(); | 860 double tx = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext-
>fObjectStack.pop(); |
| 1214 | 861 |
| 1215 // TODO(edisonn): Create factory methods or constructors so podofo is hidden | 862 // TODO(edisonn): Create factory methods or constructors so podofo is hidden |
| 1216 PdfObject _ty(PdfVariant(-ty)); | 863 SkPdfNumber* _ty = pdfContext->fPdfDoc->createNumber(-ty); |
| 1217 pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo()
, &_ty)); | 864 pdfContext->fObjectStack.push(_ty); |
| 1218 | 865 |
| 1219 PdfOp_TL(pdfContext, canvas, looper); | 866 PdfOp_TL(pdfContext, canvas, looper); |
| 1220 | 867 |
| 1221 PdfObject vtx(PdfVariant(-(-tx))); // TODO(edisonn): Hmm, the compiler thin
ks I have here a function pointer if we use (tx), but not -(-tx) | 868 SkPdfNumber* vtx = pdfContext->fPdfDoc->createNumber(tx); |
| 1222 pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo()
, &vtx)); | 869 pdfContext->fObjectStack.push(vtx); |
| 1223 | 870 |
| 1224 PdfObject vty(PdfVariant(-(-ty))); | 871 SkPdfNumber* vty = pdfContext->fPdfDoc->createNumber(ty); |
| 1225 pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo()
, &vty)); | 872 pdfContext->fObjectStack.push(vty); |
| 1226 | 873 |
| 1227 return PdfOp_Td(pdfContext, canvas, looper); | 874 PdfResult ret = PdfOp_Td(pdfContext, canvas, looper); |
| 875 |
| 876 // TODO(edisonn): delete all the objects after rendering was complete, in th
is way pdf is rendered faster |
| 877 // and the cleanup can happen while the user looks at the image |
| 878 delete _ty; |
| 879 delete vtx; |
| 880 delete vty; |
| 881 |
| 882 return ret; |
| 1228 } | 883 } |
| 1229 | 884 |
| 1230 PdfResult PdfOp_Tm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 885 PdfResult PdfOp_Tm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1231 double f = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); | 886 double f = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); |
| 1232 double e = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); | 887 double e = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); |
| 1233 double d = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); | 888 double d = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); |
| 1234 double c = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); | 889 double c = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); |
| 1235 double b = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); | 890 double b = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); |
| 1236 double a = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); | 891 double a = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->
fObjectStack.pop(); |
| 1237 | 892 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1250 pdfContext->fGraphicsState.fMatrixTm = matrix; | 905 pdfContext->fGraphicsState.fMatrixTm = matrix; |
| 1251 pdfContext->fGraphicsState.fMatrixTlm = matrix;; | 906 pdfContext->fGraphicsState.fMatrixTlm = matrix;; |
| 1252 | 907 |
| 1253 return kPartial_PdfResult; | 908 return kPartial_PdfResult; |
| 1254 } | 909 } |
| 1255 | 910 |
| 1256 //— T* Move to the start of the next line. This operator has the same effect as
the code | 911 //— T* Move to the start of the next line. This operator has the same effect as
the code |
| 1257 //0 Tl Td | 912 //0 Tl Td |
| 1258 //where Tl is the current leading parameter in the text state | 913 //where Tl is the current leading parameter in the text state |
| 1259 PdfResult PdfOp_T_star(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper*
* looper) { | 914 PdfResult PdfOp_T_star(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper*
* looper) { |
| 1260 PdfObject zero(PdfVariant(0.0)); | 915 SkPdfNumber* zero = pdfContext->fPdfDoc->createNumber(0.0); |
| 1261 PdfObject tl(PdfVariant(-(-pdfContext->fGraphicsState.fTextLeading))); | 916 SkPdfNumber* tl = pdfContext->fPdfDoc->createNumber(pdfContext->fGraphicsSta
te.fTextLeading); |
| 1262 | 917 |
| 1263 pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo()
, &zero)); | 918 pdfContext->fObjectStack.push(zero); |
| 1264 pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo()
, &tl)); | 919 pdfContext->fObjectStack.push(tl); |
| 1265 return PdfOp_Td(pdfContext, canvas, looper); | 920 |
| 921 PdfResult ret = PdfOp_Td(pdfContext, canvas, looper); |
| 922 |
| 923 delete zero; // TODO(edisonn): do not alocate and delete constants! |
| 924 delete tl; |
| 925 |
| 926 return ret; |
| 1266 } | 927 } |
| 1267 | 928 |
| 1268 PdfResult PdfOp_m(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per) { | 929 PdfResult PdfOp_m(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per) { |
| 1269 if (pdfContext->fGraphicsState.fPathClosed) { | 930 if (pdfContext->fGraphicsState.fPathClosed) { |
| 1270 pdfContext->fGraphicsState.fPath.reset(); | 931 pdfContext->fGraphicsState.fPath.reset(); |
| 1271 pdfContext->fGraphicsState.fPathClosed = false; | 932 pdfContext->fGraphicsState.fPathClosed = false; |
| 1272 } | 933 } |
| 1273 | 934 |
| 1274 pdfContext->fGraphicsState.fCurPosY = pdfContext->fObjectStack.top()->asNumb
er()->value(); pdfContext->fObjectStack.pop(); | 935 pdfContext->fGraphicsState.fCurPosY = pdfContext->fObjectStack.top()->asNumb
er()->value(); pdfContext->fObjectStack.pop(); |
| 1275 pdfContext->fGraphicsState.fCurPosX = pdfContext->fObjectStack.top()->asNumb
er()->value(); pdfContext->fObjectStack.pop(); | 936 pdfContext->fGraphicsState.fCurPosX = pdfContext->fObjectStack.top()->asNumb
er()->value(); pdfContext->fObjectStack.pop(); |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1518 //, to font and the text font size, Tfs, to size. font is the name of a | 1179 //, to font and the text font size, Tfs, to size. font is the name of a |
| 1519 //font resource in the Fontsubdictionary of the current resource dictionary; siz
e is | 1180 //font resource in the Fontsubdictionary of the current resource dictionary; siz
e is |
| 1520 //a number representing a scale factor. There is no initial value for either fon
t or | 1181 //a number representing a scale factor. There is no initial value for either fon
t or |
| 1521 //size; they must be specified explicitly using Tf before any text is shown. | 1182 //size; they must be specified explicitly using Tf before any text is shown. |
| 1522 PdfResult PdfOp_Tf(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 1183 PdfResult PdfOp_Tf(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1523 pdfContext->fGraphicsState.fCurFontSize = pdfContext->fObjectStack.top()->as
Number()->value(); pdfContext->fObjectStack.pop(); | 1184 pdfContext->fGraphicsState.fCurFontSize = pdfContext->fObjectStack.top()->as
Number()->value(); pdfContext->fObjectStack.pop(); |
| 1524 std::string fontName = pdfContext->fObjectStack.top()->asName()->value();
pdfContext->fObjectStack.pop(); | 1185 std::string fontName = pdfContext->fObjectStack.top()->asName()->value();
pdfContext->fObjectStack.pop(); |
| 1525 | 1186 |
| 1526 #ifdef PDF_TRACE | 1187 #ifdef PDF_TRACE |
| 1527 printf("font name: %s\n", fontName.c_str()); | 1188 printf("font name: %s\n", fontName.c_str()); |
| 1528 std::string str; | |
| 1529 pdfContext->fGraphicsState.fResources->podofo()->ToString(str); | |
| 1530 printf("Print Tf Resources: %s\n", str.c_str()); | |
| 1531 pdfContext->fGraphicsState.fResources->Font()->podofo()->ToString(str); | |
| 1532 printf("Print Tf Resources/Font: %s\n", str.c_str()); | |
| 1533 #endif | 1189 #endif |
| 1534 | 1190 |
| 1535 SkPdfFontDictionary* fd = NULL; | 1191 SkPdfFontDictionary* fd = NULL; |
| 1536 if (pdfContext->fGraphicsState.fResources->Font()) { | 1192 if (pdfContext->fGraphicsState.fResources->Font()) { |
| 1537 SkPdfObject* objFont = pdfContext->fGraphicsState.fResources->Font()->ge
t(fontName.c_str()); | 1193 SkPdfObject* objFont = pdfContext->fGraphicsState.fResources->Font()->ge
t(fontName.c_str()); |
| 1538 mapFontDictionary(*objFont, &fd); | 1194 objFont->doc()->mapper()->mapFontDictionary(objFont, &fd); |
| 1539 | |
| 1540 #ifdef PDF_TRACE | |
| 1541 objFont->podofo()->ToString(str); | |
| 1542 printf("Print Font loaded: %s\n", str.c_str()); | |
| 1543 fd->podofo()->ToString(str); | |
| 1544 printf("Print Font loaded and resolved and upgraded: %s\n", str.c_str())
; | |
| 1545 #endif | |
| 1546 | |
| 1547 } | 1195 } |
| 1548 | 1196 |
| 1549 SkPdfFont* skfont = SkPdfFont::fontFromPdfDictionary(fd); | 1197 SkPdfFont* skfont = SkPdfFont::fontFromPdfDictionary(fd); |
| 1550 | 1198 |
| 1551 if (skfont) { | 1199 if (skfont) { |
| 1552 pdfContext->fGraphicsState.fSkFont = skfont; | 1200 pdfContext->fGraphicsState.fSkFont = skfont; |
| 1553 } | 1201 } |
| 1554 | 1202 |
| 1555 return kPartial_PdfResult; | 1203 return kPartial_PdfResult; |
| 1556 } | 1204 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1631 SkDoubleToScalar(0), | 1279 SkDoubleToScalar(0), |
| 1632 SkDoubleToScalar(0), | 1280 SkDoubleToScalar(0), |
| 1633 SkDoubleToScalar(1)); | 1281 SkDoubleToScalar(1)); |
| 1634 | 1282 |
| 1635 pdfContext->fGraphicsState.fMatrixTm.preConcat(matrix); | 1283 pdfContext->fGraphicsState.fMatrixTm.preConcat(matrix); |
| 1636 } | 1284 } |
| 1637 } | 1285 } |
| 1638 return kPartial_PdfResult; // TODO(edisonn): Implement fully DrawText befor
e returing OK. | 1286 return kPartial_PdfResult; // TODO(edisonn): Implement fully DrawText befor
e returing OK. |
| 1639 } | 1287 } |
| 1640 | 1288 |
| 1641 PdfResult PdfOp_CS_cs(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator
* colorOperator) { | 1289 PdfResult PdfOp_CS_cs(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperat
or* colorOperator) { |
| 1642 colorOperator->fColorSpace = pdfContext->fObjectStack.top()->asName()->value
(); pdfContext->fObjectStack.pop(); | 1290 colorOperator->fColorSpace = pdfContext->fObjectStack.top()->asName()->value
(); pdfContext->fObjectStack.pop(); |
| 1643 return kOK_PdfResult; | 1291 return kOK_PdfResult; |
| 1644 } | 1292 } |
| 1645 | 1293 |
| 1646 PdfResult PdfOp_CS(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 1294 PdfResult PdfOp_CS(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1647 return PdfOp_CS_cs(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking
); | 1295 return PdfOp_CS_cs(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking
); |
| 1648 } | 1296 } |
| 1649 | 1297 |
| 1650 PdfResult PdfOp_cs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 1298 PdfResult PdfOp_cs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1651 return PdfOp_CS_cs(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrok
ing); | 1299 return PdfOp_CS_cs(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrok
ing); |
| 1652 } | 1300 } |
| 1653 | 1301 |
| 1654 PdfResult PdfOp_SC_sc(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator
* colorOperator) { | 1302 PdfResult PdfOp_SC_sc(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperat
or* colorOperator) { |
| 1655 double c[4]; | 1303 double c[4]; |
| 1656 pdf_int64 v[4]; | 1304 pdf_int64 v[4]; |
| 1657 | 1305 |
| 1658 int n = GetColorSpaceComponents(colorOperator->fColorSpace); | 1306 int n = GetColorSpaceComponents(colorOperator->fColorSpace); |
| 1659 | 1307 |
| 1660 bool doubles = true; | 1308 bool doubles = true; |
| 1661 if (colorOperator->fColorSpace == "Indexed") { | 1309 if (colorOperator->fColorSpace == "Indexed") { |
| 1662 doubles = false; | 1310 doubles = false; |
| 1663 } | 1311 } |
| 1664 | 1312 |
| 1665 #ifdef PDF_TRACE | 1313 #ifdef PDF_TRACE |
| 1666 printf("color space = %s, N = %i\n", colorOperator->fColorSpace.c_str(), n); | 1314 printf("color space = %s, N = %i\n", colorOperator->fColorSpace.c_str(), n); |
| 1667 #endif | 1315 #endif |
| 1668 | 1316 |
| 1669 for (int i = n - 1; i >= 0 ; i--) { | 1317 for (int i = n - 1; i >= 0 ; i--) { |
| 1670 if (doubles) { | 1318 if (doubles) { |
| 1671 c[i] = pdfContext->fObjectStack.top()->asNumber()->value(); pdfC
ontext->fObjectStack.pop(); | 1319 c[i] = pdfContext->fObjectStack.top()->asNumber()->value();
pdfContext->fObjectStack.pop(); |
| 1672 } else { | 1320 } else { |
| 1673 v[i] = pdfContext->fObjectStack.top()->asInteger()->value(); pdfCo
ntext->fObjectStack.pop(); | 1321 v[i] = pdfContext->fObjectStack.top()->asInteger()->value();
pdfContext->fObjectStack.pop(); |
| 1674 } | 1322 } |
| 1675 } | 1323 } |
| 1676 | 1324 |
| 1677 // TODO(edisonn): Now, set that color. Only DeviceRGB supported. | 1325 // TODO(edisonn): Now, set that color. Only DeviceRGB supported. |
| 1678 if (colorOperator->fColorSpace == "DeviceRGB") { | 1326 if (colorOperator->fColorSpace == "DeviceRGB") { |
| 1679 colorOperator->setRGBColor(SkColorSetRGB(255*c[0], 255*c[1], 255*c[2])); | 1327 colorOperator->setRGBColor(SkColorSetRGB(255*c[0], 255*c[1], 255*c[2])); |
| 1680 } | 1328 } |
| 1681 return kPartial_PdfResult; | 1329 return kPartial_PdfResult; |
| 1682 } | 1330 } |
| 1683 | 1331 |
| 1684 PdfResult PdfOp_SC(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 1332 PdfResult PdfOp_SC(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1685 return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking
); | 1333 return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking
); |
| 1686 } | 1334 } |
| 1687 | 1335 |
| 1688 PdfResult PdfOp_sc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 1336 PdfResult PdfOp_sc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1689 return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrok
ing); | 1337 return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrok
ing); |
| 1690 } | 1338 } |
| 1691 | 1339 |
| 1692 PdfResult PdfOp_SCN_scn(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperat
or* colorOperator) { | 1340 PdfResult PdfOp_SCN_scn(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOper
ator* colorOperator) { |
| 1693 PdfString name; | 1341 PdfString name; |
| 1694 | 1342 |
| 1695 if (pdfContext->fObjectStack.top()->asName()) { | 1343 if (pdfContext->fObjectStack.top()->asName()) { |
| 1696 pdfContext->fObjectStack.pop(); | 1344 pdfContext->fObjectStack.pop(); |
| 1697 } | 1345 } |
| 1698 | 1346 |
| 1699 // TODO(edisonn): SCN supports more color spaces than SCN. Read and implemen
t spec. | 1347 // TODO(edisonn): SCN supports more color spaces than SCN. Read and implemen
t spec. |
| 1700 PdfOp_SC_sc(pdfContext, canvas, colorOperator); | 1348 PdfOp_SC_sc(pdfContext, canvas, colorOperator); |
| 1701 | 1349 |
| 1702 return kPartial_PdfResult; | 1350 return kPartial_PdfResult; |
| 1703 } | 1351 } |
| 1704 | 1352 |
| 1705 PdfResult PdfOp_SCN(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** l
ooper) { | 1353 PdfResult PdfOp_SCN(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** l
ooper) { |
| 1706 return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fStroki
ng); | 1354 return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fStroki
ng); |
| 1707 } | 1355 } |
| 1708 | 1356 |
| 1709 PdfResult PdfOp_scn(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** l
ooper) { | 1357 PdfResult PdfOp_scn(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** l
ooper) { |
| 1710 return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStr
oking); | 1358 return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStr
oking); |
| 1711 } | 1359 } |
| 1712 | 1360 |
| 1713 PdfResult PdfOp_G_g(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator*
colorOperator) { | 1361 PdfResult PdfOp_G_g(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator
* colorOperator) { |
| 1714 double gray = pdfContext->fObjectStack.top()->asNumber()->value(); pdfCo
ntext->fObjectStack.pop(); | 1362 double gray = pdfContext->fObjectStack.top()->asNumber()->value(); pdfCo
ntext->fObjectStack.pop(); |
| 1715 return kNYI_PdfResult; | 1363 return kNYI_PdfResult; |
| 1716 } | 1364 } |
| 1717 | 1365 |
| 1718 PdfResult PdfOp_G(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per) { | 1366 PdfResult PdfOp_G(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per) { |
| 1719 return PdfOp_G_g(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking); | 1367 return PdfOp_G_g(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking); |
| 1720 } | 1368 } |
| 1721 | 1369 |
| 1722 PdfResult PdfOp_g(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per) { | 1370 PdfResult PdfOp_g(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo
per) { |
| 1723 return PdfOp_G_g(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrokin
g); | 1371 return PdfOp_G_g(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrokin
g); |
| 1724 } | 1372 } |
| 1725 | 1373 |
| 1726 PdfResult PdfOp_RG_rg(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator
* colorOperator) { | 1374 PdfResult PdfOp_RG_rg(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperat
or* colorOperator) { |
| 1727 double b = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); | 1375 double b = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); |
| 1728 double g = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); | 1376 double g = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); |
| 1729 double r = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); | 1377 double r = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); |
| 1730 | 1378 |
| 1731 colorOperator->fColorSpace = "DeviceRGB"; | 1379 colorOperator->fColorSpace = "DeviceRGB"; |
| 1732 colorOperator->setRGBColor(SkColorSetRGB(255*r, 255*g, 255*b)); | 1380 colorOperator->setRGBColor(SkColorSetRGB(255*r, 255*g, 255*b)); |
| 1733 return kOK_PdfResult; | 1381 return kOK_PdfResult; |
| 1734 } | 1382 } |
| 1735 | 1383 |
| 1736 PdfResult PdfOp_RG(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 1384 PdfResult PdfOp_RG(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1737 return PdfOp_RG_rg(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking
); | 1385 return PdfOp_RG_rg(pdfContext, canvas, &pdfContext->fGraphicsState.fStroking
); |
| 1738 } | 1386 } |
| 1739 | 1387 |
| 1740 PdfResult PdfOp_rg(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { | 1388 PdfResult PdfOp_rg(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo
oper) { |
| 1741 return PdfOp_RG_rg(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrok
ing); | 1389 return PdfOp_RG_rg(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrok
ing); |
| 1742 } | 1390 } |
| 1743 | 1391 |
| 1744 PdfResult PdfOp_K_k(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator*
colorOperator) { | 1392 PdfResult PdfOp_K_k(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator
* colorOperator) { |
| 1745 // TODO(edisonn): spec has some rules about overprint, implement them. | 1393 // TODO(edisonn): spec has some rules about overprint, implement them. |
| 1746 double k = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); | 1394 double k = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); |
| 1747 double y = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); | 1395 double y = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); |
| 1748 double m = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); | 1396 double m = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); |
| 1749 double c = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); | 1397 double c = pdfContext->fObjectStack.top()->asNumber()->value(); pdfConte
xt->fObjectStack.pop(); |
| 1750 | 1398 |
| 1751 colorOperator->fColorSpace = "DeviceCMYK"; | 1399 colorOperator->fColorSpace = "DeviceCMYK"; |
| 1752 // TODO(edisonn): Set color. | 1400 // TODO(edisonn): Set color. |
| 1753 return kNYI_PdfResult; | 1401 return kNYI_PdfResult; |
| 1754 } | 1402 } |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1889 | 1537 |
| 1890 if (extGStateDictionary == NULL) { | 1538 if (extGStateDictionary == NULL) { |
| 1891 #ifdef PDF_TRACE | 1539 #ifdef PDF_TRACE |
| 1892 printf("ExtGState is NULL!\n"); | 1540 printf("ExtGState is NULL!\n"); |
| 1893 #endif | 1541 #endif |
| 1894 return kIgnoreError_PdfResult; | 1542 return kIgnoreError_PdfResult; |
| 1895 } | 1543 } |
| 1896 | 1544 |
| 1897 SkPdfObject* value = extGStateDictionary->get(name.c_str()); | 1545 SkPdfObject* value = extGStateDictionary->get(name.c_str()); |
| 1898 | 1546 |
| 1899 #ifdef PDF_TRACE | |
| 1900 // value->ToString(str); | |
| 1901 // printf("gs object value: %s\n", str.c_str()); | |
| 1902 #endif | |
| 1903 | |
| 1904 SkPdfGraphicsStateDictionary* gs = NULL; | 1547 SkPdfGraphicsStateDictionary* gs = NULL; |
| 1905 mapGraphicsStateDictionary(*value, &gs); | 1548 value->doc()->mapper()->mapGraphicsStateDictionary(value, &gs); |
| 1906 | 1549 |
| 1907 // TODO(edisonn): now load all those properties in graphic state. | 1550 // TODO(edisonn): now load all those properties in graphic state. |
| 1908 if (gs == NULL) { | 1551 if (gs == NULL) { |
| 1909 return kIgnoreError_PdfResult; | 1552 return kIgnoreError_PdfResult; |
| 1910 } | 1553 } |
| 1911 | 1554 |
| 1912 if (gs->has_CA()) { | 1555 if (gs->has_CA()) { |
| 1913 pdfContext->fGraphicsState.fStroking.fOpacity = gs->CA(); | 1556 pdfContext->fGraphicsState.fStroking.fOpacity = gs->CA(); |
| 1914 } | 1557 } |
| 1915 | 1558 |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2293 // e.g. SkBitmap getPage(int page); | 1936 // e.g. SkBitmap getPage(int page); |
| 2294 // int formsCount(); | 1937 // int formsCount(); |
| 2295 // SkForm getForm(int formID); // SkForm(SkRect, .. other data) | 1938 // SkForm getForm(int formID); // SkForm(SkRect, .. other data) |
| 2296 // TODO (edisonn): Add intend when loading pdf, for example: for viewing, parsin
g all content, ... | 1939 // TODO (edisonn): Add intend when loading pdf, for example: for viewing, parsin
g all content, ... |
| 2297 // if we load the first page, and we zoom to fit to screen horizontally, then lo
ad only those | 1940 // if we load the first page, and we zoom to fit to screen horizontally, then lo
ad only those |
| 2298 // resources needed, so the preview is fast. | 1941 // resources needed, so the preview is fast. |
| 2299 // TODO (edisonn): hide parser/tokenizer behind and interface and a query langua
ge, and resolve | 1942 // TODO (edisonn): hide parser/tokenizer behind and interface and a query langua
ge, and resolve |
| 2300 // references automatically. | 1943 // references automatically. |
| 2301 | 1944 |
| 2302 bool SkPdfViewer::load(const SkString inputFileName, SkPicture* out) { | 1945 bool SkPdfViewer::load(const SkString inputFileName, SkPicture* out) { |
| 2303 try | 1946 std::cout << "Init: " << inputFileName.c_str() << std::endl; |
| 1947 |
| 1948 SkPodofoParsedPDF* doc = new SkPodofoParsedPDF(inputFileName.c_str()); |
| 1949 if (!doc->pages()) |
| 2304 { | 1950 { |
| 2305 std::cout << "Init: " << inputFileName.c_str() << std::endl; | 1951 std::cout << "ERROR: Empty Document" << inputFileName.c_str() << std::en
dl; |
| 1952 return false; |
| 1953 } else { |
| 2306 | 1954 |
| 2307 SkPdfDoc doc(inputFileName.c_str()); | 1955 for (int pn = 0; pn < doc->pages(); ++pn) { |
| 2308 if (!doc.pages()) | 1956 // TODO(edisonn): implement inheritance properties as per PDF spec |
| 2309 { | 1957 //SkRect rect = page->MediaBox(); |
| 2310 std::cout << "ERROR: Empty Document" << inputFileName.c_str() << std
::endl; | 1958 SkRect rect = doc->MediaBox(pn); |
| 2311 return false; | |
| 2312 } else { | |
| 2313 | 1959 |
| 2314 for (int pn = 0; pn < doc.pages(); ++pn) { | 1960 #ifdef PDF_TRACE |
| 2315 // TODO(edisonn): implement inheritance properties as per PDF sp
ec | 1961 printf("Page Width: %f, Page Height: %f\n", SkScalarToDouble(rect.wi
dth()), SkScalarToDouble(rect.height())); |
| 2316 //SkRect rect = page->MediaBox(); | 1962 #endif |
| 2317 SkRect rect = doc.MediaBox(pn); | |
| 2318 | 1963 |
| 2319 #ifdef PDF_TRACE | 1964 // TODO(edisonn): page->GetCropBox(), page->GetTrimBox() ... how to
use? |
| 2320 printf("Page Width: %f, Page Height: %f\n", SkScalarToDouble(rec
t.width()), SkScalarToDouble(rect.height())); | |
| 2321 #endif | |
| 2322 | 1965 |
| 2323 // TODO(edisonn): page->GetCropBox(), page->GetTrimBox() ... how
to use? | 1966 SkBitmap bitmap; |
| 1967 #ifdef PDF_DEBUG_3X |
| 1968 setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(rect.width()), 3 * (
int)SkScalarToDouble(rect.height())); |
| 1969 #else |
| 1970 setup_bitmap(&bitmap, (int)SkScalarToDouble(rect.width()), (int)SkSc
alarToDouble(rect.height())); |
| 1971 #endif |
| 1972 SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap))); |
| 1973 SkCanvas canvas(device); |
| 2324 | 1974 |
| 2325 SkBitmap bitmap; | 1975 gDumpBitmap = &bitmap; |
| 2326 #ifdef PDF_DEBUG_3X | |
| 2327 setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(rect.width()), 3
* (int)SkScalarToDouble(rect.height())); | |
| 2328 #else | |
| 2329 setup_bitmap(&bitmap, (int)SkScalarToDouble(rect.width()), (int)
SkScalarToDouble(rect.height())); | |
| 2330 #endif | |
| 2331 SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap))); | |
| 2332 SkCanvas canvas(device); | |
| 2333 | 1976 |
| 2334 gDumpBitmap = &bitmap; | 1977 gDumpCanvas = &canvas; |
| 1978 doc->drawPage(pn, &canvas); |
| 2335 | 1979 |
| 2336 doc.drawPage(pn, &canvas); | 1980 SkString out; |
| 2337 | 1981 if (doc->pages() > 1) { |
| 2338 SkString out; | 1982 out.appendf("%s-%i.png", inputFileName.c_str(), pn); |
| 2339 if (doc.pages() > 1) { | 1983 } else { |
| 2340 out.appendf("%s-%i.png", inputFileName.c_str(), pn); | 1984 out = inputFileName; |
| 2341 } else { | 1985 // .pdf -> .png |
| 2342 out = inputFileName; | 1986 out[out.size() - 2] = 'n'; |
| 2343 // .pdf -> .png | 1987 out[out.size() - 1] = 'g'; |
| 2344 out[out.size() - 2] = 'n'; | |
| 2345 out[out.size() - 1] = 'g'; | |
| 2346 } | |
| 2347 SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::
kPNG_Type, 100); | |
| 2348 } | 1988 } |
| 2349 return true; | 1989 SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::kPNG
_Type, 100); |
| 2350 } | 1990 } |
| 2351 } | 1991 return true; |
| 2352 catch( PdfError & e ) | |
| 2353 { | |
| 2354 e.PrintErrorMsg(); | |
| 2355 std::cout << "ERROR: PDF can't be parsed!" << inputFileName.c_str() << s
td::endl; | |
| 2356 return false; | |
| 2357 } | 1992 } |
| 2358 | 1993 |
| 2359 return true; | 1994 return true; |
| 2360 } | 1995 } |
| OLD | NEW |