From e7107f48ddb9309e1664d84ec360ce06ec3201e2 Mon Sep 17 00:00:00 2001 From: jaepark Date: Tue, 9 Aug 2016 11:40:58 -0700 Subject: Generate default AP stream for circle annotation. This patch generates a default AP stream for circle annotation so that circle annotations without AP stream can be displayed. Also, roll DEPS for testing/corpus to 71d1f22 to test circle annotations. BUG=62625 Review-Url: https://codereview.chromium.org/2228093002 --- core/fpdfdoc/cpdf_annot.cpp | 4 ++- core/fpdfdoc/cpvt_generateap.cpp | 76 ++++++++++++++++++++++++++++++++++++++++ core/fpdfdoc/cpvt_generateap.h | 2 ++ 3 files changed, 81 insertions(+), 1 deletion(-) (limited to 'core/fpdfdoc') diff --git a/core/fpdfdoc/cpdf_annot.cpp b/core/fpdfdoc/cpdf_annot.cpp index 252e8361dd..ce84df1ee0 100644 --- a/core/fpdfdoc/cpdf_annot.cpp +++ b/core/fpdfdoc/cpdf_annot.cpp @@ -21,7 +21,9 @@ CPDF_Annot::CPDF_Annot(CPDF_Dictionary* pDict, CPDF_Document* pDocument) : m_pAnnotDict(pDict), m_pDocument(pDocument), m_sSubtype(m_pAnnotDict->GetStringBy("Subtype")) { - if (m_sSubtype == "Highlight") + if (m_sSubtype == "Circle") + CPVT_GenerateAP::GenerateCircleAP(m_pDocument, m_pAnnotDict); + else if (m_sSubtype == "Highlight") CPVT_GenerateAP::GenerateHighlightAP(m_pDocument, m_pAnnotDict); else if (m_sSubtype == "Square") CPVT_GenerateAP::GenerateSquareAP(m_pDocument, m_pAnnotDict); diff --git a/core/fpdfdoc/cpvt_generateap.cpp b/core/fpdfdoc/cpvt_generateap.cpp index 13d0fa0d38..5cf96f211f 100644 --- a/core/fpdfdoc/cpvt_generateap.cpp +++ b/core/fpdfdoc/cpvt_generateap.cpp @@ -612,6 +612,82 @@ bool CPVT_GenerateAP::GenerateTextFieldAP(CPDF_Document* pDoc, return GenerateWidgetAP(pDoc, pAnnotDict, 0); } +bool CPVT_GenerateAP::GenerateCircleAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict) { + // If AP dictionary exists, we use the appearance defined in the + // existing AP dictionary. + if (pAnnotDict->KeyExist("AP")) + return false; + + CFX_ByteTextBuf sAppStream; + CFX_ByteString sExtGSDictName = "GS"; + sAppStream << "/" << sExtGSDictName << " gs "; + + CPDF_Array* pInteriorColor = pAnnotDict->GetArrayBy("IC"); + sAppStream << GetColorStringWithDefault(pInteriorColor, + CPVT_Color(CPVT_Color::kTransparent), + PaintOperation::FILL); + + sAppStream << GetColorStringWithDefault(pAnnotDict->GetArrayBy("C"), + CPVT_Color(CPVT_Color::kRGB, 0, 0, 0), + PaintOperation::STROKE); + + FX_FLOAT fBorderWidth = GetBorderWidth(*pAnnotDict); + bool bIsStrokeRect = fBorderWidth > 0; + + if (bIsStrokeRect) { + sAppStream << fBorderWidth << " w "; + sAppStream << GetDashPatternString(*pAnnotDict); + } + + CFX_FloatRect rect = pAnnotDict->GetRectBy("Rect"); + rect.Normalize(); + + if (bIsStrokeRect) { + // Deflating rect because stroking a path entails painting all points whose + // perpendicular distance from the path in user space is less than or equal + // to half the line width. + rect.Deflate(fBorderWidth / 2, fBorderWidth / 2); + } + + const FX_FLOAT fMiddleX = (rect.left + rect.right) / 2; + const FX_FLOAT fMiddleY = (rect.top + rect.bottom) / 2; + + // |fL| is precalculated approximate value of 4 * tan((3.14 / 2) / 4) / 3, + // where |fL| * radius is a good approximation of control points for + // arc with 90 degrees. + const FX_FLOAT fL = 0.5523f; + const FX_FLOAT fDeltaX = fL * rect.Width() / 2.0; + const FX_FLOAT fDeltaY = fL * rect.Height() / 2.0; + + // Starting point + sAppStream << fMiddleX << " " << rect.top << " m\n"; + // First Bezier Curve + sAppStream << fMiddleX + fDeltaX << " " << rect.top << " " << rect.right + << " " << fMiddleY + fDeltaY << " " << rect.right << " " + << fMiddleY << " c\n"; + // Second Bezier Curve + sAppStream << rect.right << " " << fMiddleY - fDeltaY << " " + << fMiddleX + fDeltaX << " " << rect.bottom << " " << fMiddleX + << " " << rect.bottom << " c\n"; + // Third Bezier Curve + sAppStream << fMiddleX - fDeltaX << " " << rect.bottom << " " << rect.left + << " " << fMiddleY - fDeltaY << " " << rect.left << " " << fMiddleY + << " c\n"; + // Fourth Bezier Curve + sAppStream << rect.left << " " << fMiddleY + fDeltaY << " " + << fMiddleX - fDeltaX << " " << rect.top << " " << fMiddleX << " " + << rect.top << " c\n"; + + bool bIsFillRect = pInteriorColor && !pInteriorColor->IsEmpty(); + sAppStream << GetPaintOperatorString(bIsStrokeRect, bIsFillRect) << "\n"; + + CPDF_Dictionary* pExtGStateDict = + GenerateExtGStateDict(*pAnnotDict, sExtGSDictName, "Normal"); + GenerateAndSetAPDict(pDoc, pAnnotDict, sAppStream, pExtGStateDict); + return true; +} + bool CPVT_GenerateAP::GenerateHighlightAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { // If AP dictionary exists, we use the appearance defined in the diff --git a/core/fpdfdoc/cpvt_generateap.h b/core/fpdfdoc/cpvt_generateap.h index e0dd706439..a81bea276a 100644 --- a/core/fpdfdoc/cpvt_generateap.h +++ b/core/fpdfdoc/cpvt_generateap.h @@ -25,6 +25,8 @@ bool FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict); class CPVT_GenerateAP { public: + static bool GenerateCircleAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict); static bool GenerateComboBoxAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict); static bool GenerateHighlightAP(CPDF_Document* pDoc, -- cgit v1.2.3