OLD | NEW |
1 // Copyright 2016 PDFium Authors. All rights reserved. | 1 // Copyright 2016 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "core/fpdfdoc/cpvt_generateap.h" | 7 #include "core/fpdfdoc/cpvt_generateap.h" |
8 | 8 |
9 #include "core/fpdfapi/fpdf_font/include/cpdf_font.h" | 9 #include "core/fpdfapi/fpdf_font/include/cpdf_font.h" |
10 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" | 10 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); | 445 pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); |
446 } else { | 446 } else { |
447 pStreamDict->SetAt("Resources", pFormDict->GetDictBy("DR")->Clone()); | 447 pStreamDict->SetAt("Resources", pFormDict->GetDictBy("DR")->Clone()); |
448 pStreamResList = pStreamDict->GetDictBy("Resources"); | 448 pStreamResList = pStreamDict->GetDictBy("Resources"); |
449 } | 449 } |
450 } | 450 } |
451 } | 451 } |
452 return true; | 452 return true; |
453 } | 453 } |
454 | 454 |
455 CFX_ByteString GetColorStringWithDefault(CPDF_Dictionary* pAnnotDict, | 455 CFX_ByteString GetColorStringWithDefault(CPDF_Array* pColor, |
456 const CPVT_Color& crDefaultColor, | 456 const CPVT_Color& crDefaultColor, |
457 PaintOperation nOperation) { | 457 PaintOperation nOperation) { |
458 if (CPDF_Array* pColor = pAnnotDict->GetArrayBy("C")) { | 458 if (pColor) { |
459 CPVT_Color color = CPVT_Color::ParseColor(*pColor); | 459 CPVT_Color color = CPVT_Color::ParseColor(*pColor); |
460 return CPVT_GenerateAP::GenerateColorAP(color, nOperation); | 460 return CPVT_GenerateAP::GenerateColorAP(color, nOperation); |
461 } | 461 } |
462 | 462 |
463 return CPVT_GenerateAP::GenerateColorAP(crDefaultColor, nOperation); | 463 return CPVT_GenerateAP::GenerateColorAP(crDefaultColor, nOperation); |
464 } | 464 } |
465 | 465 |
| 466 FX_FLOAT GetBorderWidth(const CPDF_Dictionary& pAnnotDict) { |
| 467 if (CPDF_Dictionary* pBorderStyleDict = pAnnotDict.GetDictBy("BS")) { |
| 468 if (pBorderStyleDict->KeyExist("W")) |
| 469 return pBorderStyleDict->GetNumberBy("W"); |
| 470 } |
| 471 |
| 472 if (CPDF_Array* pBorderArray = pAnnotDict.GetArrayBy("Border")) { |
| 473 if (pBorderArray->GetCount() > 2) |
| 474 return pBorderArray->GetNumberAt(2); |
| 475 } |
| 476 |
| 477 return 1; |
| 478 } |
| 479 |
| 480 CPDF_Array* GetDashArray(const CPDF_Dictionary& pAnnotDict) { |
| 481 if (CPDF_Dictionary* pBorderStyleDict = pAnnotDict.GetDictBy("BS")) { |
| 482 if (pBorderStyleDict->GetStringBy("S") == "D") |
| 483 return pBorderStyleDict->GetArrayBy("D"); |
| 484 } |
| 485 |
| 486 if (CPDF_Array* pBorderArray = pAnnotDict.GetArrayBy("Border")) { |
| 487 if (pBorderArray->GetCount() == 4) |
| 488 return pBorderArray->GetArrayAt(3); |
| 489 } |
| 490 |
| 491 return nullptr; |
| 492 } |
| 493 |
| 494 CFX_ByteString GetDashPatternString(const CPDF_Dictionary& pAnnotDict) { |
| 495 CPDF_Array* pDashArray = GetDashArray(pAnnotDict); |
| 496 if (!pDashArray || pDashArray->IsEmpty()) |
| 497 return CFX_ByteString(); |
| 498 |
| 499 // Support maximum of ten elements in the dash array. |
| 500 size_t pDashArrayCount = std::min<size_t>(pDashArray->GetCount(), 10); |
| 501 CFX_ByteTextBuf sDashStream; |
| 502 |
| 503 sDashStream << "["; |
| 504 for (size_t i = 0; i < pDashArrayCount; ++i) |
| 505 sDashStream << pDashArray->GetNumberAt(i) << " "; |
| 506 sDashStream << "] 0 d\n"; |
| 507 |
| 508 return sDashStream.MakeString(); |
| 509 } |
| 510 |
466 CPDF_Dictionary* GenerateExtGStateDict(const CPDF_Dictionary& pAnnotDict, | 511 CPDF_Dictionary* GenerateExtGStateDict(const CPDF_Dictionary& pAnnotDict, |
467 const CFX_ByteString& sExtGSDictName, | 512 const CFX_ByteString& sExtGSDictName, |
468 const CFX_ByteString& sBlendMode) { | 513 const CFX_ByteString& sBlendMode) { |
469 CPDF_Dictionary* pGSDict = new CPDF_Dictionary; | 514 CPDF_Dictionary* pGSDict = new CPDF_Dictionary; |
470 pGSDict->SetAtString("Type", "ExtGState"); | 515 pGSDict->SetAtString("Type", "ExtGState"); |
471 | 516 |
472 FX_FLOAT fOpacity = | 517 FX_FLOAT fOpacity = |
473 pAnnotDict.KeyExist("CA") ? pAnnotDict.GetNumberBy("CA") : 1; | 518 pAnnotDict.KeyExist("CA") ? pAnnotDict.GetNumberBy("CA") : 1; |
474 pGSDict->SetAtNumber("CA", fOpacity); | 519 pGSDict->SetAtNumber("CA", fOpacity); |
475 pGSDict->SetAtNumber("ca", fOpacity); | 520 pGSDict->SetAtNumber("ca", fOpacity); |
(...skipping 28 matching lines...) Expand all Loading... |
504 | 549 |
505 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | 550 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
506 pStreamDict->SetAtRect("BBox", rect); | 551 pStreamDict->SetAtRect("BBox", rect); |
507 | 552 |
508 CPDF_Dictionary* pResourceDict = new CPDF_Dictionary; | 553 CPDF_Dictionary* pResourceDict = new CPDF_Dictionary; |
509 pResourceDict->SetAt("ExtGState", pExtGStateDict); | 554 pResourceDict->SetAt("ExtGState", pExtGStateDict); |
510 | 555 |
511 pStreamDict->SetAt("Resources", pResourceDict); | 556 pStreamDict->SetAt("Resources", pResourceDict); |
512 } | 557 } |
513 | 558 |
| 559 CFX_ByteString GetPaintOperatorString(bool bIsStrokeRect, bool bIsFillRect) { |
| 560 if (bIsStrokeRect) |
| 561 return bIsFillRect ? "b" : "s"; |
| 562 return bIsFillRect ? "f" : "n"; |
| 563 } |
| 564 |
514 } // namespace | 565 } // namespace |
515 | 566 |
516 bool FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { | 567 bool FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { |
517 if (!pAnnotDict || pAnnotDict->GetStringBy("Subtype") != "Widget") | 568 if (!pAnnotDict || pAnnotDict->GetStringBy("Subtype") != "Widget") |
518 return false; | 569 return false; |
519 | 570 |
520 CFX_ByteString field_type = FPDF_GetFieldAttr(pAnnotDict, "FT")->GetString(); | 571 CFX_ByteString field_type = FPDF_GetFieldAttr(pAnnotDict, "FT")->GetString(); |
521 uint32_t flags = FPDF_GetFieldAttr(pAnnotDict, "Ff") | 572 uint32_t flags = FPDF_GetFieldAttr(pAnnotDict, "Ff") |
522 ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() | 573 ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() |
523 : 0; | 574 : 0; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
565 CPDF_Dictionary* pAnnotDict) { | 616 CPDF_Dictionary* pAnnotDict) { |
566 // If AP dictionary exists, we use the appearance defined in the | 617 // If AP dictionary exists, we use the appearance defined in the |
567 // existing AP dictionary. | 618 // existing AP dictionary. |
568 if (pAnnotDict->KeyExist("AP")) | 619 if (pAnnotDict->KeyExist("AP")) |
569 return false; | 620 return false; |
570 | 621 |
571 CFX_ByteTextBuf sAppStream; | 622 CFX_ByteTextBuf sAppStream; |
572 CFX_ByteString sExtGSDictName = "GS"; | 623 CFX_ByteString sExtGSDictName = "GS"; |
573 sAppStream << "/" << sExtGSDictName << " gs "; | 624 sAppStream << "/" << sExtGSDictName << " gs "; |
574 | 625 |
575 sAppStream << GetColorStringWithDefault( | 626 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), |
576 pAnnotDict, CPVT_Color(CPVT_Color::kRGB, 1, 1, 0), PaintOperation::FILL); | 627 CPVT_Color(CPVT_Color::kRGB, 1, 1, 0), |
| 628 PaintOperation::FILL); |
577 | 629 |
578 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | 630 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
579 rect.Normalize(); | 631 rect.Normalize(); |
580 | 632 |
581 sAppStream << rect.left << " " << rect.top << " m " << rect.right << " " | 633 sAppStream << rect.left << " " << rect.top << " m " << rect.right << " " |
582 << rect.top << " l " << rect.right << " " << rect.bottom << " l " | 634 << rect.top << " l " << rect.right << " " << rect.bottom << " l " |
583 << rect.left << " " << rect.bottom << " l " | 635 << rect.left << " " << rect.bottom << " l " |
584 << "h f\n"; | 636 << "h f\n"; |
585 | 637 |
586 CPDF_Dictionary* pExtGStateDict = | 638 CPDF_Dictionary* pExtGStateDict = |
587 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Multiply"); | 639 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Multiply"); |
588 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); | 640 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); |
589 | 641 |
590 return true; | 642 return true; |
591 } | 643 } |
592 | 644 |
593 bool CPVT_GenerateAP::GenerateUnderlineAP(CPDF_Document* pDoc, | 645 bool CPVT_GenerateAP::GenerateUnderlineAP(CPDF_Document* pDoc, |
594 CPDF_Dictionary* pAnnotDict) { | 646 CPDF_Dictionary* pAnnotDict) { |
595 // If AP dictionary exists, we use the appearance defined in the | 647 // If AP dictionary exists, we use the appearance defined in the |
596 // existing AP dictionary. | 648 // existing AP dictionary. |
597 if (pAnnotDict->KeyExist("AP")) | 649 if (pAnnotDict->KeyExist("AP")) |
598 return false; | 650 return false; |
599 | 651 |
600 CFX_ByteTextBuf sAppStream; | 652 CFX_ByteTextBuf sAppStream; |
601 CFX_ByteString sExtGSDictName = "GS"; | 653 CFX_ByteString sExtGSDictName = "GS"; |
602 sAppStream << "/" << sExtGSDictName << " gs "; | 654 sAppStream << "/" << sExtGSDictName << " gs "; |
603 | 655 |
604 sAppStream << GetColorStringWithDefault(pAnnotDict, | 656 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), |
605 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), | 657 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), |
606 PaintOperation::STROKE); | 658 PaintOperation::STROKE); |
607 | 659 |
608 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | 660 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
609 rect.Normalize(); | 661 rect.Normalize(); |
610 | 662 |
611 FX_FLOAT fLineWidth = 1.0; | 663 FX_FLOAT fLineWidth = 1.0; |
612 sAppStream << fLineWidth << " w " << rect.left << " " | 664 sAppStream << fLineWidth << " w " << rect.left << " " |
613 << rect.bottom + fLineWidth << " m " << rect.right << " " | 665 << rect.bottom + fLineWidth << " m " << rect.right << " " |
614 << rect.bottom + fLineWidth << " l S\n"; | 666 << rect.bottom + fLineWidth << " l S\n"; |
615 | 667 |
616 CPDF_Dictionary* pExtGStateDict = | 668 CPDF_Dictionary* pExtGStateDict = |
617 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); | 669 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); |
618 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); | 670 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); |
619 return true; | 671 return true; |
620 } | 672 } |
621 | 673 |
| 674 bool CPVT_GenerateAP::GenerateSquareAP(CPDF_Document* pDoc, |
| 675 CPDF_Dictionary* pAnnotDict) { |
| 676 // If AP dictionary exists, we use the appearance defined in the |
| 677 // existing AP dictionary. |
| 678 if (pAnnotDict->KeyExist("AP")) |
| 679 return false; |
| 680 |
| 681 CFX_ByteTextBuf sAppStream; |
| 682 CFX_ByteString sExtGSDictName = "GS"; |
| 683 sAppStream << "/" << sExtGSDictName << " gs "; |
| 684 |
| 685 CPDF_Array* pInteriorColor = pAnnotDict->GetArrayBy("IC"); |
| 686 sAppStream << GetColorStringWithDefault(pInteriorColor, |
| 687 CPVT_Color(CPVT_Color::kTransparent), |
| 688 PaintOperation::FILL); |
| 689 |
| 690 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), |
| 691 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), |
| 692 PaintOperation::STROKE); |
| 693 |
| 694 FX_FLOAT fBorderWidth = GetBorderWidth(*pAnnotDict); |
| 695 bool bIsStrokeRect = fBorderWidth > 0; |
| 696 |
| 697 if (bIsStrokeRect) { |
| 698 sAppStream << fBorderWidth << " w "; |
| 699 sAppStream << GetDashPatternString(*pAnnotDict); |
| 700 } |
| 701 |
| 702 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
| 703 rect.Normalize(); |
| 704 |
| 705 if (bIsStrokeRect) { |
| 706 // Deflating rect because stroking a path entails painting all points whose |
| 707 // perpendicular distance from the path in user space is less than or equal |
| 708 // to half the line width. |
| 709 rect.Deflate(fBorderWidth / 2, fBorderWidth / 2); |
| 710 } |
| 711 |
| 712 bool bIsFillRect = pInteriorColor && (pInteriorColor->GetCount() > 0); |
| 713 |
| 714 sAppStream << rect.left << " " << rect.bottom << " " << rect.Width() << " " |
| 715 << rect.Height() << " re " |
| 716 << GetPaintOperatorString(bIsStrokeRect, bIsFillRect) << "\n"; |
| 717 |
| 718 CPDF_Dictionary* pExtGStateDict = |
| 719 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); |
| 720 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); |
| 721 return true; |
| 722 } |
| 723 |
622 bool CPVT_GenerateAP::GenerateSquigglyAP(CPDF_Document* pDoc, | 724 bool CPVT_GenerateAP::GenerateSquigglyAP(CPDF_Document* pDoc, |
623 CPDF_Dictionary* pAnnotDict) { | 725 CPDF_Dictionary* pAnnotDict) { |
624 // If AP dictionary exists, we use the appearance defined in the | 726 // If AP dictionary exists, we use the appearance defined in the |
625 // existing AP dictionary. | 727 // existing AP dictionary. |
626 if (pAnnotDict->KeyExist("AP")) | 728 if (pAnnotDict->KeyExist("AP")) |
627 return false; | 729 return false; |
628 | 730 |
629 CFX_ByteTextBuf sAppStream; | 731 CFX_ByteTextBuf sAppStream; |
630 CFX_ByteString sExtGSDictName = "GS"; | 732 CFX_ByteString sExtGSDictName = "GS"; |
631 sAppStream << "/" << sExtGSDictName << " gs "; | 733 sAppStream << "/" << sExtGSDictName << " gs "; |
632 | 734 |
633 sAppStream << GetColorStringWithDefault(pAnnotDict, | 735 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), |
634 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), | 736 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), |
635 PaintOperation::STROKE); | 737 PaintOperation::STROKE); |
636 | 738 |
637 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | 739 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
638 rect.Normalize(); | 740 rect.Normalize(); |
639 | 741 |
640 FX_FLOAT fLineWidth = 1.0; | 742 FX_FLOAT fLineWidth = 1.0; |
641 sAppStream << fLineWidth << " w "; | 743 sAppStream << fLineWidth << " w "; |
642 | 744 |
643 const FX_FLOAT fDelta = 2.0; | 745 const FX_FLOAT fDelta = 2.0; |
(...skipping 30 matching lines...) Expand all Loading... |
674 CPDF_Dictionary* pAnnotDict) { | 776 CPDF_Dictionary* pAnnotDict) { |
675 // If AP dictionary exists, we use the appearance defined in the | 777 // If AP dictionary exists, we use the appearance defined in the |
676 // existing AP dictionary. | 778 // existing AP dictionary. |
677 if (pAnnotDict->KeyExist("AP")) | 779 if (pAnnotDict->KeyExist("AP")) |
678 return false; | 780 return false; |
679 | 781 |
680 CFX_ByteTextBuf sAppStream; | 782 CFX_ByteTextBuf sAppStream; |
681 CFX_ByteString sExtGSDictName = "GS"; | 783 CFX_ByteString sExtGSDictName = "GS"; |
682 sAppStream << "/" << sExtGSDictName << " gs "; | 784 sAppStream << "/" << sExtGSDictName << " gs "; |
683 | 785 |
684 sAppStream << GetColorStringWithDefault(pAnnotDict, | 786 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), |
685 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), | 787 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), |
686 PaintOperation::STROKE); | 788 PaintOperation::STROKE); |
687 | 789 |
688 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | 790 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
689 rect.Normalize(); | 791 rect.Normalize(); |
690 | 792 |
691 FX_FLOAT fLineWidth = 1.0; | 793 FX_FLOAT fLineWidth = 1.0; |
692 FX_FLOAT fY = (rect.top + rect.bottom) / 2; | 794 FX_FLOAT fY = (rect.top + rect.bottom) / 2; |
693 sAppStream << fLineWidth << " w " << rect.left << " " << fY << " m " | 795 sAppStream << fLineWidth << " w " << rect.left << " " << fY << " m " |
694 << rect.right << " " << fY << " l S\n"; | 796 << rect.right << " " << fY << " l S\n"; |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
960 int32_t nFontIndex, | 1062 int32_t nFontIndex, |
961 FX_FLOAT fFontSize) { | 1063 FX_FLOAT fFontSize) { |
962 CFX_ByteTextBuf sRet; | 1064 CFX_ByteTextBuf sRet; |
963 if (pFontMap) { | 1065 if (pFontMap) { |
964 CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); | 1066 CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); |
965 if (sFontAlias.GetLength() > 0 && fFontSize > 0) | 1067 if (sFontAlias.GetLength() > 0 && fFontSize > 0) |
966 sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; | 1068 sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; |
967 } | 1069 } |
968 return sRet.MakeString(); | 1070 return sRet.MakeString(); |
969 } | 1071 } |
OLD | NEW |