diff options
Diffstat (limited to 'fpdfsdk/fpdfannot.cpp')
-rw-r--r-- | fpdfsdk/fpdfannot.cpp | 145 |
1 files changed, 109 insertions, 36 deletions
diff --git a/fpdfsdk/fpdfannot.cpp b/fpdfsdk/fpdfannot.cpp index 169c31c236..4a288b7df7 100644 --- a/fpdfsdk/fpdfannot.cpp +++ b/fpdfsdk/fpdfannot.cpp @@ -136,6 +136,10 @@ CPDF_AnnotContext* CPDFAnnotContextFromFPDFAnnotation(FPDF_ANNOTATION annot) { return static_cast<CPDF_AnnotContext*>(annot); } +bool HasAPStream(const CPDF_Dictionary* pAnnotDict) { + return !!FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); +} + } // namespace DLLEXPORT FPDF_BOOL STDCALL @@ -225,6 +229,12 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_SetColor(FPDF_ANNOTATION annot, if (!pAnnotDict) return false; + // For annotations with their appearance streams already defined, the path + // stream's own color definitions take priority over the annotation color + // definitions set by this method, hence this method will simply fail. + if (HasAPStream(pAnnotDict)) + return false; + // Set the opacity of the annotation. pAnnotDict->SetNewFor<CPDF_Number>("CA", A / 255.f); @@ -257,6 +267,12 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_GetColor(FPDF_ANNOTATION annot, if (!pAnnotDict) return false; + // For annotations with their appearance streams already defined, the path + // stream's own color definitions take priority over the annotation color + // definitions retrieved by this method, hence this method will simply fail. + if (HasAPStream(pAnnotDict)) + return false; + CPDF_Array* pColor = pAnnotDict->GetArrayFor( type == FPDFANNOT_COLORTYPE_InteriorColor ? "IC" : "C"); *A = @@ -315,8 +331,8 @@ FPDFAnnot_HasAttachmentPoints(FPDF_ANNOTATION annot) { DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_SetAttachmentPoints(FPDF_ANNOTATION annot, - FS_QUADPOINTSF quadPoints) { - if (!annot || !FPDFAnnot_HasAttachmentPoints(annot)) + const FS_QUADPOINTSF* quadPoints) { + if (!annot || !quadPoints || !FPDFAnnot_HasAttachmentPoints(annot)) return false; CPDF_Dictionary* pAnnotDict = @@ -324,20 +340,33 @@ FPDFAnnot_SetAttachmentPoints(FPDF_ANNOTATION annot, if (!pAnnotDict) return false; + // Update the "QuadPoints" entry in the annotation dictionary. CPDF_Array* pQuadPoints = pAnnotDict->GetArrayFor("QuadPoints"); if (pQuadPoints) pQuadPoints->Clear(); else pQuadPoints = pAnnotDict->SetNewFor<CPDF_Array>("QuadPoints"); - pQuadPoints->AddNew<CPDF_Number>(quadPoints.x1); - pQuadPoints->AddNew<CPDF_Number>(quadPoints.y1); - pQuadPoints->AddNew<CPDF_Number>(quadPoints.x2); - pQuadPoints->AddNew<CPDF_Number>(quadPoints.y2); - pQuadPoints->AddNew<CPDF_Number>(quadPoints.x3); - pQuadPoints->AddNew<CPDF_Number>(quadPoints.y3); - pQuadPoints->AddNew<CPDF_Number>(quadPoints.x4); - pQuadPoints->AddNew<CPDF_Number>(quadPoints.y4); + pQuadPoints->AddNew<CPDF_Number>(quadPoints->x1); + pQuadPoints->AddNew<CPDF_Number>(quadPoints->y1); + pQuadPoints->AddNew<CPDF_Number>(quadPoints->x2); + pQuadPoints->AddNew<CPDF_Number>(quadPoints->y2); + pQuadPoints->AddNew<CPDF_Number>(quadPoints->x3); + pQuadPoints->AddNew<CPDF_Number>(quadPoints->y3); + pQuadPoints->AddNew<CPDF_Number>(quadPoints->x4); + pQuadPoints->AddNew<CPDF_Number>(quadPoints->y4); + + // If the annotation's appearance stream is defined, and the new quadpoints + // defines a bigger bounding box than the appearance stream currently + // specifies, then update the "BBox" entry in the AP dictionary too, since it + // comes from annotation dictionary's "QuadPoints" entry. + CPDF_Stream* pStream = + FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); + if (pStream) { + CFX_FloatRect newRect = CPDF_Annot::RectFromQuadPoints(pAnnotDict); + if (newRect.Contains(pStream->GetDict()->GetRectFor("BBox"))) + pStream->GetDict()->SetRectFor("BBox", newRect); + } return true; } @@ -351,25 +380,52 @@ FPDFAnnot_GetAttachmentPoints(FPDF_ANNOTATION annot) { if (!pAnnotDict) return FS_QUADPOINTSF(); - CPDF_Array* pArray = pAnnotDict->GetArrayFor("QuadPoints"); - if (!pArray) - return FS_QUADPOINTSF(); - + // If the annotation's appearance stream is defined, then retrieve the + // quadpoints defined by the "BBox" entry in the AP dictionary, since its + // "BBox" entry comes from annotation dictionary's "QuadPoints" entry, but + // takes priority over "QuadPoints" when rendering. Otherwise, retrieve + // the "Quadpoints" entry from the annotation dictionary. + CPDF_Array* pArray; FS_QUADPOINTSF quadPoints; - quadPoints.x1 = pArray->GetNumberAt(0); - quadPoints.y1 = pArray->GetNumberAt(1); - quadPoints.x2 = pArray->GetNumberAt(2); - quadPoints.y2 = pArray->GetNumberAt(3); - quadPoints.x3 = pArray->GetNumberAt(4); - quadPoints.y3 = pArray->GetNumberAt(5); - quadPoints.x4 = pArray->GetNumberAt(6); - quadPoints.y4 = pArray->GetNumberAt(7); + CPDF_Stream* pStream = + FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); + if (pStream) { + pArray = pStream->GetDict()->GetArrayFor("BBox"); + if (!pArray) + return FS_QUADPOINTSF(); + + // Convert the BBox array into quadpoint coordinates. BBox array follows the + // order of a rectangle array: (left, bottom, right, up); and quadpoints + // follows the following order: (top-left vertex, top-right vertex, bottom- + // left vertex, bottom-right vertex). + quadPoints.x1 = pArray->GetNumberAt(0); + quadPoints.y1 = pArray->GetNumberAt(3); + quadPoints.x2 = pArray->GetNumberAt(2); + quadPoints.y2 = pArray->GetNumberAt(3); + quadPoints.x3 = pArray->GetNumberAt(0); + quadPoints.y3 = pArray->GetNumberAt(1); + quadPoints.x4 = pArray->GetNumberAt(2); + quadPoints.y4 = pArray->GetNumberAt(1); + } else { + pArray = pAnnotDict->GetArrayFor("QuadPoints"); + if (!pArray) + return FS_QUADPOINTSF(); + + quadPoints.x1 = pArray->GetNumberAt(0); + quadPoints.y1 = pArray->GetNumberAt(1); + quadPoints.x2 = pArray->GetNumberAt(2); + quadPoints.y2 = pArray->GetNumberAt(3); + quadPoints.x3 = pArray->GetNumberAt(4); + quadPoints.y3 = pArray->GetNumberAt(5); + quadPoints.x4 = pArray->GetNumberAt(6); + quadPoints.y4 = pArray->GetNumberAt(7); + } return quadPoints; } DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_SetRect(FPDF_ANNOTATION annot, - FS_RECTF rect) { - if (!annot) + const FS_RECTF* rect) { + if (!annot || !rect) return false; CPDF_Dictionary* pAnnotDict = @@ -377,16 +433,23 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFAnnot_SetRect(FPDF_ANNOTATION annot, if (!pAnnotDict) return false; - CPDF_Array* pRect = pAnnotDict->GetArrayFor("Rect"); - if (pRect) - pRect->Clear(); - else - pRect = pAnnotDict->SetNewFor<CPDF_Array>("Rect"); + CFX_FloatRect newRect(rect->left, rect->bottom, rect->right, rect->top); + + // Update the "Rect" entry in the annotation dictionary. + pAnnotDict->SetRectFor("Rect", newRect); - pRect->AddNew<CPDF_Number>(rect.left); - pRect->AddNew<CPDF_Number>(rect.bottom); - pRect->AddNew<CPDF_Number>(rect.right); - pRect->AddNew<CPDF_Number>(rect.top); + // If the annotation's appearance stream is defined, the annotation is of a + // type that does not have quadpoints, and the new rectangle is bigger than + // the current bounding box, then update the "BBox" entry in the AP + // dictionary too, since its "BBox" entry comes from annotation dictionary's + // "Rect" entry. + if (FPDFAnnot_HasAttachmentPoints(annot)) + return true; + + CPDF_Stream* pStream = + FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); + if (pStream && newRect.Contains(pStream->GetDict()->GetRectFor("BBox"))) + pStream->GetDict()->SetRectFor("BBox", newRect); return true; } @@ -399,9 +462,19 @@ DLLEXPORT FS_RECTF STDCALL FPDFAnnot_GetRect(FPDF_ANNOTATION annot) { if (!pAnnotDict) return FS_RECTF(); - CFX_FloatRect rt = pAnnotDict->GetRectFor("Rect"); - if (rt.IsEmpty()) - return FS_RECTF(); + // If the annotation's appearance stream is defined and the annotation is of + // a type that does not have quadpoints, then retrieve the rectangle defined + // by the "BBox" entry in the AP dictionary, since its "BBox" entry comes + // from annotation dictionary's "Rect" entry, but takes priority over "Rect" + // when rendering. Otherwise, retrieve the "Rect" entry from the annotation + // dictionary. + CFX_FloatRect rt; + CPDF_Stream* pStream = + FPDFDOC_GetAnnotAP(pAnnotDict, CPDF_Annot::AppearanceMode::Normal); + if (!pStream || FPDFAnnot_HasAttachmentPoints(annot)) + rt = pAnnotDict->GetRectFor("Rect"); + else + rt = pStream->GetDict()->GetRectFor("BBox"); FS_RECTF rect; rect.left = rt.left; |