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, |
Lei Zhang
2016/08/05 02:01:05
What prompted this change? Seemed fine before.
jaepark
2016/08/05 02:49:37
For Square annotation, stroke color is in "C" fiel
Lei Zhang
2016/08/05 17:27:29
Another option is to change this to:
enum class C
jaepark
2016/08/05 19:02:19
Acknowledged.
| |
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"); | |
Lei Zhang
2016/08/05 02:01:05
Do you care if this or line 473 returns 0? If a ma
jaepark
2016/08/05 02:49:37
It can be 0, in which case the border will not be
Lei Zhang
2016/08/05 15:50:09
Why don't we generate a test PDF and find out?
jaepark
2016/08/05 19:02:19
Figured out that if the border width is 0 or negat
| |
470 } | |
471 | |
472 if (CPDF_Array* pBorderArray = pAnnotDict.GetArrayBy("Border")) | |
473 return pBorderArray->GetNumberAt(2); | |
474 | |
475 return 1; | |
476 } | |
477 | |
478 CFX_ByteString GetDashArrayInString(const CPDF_Dictionary& pAnnotDict) { | |
Lei Zhang
2016/08/05 02:01:05
just GetDashArrayString?
jaepark
2016/08/05 02:49:38
Done.
| |
479 CPDF_Array* pDashArray = nullptr; | |
480 | |
481 if (CPDF_Dictionary* pBorderStyleDict = pAnnotDict.GetDictBy("BS")) { | |
482 if (pBorderStyleDict->GetStringBy("S") == "D") | |
483 pDashArray = pBorderStyleDict->GetArrayBy("D"); | |
484 } else if (CPDF_Array* pBorderArray = pAnnotDict.GetArrayBy("Border")) { | |
485 if (pBorderArray->GetCount() == 4) | |
486 pDashArray = pBorderArray->GetArrayAt(3); | |
487 } | |
488 | |
489 CFX_ByteTextBuf sDashStream; | |
490 if (pDashArray) { | |
491 sDashStream << "[" << pDashArray->GetNumberAt(0); | |
Lei Zhang
2016/08/05 02:01:05
If |pDashArray| is empty, you would get "[ 0 ]", i
jaepark
2016/08/05 02:49:37
I changed it to return empty string when |pDashArr
| |
492 if (pDashArray->GetCount() == 2) | |
493 sDashStream << " " << pDashArray->GetNumberAt(1); | |
494 sDashStream << "]"; | |
495 } | |
496 | |
497 return sDashStream.MakeString(); | |
498 } | |
499 | |
466 CPDF_Dictionary* GenerateExtGStateDict(const CPDF_Dictionary& pAnnotDict, | 500 CPDF_Dictionary* GenerateExtGStateDict(const CPDF_Dictionary& pAnnotDict, |
467 const CFX_ByteString& sExtGSDictName, | 501 const CFX_ByteString& sExtGSDictName, |
468 const CFX_ByteString& sBlendMode) { | 502 const CFX_ByteString& sBlendMode) { |
469 CPDF_Dictionary* pGSDict = new CPDF_Dictionary; | 503 CPDF_Dictionary* pGSDict = new CPDF_Dictionary; |
470 pGSDict->SetAtString("Type", "ExtGState"); | 504 pGSDict->SetAtString("Type", "ExtGState"); |
471 | 505 |
472 FX_FLOAT fOpacity = | 506 FX_FLOAT fOpacity = |
473 pAnnotDict.KeyExist("CA") ? pAnnotDict.GetNumberBy("CA") : 1; | 507 pAnnotDict.KeyExist("CA") ? pAnnotDict.GetNumberBy("CA") : 1; |
474 pGSDict->SetAtNumber("CA", fOpacity); | 508 pGSDict->SetAtNumber("CA", fOpacity); |
475 pGSDict->SetAtNumber("ca", fOpacity); | 509 pGSDict->SetAtNumber("ca", fOpacity); |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
565 CPDF_Dictionary* pAnnotDict) { | 599 CPDF_Dictionary* pAnnotDict) { |
566 // If AP dictionary exists, we use the appearance defined in the | 600 // If AP dictionary exists, we use the appearance defined in the |
567 // existing AP dictionary. | 601 // existing AP dictionary. |
568 if (pAnnotDict->KeyExist("AP")) | 602 if (pAnnotDict->KeyExist("AP")) |
569 return false; | 603 return false; |
570 | 604 |
571 CFX_ByteTextBuf sAppStream; | 605 CFX_ByteTextBuf sAppStream; |
572 CFX_ByteString sExtGSDictName = "GS"; | 606 CFX_ByteString sExtGSDictName = "GS"; |
573 sAppStream << "/" << sExtGSDictName << " gs "; | 607 sAppStream << "/" << sExtGSDictName << " gs "; |
574 | 608 |
575 sAppStream << GetColorStringWithDefault( | 609 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), |
576 pAnnotDict, CPVT_Color(CPVT_Color::kRGB, 1, 1, 0), PaintOperation::FILL); | 610 CPVT_Color(CPVT_Color::kRGB, 1, 1, 0), |
611 PaintOperation::FILL); | |
577 | 612 |
578 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | 613 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
579 rect.Normalize(); | 614 rect.Normalize(); |
580 | 615 |
581 sAppStream << rect.left << " " << rect.top << " m " << rect.right << " " | 616 sAppStream << rect.left << " " << rect.top << " m " << rect.right << " " |
582 << rect.top << " l " << rect.right << " " << rect.bottom << " l " | 617 << rect.top << " l " << rect.right << " " << rect.bottom << " l " |
583 << rect.left << " " << rect.bottom << " l " | 618 << rect.left << " " << rect.bottom << " l " |
584 << "h f\n"; | 619 << "h f\n"; |
585 | 620 |
586 CPDF_Dictionary* pExtGStateDict = | 621 CPDF_Dictionary* pExtGStateDict = |
587 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Multiply"); | 622 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Multiply"); |
588 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); | 623 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); |
589 | 624 |
590 return true; | 625 return true; |
591 } | 626 } |
592 | 627 |
593 bool CPVT_GenerateAP::GenerateUnderlineAP(CPDF_Document* pDoc, | 628 bool CPVT_GenerateAP::GenerateUnderlineAP(CPDF_Document* pDoc, |
594 CPDF_Dictionary* pAnnotDict) { | 629 CPDF_Dictionary* pAnnotDict) { |
595 // If AP dictionary exists, we use the appearance defined in the | 630 // If AP dictionary exists, we use the appearance defined in the |
596 // existing AP dictionary. | 631 // existing AP dictionary. |
597 if (pAnnotDict->KeyExist("AP")) | 632 if (pAnnotDict->KeyExist("AP")) |
598 return false; | 633 return false; |
599 | 634 |
600 CFX_ByteTextBuf sAppStream; | 635 CFX_ByteTextBuf sAppStream; |
601 CFX_ByteString sExtGSDictName = "GS"; | 636 CFX_ByteString sExtGSDictName = "GS"; |
602 sAppStream << "/" << sExtGSDictName << " gs "; | 637 sAppStream << "/" << sExtGSDictName << " gs "; |
603 | 638 |
604 sAppStream << GetColorStringWithDefault(pAnnotDict, | 639 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), |
605 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), | 640 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), |
606 PaintOperation::STROKE); | 641 PaintOperation::STROKE); |
607 | 642 |
608 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | 643 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
609 rect.Normalize(); | 644 rect.Normalize(); |
610 | 645 |
611 FX_FLOAT fLineWidth = 1.0; | 646 FX_FLOAT fLineWidth = 1.0; |
612 sAppStream << fLineWidth << " w " << rect.left << " " | 647 sAppStream << fLineWidth << " w " << rect.left << " " |
613 << rect.bottom + fLineWidth << " m " << rect.right << " " | 648 << rect.bottom + fLineWidth << " m " << rect.right << " " |
614 << rect.bottom + fLineWidth << " l S\n"; | 649 << rect.bottom + fLineWidth << " l S\n"; |
615 | 650 |
616 CPDF_Dictionary* pExtGStateDict = | 651 CPDF_Dictionary* pExtGStateDict = |
617 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); | 652 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); |
618 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); | 653 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); |
619 return true; | 654 return true; |
620 } | 655 } |
621 | 656 |
657 bool CPVT_GenerateAP::GenerateSquareAP(CPDF_Document* pDoc, | |
658 CPDF_Dictionary* pAnnotDict) { | |
659 // If AP dictionary exists, we use the appearance defined in the | |
660 // existing AP dictionary. | |
661 if (pAnnotDict->KeyExist("AP")) | |
662 return false; | |
663 | |
664 CFX_ByteTextBuf sAppStream; | |
665 CFX_ByteString sExtGSDictName = "GS"; | |
666 sAppStream << "/" << sExtGSDictName << " gs "; | |
667 | |
668 bool isFillRect = pAnnotDict->GetArrayBy("IC") && | |
Lei Zhang
2016/08/05 02:01:05
bIsFillRect for consistency.
Lei Zhang
2016/08/05 02:01:05
Can we save the pointer instead of calling pAnnotD
jaepark
2016/08/05 02:49:38
Done.
jaepark
2016/08/05 02:49:38
Done.
| |
669 (pAnnotDict->GetArrayBy("IC")->GetCount() > 0); | |
670 | |
671 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), | |
672 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), | |
673 PaintOperation::STROKE); | |
674 | |
675 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("IC"), | |
676 CPVT_Color(CPVT_Color::kTransparent), | |
677 PaintOperation::FILL); | |
678 | |
679 FX_FLOAT fBorderWidth = GetBorderWidth(*pAnnotDict); | |
680 sAppStream << fBorderWidth << " w "; | |
681 | |
682 CFX_ByteString sDashArray = GetDashArrayInString(*pAnnotDict); | |
683 if (!sDashArray.IsEmpty()) | |
684 sAppStream << sDashArray << " 0 d "; | |
685 | |
686 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | |
687 rect.Normalize(); | |
688 | |
689 // Deflating rect because stroking a path entails painting all points whose | |
690 // perpendicular distance from the path in user space is less than or equal go | |
691 // half the line width. | |
692 rect.Deflate(fBorderWidth / 2, fBorderWidth / 2); | |
693 | |
694 sAppStream << rect.left << " " << rect.top << " m " << rect.right << " " | |
695 << rect.top << " l " << rect.right << " " << rect.bottom << " l " | |
696 << rect.left << " " << rect.bottom << " l " | |
697 << (isFillRect ? "b" : "s") << "\n"; | |
698 | |
699 CPDF_Dictionary* pExtGStateDict = | |
700 GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); | |
701 GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); | |
702 return true; | |
703 } | |
704 | |
622 bool CPVT_GenerateAP::GenerateSquigglyAP(CPDF_Document* pDoc, | 705 bool CPVT_GenerateAP::GenerateSquigglyAP(CPDF_Document* pDoc, |
623 CPDF_Dictionary* pAnnotDict) { | 706 CPDF_Dictionary* pAnnotDict) { |
624 // If AP dictionary exists, we use the appearance defined in the | 707 // If AP dictionary exists, we use the appearance defined in the |
625 // existing AP dictionary. | 708 // existing AP dictionary. |
626 if (pAnnotDict->KeyExist("AP")) | 709 if (pAnnotDict->KeyExist("AP")) |
627 return false; | 710 return false; |
628 | 711 |
629 CFX_ByteTextBuf sAppStream; | 712 CFX_ByteTextBuf sAppStream; |
630 CFX_ByteString sExtGSDictName = "GS"; | 713 CFX_ByteString sExtGSDictName = "GS"; |
631 sAppStream << "/" << sExtGSDictName << " gs "; | 714 sAppStream << "/" << sExtGSDictName << " gs "; |
632 | 715 |
633 sAppStream << GetColorStringWithDefault(pAnnotDict, | 716 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), |
634 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), | 717 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), |
635 PaintOperation::STROKE); | 718 PaintOperation::STROKE); |
636 | 719 |
637 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | 720 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
638 rect.Normalize(); | 721 rect.Normalize(); |
639 | 722 |
640 FX_FLOAT fLineWidth = 1.0; | 723 FX_FLOAT fLineWidth = 1.0; |
641 sAppStream << fLineWidth << " w "; | 724 sAppStream << fLineWidth << " w "; |
642 | 725 |
643 const FX_FLOAT fDelta = 2.0; | 726 const FX_FLOAT fDelta = 2.0; |
(...skipping 30 matching lines...) Expand all Loading... | |
674 CPDF_Dictionary* pAnnotDict) { | 757 CPDF_Dictionary* pAnnotDict) { |
675 // If AP dictionary exists, we use the appearance defined in the | 758 // If AP dictionary exists, we use the appearance defined in the |
676 // existing AP dictionary. | 759 // existing AP dictionary. |
677 if (pAnnotDict->KeyExist("AP")) | 760 if (pAnnotDict->KeyExist("AP")) |
678 return false; | 761 return false; |
679 | 762 |
680 CFX_ByteTextBuf sAppStream; | 763 CFX_ByteTextBuf sAppStream; |
681 CFX_ByteString sExtGSDictName = "GS"; | 764 CFX_ByteString sExtGSDictName = "GS"; |
682 sAppStream << "/" << sExtGSDictName << " gs "; | 765 sAppStream << "/" << sExtGSDictName << " gs "; |
683 | 766 |
684 sAppStream << GetColorStringWithDefault(pAnnotDict, | 767 sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), |
685 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), | 768 CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), |
686 PaintOperation::STROKE); | 769 PaintOperation::STROKE); |
687 | 770 |
688 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); | 771 CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); |
689 rect.Normalize(); | 772 rect.Normalize(); |
690 | 773 |
691 FX_FLOAT fLineWidth = 1.0; | 774 FX_FLOAT fLineWidth = 1.0; |
692 FX_FLOAT fY = (rect.top + rect.bottom) / 2; | 775 FX_FLOAT fY = (rect.top + rect.bottom) / 2; |
693 sAppStream << fLineWidth << " w " << rect.left << " " << fY << " m " | 776 sAppStream << fLineWidth << " w " << rect.left << " " << fY << " m " |
694 << rect.right << " " << fY << " l S\n"; | 777 << rect.right << " " << fY << " l S\n"; |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
960 int32_t nFontIndex, | 1043 int32_t nFontIndex, |
961 FX_FLOAT fFontSize) { | 1044 FX_FLOAT fFontSize) { |
962 CFX_ByteTextBuf sRet; | 1045 CFX_ByteTextBuf sRet; |
963 if (pFontMap) { | 1046 if (pFontMap) { |
964 CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); | 1047 CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); |
965 if (sFontAlias.GetLength() > 0 && fFontSize > 0) | 1048 if (sFontAlias.GetLength() > 0 && fFontSize > 0) |
966 sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; | 1049 sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; |
967 } | 1050 } |
968 return sRet.MakeString(); | 1051 return sRet.MakeString(); |
969 } | 1052 } |
OLD | NEW |