Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(215)

Side by Side Diff: core/fpdfdoc/cpvt_generateap.cpp

Issue 2219683002: Generate default AP stream for square annotation. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/fpdfdoc/cpvt_generateap.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « core/fpdfdoc/cpvt_generateap.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698