Further split CPDF_GenerateAP::GenerateFormAP() - Move /MK dictionary parsing into its own function. - Move bounding box / matrix calculation into its own function. - Move /DA string retrieval into its own function. Change-Id: I23ade161f2bd72af3237dbedaf9a2088b7c4be08 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/126592 Reviewed-by: Tom Sepez <tsepez@chromium.org> Reviewed-by: Thomas Sepez <tsepez@google.com> Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfdoc/cpdf_generateap.cpp b/core/fpdfdoc/cpdf_generateap.cpp index b66a947..609185f 100644 --- a/core/fpdfdoc/cpdf_generateap.cpp +++ b/core/fpdfdoc/cpdf_generateap.cpp
@@ -105,6 +105,8 @@ return ByteString(font_stream); } +// ISO 32000-1:2008 spec, table 166. +// ISO 32000-2:2020 spec, table 168. struct BorderStyleInfo { float width = 1; BorderStyle style = BorderStyle::kSolid; @@ -155,6 +157,100 @@ return border_style_info; } +// ISO 32000-1:2008 spec, table 189. +// ISO 32000-2:2020 spec, table 192. +struct AppearanceCharacteristics { + int rotation = 0; // In degrees. + CFX_Color border_color; + CFX_Color background_color; +}; + +AppearanceCharacteristics GetAppearanceCharacteristics( + const CPDF_Dictionary* mk_dict) { + AppearanceCharacteristics appearance_characteristics; + if (!mk_dict) { + return appearance_characteristics; + } + + appearance_characteristics.rotation = + mk_dict->GetIntegerFor(pdfium::appearance::kR); + + RetainPtr<const CPDF_Array> border_color_array = + mk_dict->GetArrayFor(pdfium::appearance::kBC); + if (border_color_array) { + appearance_characteristics.border_color = + fpdfdoc::CFXColorFromArray(*border_color_array); + } + RetainPtr<const CPDF_Array> background_color_array = + mk_dict->GetArrayFor(pdfium::appearance::kBG); + if (background_color_array) { + appearance_characteristics.background_color = + fpdfdoc::CFXColorFromArray(*background_color_array); + } + return appearance_characteristics; +} + +struct AnnotationDimensionsAndColor { + CFX_FloatRect bbox; + CFX_Matrix matrix; + CFX_Color border_color; + CFX_Color background_color; +}; + +AnnotationDimensionsAndColor GetAnnotationDimensionsAndColor( + const CPDF_Dictionary* annot_dict) { + const AppearanceCharacteristics appearance_characteristics = + GetAppearanceCharacteristics(annot_dict->GetDictFor("MK")); + const CFX_FloatRect annot_rect = + annot_dict->GetRectFor(pdfium::annotation::kRect); + + CFX_FloatRect bbox_rect; + CFX_Matrix matrix; + switch (appearance_characteristics.rotation % 360) { + case 0: + bbox_rect = CFX_FloatRect(0, 0, annot_rect.right - annot_rect.left, + annot_rect.top - annot_rect.bottom); + break; + case 90: + matrix = CFX_Matrix(0, 1, -1, 0, annot_rect.right - annot_rect.left, 0); + bbox_rect = CFX_FloatRect(0, 0, annot_rect.top - annot_rect.bottom, + annot_rect.right - annot_rect.left); + break; + case 180: + matrix = CFX_Matrix(-1, 0, 0, -1, annot_rect.right - annot_rect.left, + annot_rect.top - annot_rect.bottom); + bbox_rect = CFX_FloatRect(0, 0, annot_rect.right - annot_rect.left, + annot_rect.top - annot_rect.bottom); + break; + case 270: + matrix = CFX_Matrix(0, -1, 1, 0, 0, annot_rect.top - annot_rect.bottom); + bbox_rect = CFX_FloatRect(0, 0, annot_rect.top - annot_rect.bottom, + annot_rect.right - annot_rect.left); + break; + } + + return { + .bbox = bbox_rect, + .matrix = matrix, + .border_color = appearance_characteristics.border_color, + .background_color = appearance_characteristics.background_color, + }; +} + +ByteString GetDefaultAppearanceString(CPDF_Dictionary* annot_dict, + CPDF_Dictionary* form_dict) { + ByteString default_appearance_string; + RetainPtr<const CPDF_Object> default_appearance_object = + CPDF_FormField::GetFieldAttrForDict(annot_dict, "DA"); + if (default_appearance_object) { + default_appearance_string = default_appearance_object->GetString(); + } + if (default_appearance_string.IsEmpty()) { + default_appearance_string = form_dict->GetByteStringFor("DA"); + } + return default_appearance_string; +} + ByteString GenerateEditAP(IPVT_FontMap* font_map, CPVT_VariableText::Iterator* vt_iterator, const CFX_PointF& offset, @@ -974,15 +1070,8 @@ return; } - ByteString default_appearance_string; - RetainPtr<const CPDF_Object> default_appearance_object = - CPDF_FormField::GetFieldAttrForDict(annot_dict, "DA"); - if (default_appearance_object) { - default_appearance_string = default_appearance_object->GetString(); - } - if (default_appearance_string.IsEmpty()) { - default_appearance_string = form_dict->GetByteStringFor("DA"); - } + const ByteString default_appearance_string = + GetDefaultAppearanceString(annot_dict, form_dict); if (default_appearance_string.IsEmpty()) { return; } @@ -1020,66 +1109,26 @@ return; } - CFX_FloatRect annot_rect = annot_dict->GetRectFor(pdfium::annotation::kRect); - RetainPtr<const CPDF_Dictionary> mk_dict = annot_dict->GetDictFor("MK"); - const int32_t rotate = - mk_dict ? mk_dict->GetIntegerFor(pdfium::appearance::kR) : 0; - - CFX_FloatRect bbox_rect; - CFX_Matrix matrix; - switch (rotate % 360) { - case 0: - bbox_rect = CFX_FloatRect(0, 0, annot_rect.right - annot_rect.left, - annot_rect.top - annot_rect.bottom); - break; - case 90: - matrix = CFX_Matrix(0, 1, -1, 0, annot_rect.right - annot_rect.left, 0); - bbox_rect = CFX_FloatRect(0, 0, annot_rect.top - annot_rect.bottom, - annot_rect.right - annot_rect.left); - break; - case 180: - matrix = CFX_Matrix(-1, 0, 0, -1, annot_rect.right - annot_rect.left, - annot_rect.top - annot_rect.bottom); - bbox_rect = CFX_FloatRect(0, 0, annot_rect.right - annot_rect.left, - annot_rect.top - annot_rect.bottom); - break; - case 270: - matrix = CFX_Matrix(0, -1, 1, 0, 0, annot_rect.top - annot_rect.bottom); - bbox_rect = CFX_FloatRect(0, 0, annot_rect.top - annot_rect.bottom, - annot_rect.right - annot_rect.left); - break; + const AnnotationDimensionsAndColor annot_dimensions_and_color = + GetAnnotationDimensionsAndColor(annot_dict); + fxcrt::ostringstream app_stream; + const ByteString background = GenerateColorAP( + annot_dimensions_and_color.background_color, PaintOperation::kFill); + if (background.GetLength() > 0) { + app_stream << "q\n" << background; + WriteRect(app_stream, annot_dimensions_and_color.bbox) << " re f\nQ\n"; } const BorderStyleInfo border_style_info = GetBorderStyleInfo(annot_dict->GetDictFor("BS")); - CFX_Color border_color; - CFX_Color background_color; - if (mk_dict) { - RetainPtr<const CPDF_Array> border_color_array = - mk_dict->GetArrayFor(pdfium::appearance::kBC); - if (border_color_array) { - border_color = fpdfdoc::CFXColorFromArray(*border_color_array); - } - RetainPtr<const CPDF_Array> background_color_array = - mk_dict->GetArrayFor(pdfium::appearance::kBG); - if (background_color_array) { - background_color = fpdfdoc::CFXColorFromArray(*background_color_array); - } - } - fxcrt::ostringstream app_stream; - ByteString background = - GenerateColorAP(background_color, PaintOperation::kFill); - if (background.GetLength() > 0) { - app_stream << "q\n" << background; - WriteRect(app_stream, bbox_rect) << " re f\nQ\n"; - } - ByteString border_stream = - GenerateBorderAP(bbox_rect, border_style_info, border_color); + const ByteString border_stream = + GenerateBorderAP(annot_dimensions_and_color.bbox, border_style_info, + annot_dimensions_and_color.border_color); if (border_stream.GetLength() > 0) { app_stream << "q\n" << border_stream << "Q\n"; } - CFX_FloatRect body_rect = bbox_rect; + CFX_FloatRect body_rect = annot_dimensions_and_color.bbox; body_rect.Deflate(border_style_info.width, border_style_info.width); RetainPtr<CPDF_Dictionary> ap_dict = @@ -1107,8 +1156,8 @@ } else { stream_dict->SetFor("Resources", form_dict->GetDictFor("DR")->Clone()); } - stream_dict->SetMatrixFor("Matrix", matrix); - stream_dict->SetRectFor("BBox", bbox_rect); + stream_dict->SetMatrixFor("Matrix", annot_dimensions_and_color.matrix); + stream_dict->SetRectFor("BBox", annot_dimensions_and_color.bbox); } else { normal_stream = doc->NewIndirect<CPDF_Stream>(pdfium::MakeRetain<CPDF_Dictionary>()); @@ -1338,8 +1387,8 @@ normal_stream->SetDataFromStringstreamAndRemoveFilter(&app_stream); stream_dict = normal_stream->GetMutableDict(); - stream_dict->SetMatrixFor("Matrix", matrix); - stream_dict->SetRectFor("BBox", bbox_rect); + stream_dict->SetMatrixFor("Matrix", annot_dimensions_and_color.matrix); + stream_dict->SetRectFor("BBox", annot_dimensions_and_color.bbox); RetainPtr<CPDF_Dictionary> resources_dict = stream_dict->GetMutableDictFor("Resources"); if (!resources_dict) {