7#include "public/fpdf_flatten.h"
16#include "constants/annotation_common.h"
17#include "constants/annotation_flags.h"
18#include "constants/font_encodings.h"
19#include "constants/page_object.h"
20#include "core/fpdfapi/edit/cpdf_contentstream_write_utils.h"
21#include "core/fpdfapi/page/cpdf_page.h"
22#include "core/fpdfapi/page/cpdf_pageobject.h"
23#include "core/fpdfapi/parser/cpdf_array.h"
24#include "core/fpdfapi/parser/cpdf_dictionary.h"
25#include "core/fpdfapi/parser/cpdf_document.h"
26#include "core/fpdfapi/parser/cpdf_name.h"
27#include "core/fpdfapi/parser/cpdf_number.h"
28#include "core/fpdfapi/parser/cpdf_reference.h"
29#include "core/fpdfapi/parser/cpdf_stream.h"
30#include "core/fpdfapi/parser/cpdf_stream_acc.h"
31#include "core/fpdfapi/parser/fpdf_parser_utility.h"
32#include "core/fpdfdoc/cpdf_annot.h"
33#include "core/fxcrt/fx_string_wrappers.h"
34#include "core/fxcrt/notreached.h"
35#include "fpdfsdk/cpdfsdk_helpers.h"
43 constexpr float kMinSize = 0.000001f;
50 constexpr float kMinBorderSize = 10.000001f;
51 return rect
.left - rcPage
.left >= -kMinBorderSize &&
53 rect
.top - rcPage
.top <= kMinBorderSize &&
59 std::vector<CFX_FloatRect>* pRectArray) {
60 auto pPDFPage =
pdfium::MakeRetain<CPDF_Page>(pDoc, pDict);
61 pPDFPage->ParseContent();
63 for (
const auto& pPageObject : *pPDFPage) {
64 const CFX_FloatRect& rc = pPageObject->GetRect();
65 if (IsValidRect(rc, pDict->GetRectFor(pdfium::page_object::kMediaBox)))
66 pRectArray->push_back(rc);
72 std::vector<CFX_FloatRect>* pRectArray,
73 std::vector<CPDF_Dictionary*>* pObjectArray) {
83 pRectArray->push_back(rect);
85 pObjectArray->push_back(pStream);
90 std::vector<CFX_FloatRect>* pRectArray,
91 std::vector<CPDF_Dictionary*>* pObjectArray,
96 GetContentsRect(pSourceDoc, pPageDic, pRectArray);
102 for (
const auto& pAnnot : locker) {
103 RetainPtr<CPDF_Dictionary> pAnnotDict =
104 ToDictionary(pAnnot->GetMutableDirect());
108 ByteString sSubtype =
109 pAnnotDict->GetByteStringFor(pdfium::annotation::kSubtype);
110 if (sSubtype ==
"Popup")
113 int nAnnotFlag = pAnnotDict->GetIntegerFor(
"F");
114 if (nAnnotFlag & pdfium::annotation_flags::kHidden)
119 bParseStream = !(nAnnotFlag & pdfium::annotation_flags::kInvisible);
121 bParseStream = !!(nAnnotFlag & pdfium::annotation_flags::kPrint);
123 ParserStream(pPageDic.Get(), pAnnotDict.Get(), pRectArray, pObjectArray);
128float GetMinMaxValue(
const std::vector<CFX_FloatRect>& array,
134 size_t nRects = array.size();
135 std::vector<
float> pArray(nRects);
138 for (size_t i = 0; i < nRects; i++)
139 pArray[i] = array[i].left;
142 for (size_t i = 0; i < nRects; i++)
143 pArray[i] = array[i].top;
146 for (size_t i = 0; i < nRects; i++)
147 pArray[i] = array[i].right;
150 for (size_t i = 0; i < nRects; i++)
151 pArray[i] = array[i].bottom;
155 float fRet = pArray[0];
157 for (size_t i = 1; i < nRects; i++)
158 fRet =
std::max(fRet, pArray[i]);
160 for (size_t i = 1; i < nRects; i++)
161 fRet =
std::min(fRet, pArray[i]);
166CFX_FloatRect CalculateRect(std::vector<CFX_FloatRect>* pRectArray) {
169 rcRet.left = GetMinMaxValue(*pRectArray, MIN, LEFT);
170 rcRet.top = GetMinMaxValue(*pRectArray, MAX, TOP);
171 rcRet.right = GetMinMaxValue(*pRectArray, MAX, RIGHT);
172 rcRet.bottom = GetMinMaxValue(*pRectArray, MIN, BOTTOM);
178 return "q 1 0 0 1 0 0 cm /" + key
+ " Do Q";
181RetainPtr<CPDF_Reference> NewIndirectContentsStreamReference(
185 pDocument->NewIndirect<CPDF_Stream>(pDocument->New<
CPDF_Dictionary>());
186 pNewContents->SetData(contents.unsigned_span());
187 return pNewContents->MakeReference(pDocument);
194 pPage->GetMutableArrayFor(pdfium::page_object::kContents);
196 pPage->GetMutableStreamFor(pdfium::page_object::kContents);
197 if (!pContentsStream && !pContentsArray) {
198 if (!key.IsEmpty()) {
199 pPage->SetFor(pdfium::page_object::kContents,
200 NewIndirectContentsStreamReference(
201 pDocument, GenerateFlattenedContent(key)));
207 if (pContentsArray) {
208 pContentsArray->InsertAt(
209 0, NewIndirectContentsStreamReference(pDocument,
"q"));
210 pContentsArray->Append(NewIndirectContentsStreamReference(pDocument,
"Q"));
214 auto pAcc =
pdfium::MakeRetain<CPDF_StreamAcc>(pContentsStream);
215 pAcc->LoadAllDataFiltered();
219 pContentsStream->SetDataAndRemoveFilter(sStream.unsigned_span());
220 pContentsArray = pDocument->NewIndirect<
CPDF_Array>();
221 pContentsArray->AppendNew<CPDF_Reference>(pDocument,
222 pContentsStream->GetObjNum());
224 pContentsArray->GetObjNum());
226 if (!key.IsEmpty()) {
227 pContentsArray->Append(NewIndirectContentsStreamReference(
228 pDocument, GenerateFlattenedContent(key)));
244 float e = rcAnnot
.left - rcTransformed
.left * a;
249bool IsValidBaseEncoding(
ByteString base_encoding) {
254 return base_encoding.IsEmpty() ||
266 font_dict->GetMutableDictFor(
"Encoding");
268 if (!IsValidBaseEncoding(encoding_dict->GetNameFor(
"BaseEncoding"))) {
269 font_dict->RemoveFor(
"Encoding");
275 if (!font_resource_dict) {
280 for (
auto it : locker) {
281 SanitizeFont(ToDictionary(it.second->GetMutableDirect()));
286 if (!resources_dict) {
290 SanitizeFontResources(resources_dict->GetMutableDictFor(
"Font"));
305 std::vector<CPDF_Dictionary*> ObjectArray;
306 std::vector<CFX_FloatRect> RectArray;
308 ParserAnnots(pDocument, pPageDict, &RectArray, &ObjectArray, nFlag);
328 rcOriginalCB
= rcOriginalMB;
339 pPageDict->GetOrCreateDictFor(pdfium::page_object::kResources);
341 pDocument->NewIndirect<CPDF_Stream>(pDocument->New<
CPDF_Dictionary>());
345 if (!ObjectArray.empty()) {
347 while (i < INT_MAX) {
349 if (!pPageXObject->KeyExist(sKey)) {
350 key =
std::move(sKey);
357 SetPageContents(key, pPageDict.Get(), pDocument);
360 if (!key.IsEmpty()) {
361 pPageXObject->SetNewFor<CPDF_Reference>(key, pDocument,
362 pNewXObject->GetObjNum());
366 pNewOXbjectDic->SetNewFor<CPDF_Name>(
"Type",
"XObject");
367 pNewOXbjectDic->SetNewFor<CPDF_Name>(
"Subtype",
"Form");
368 pNewOXbjectDic->SetNewFor<CPDF_Number>(
"FormType", 1);
369 pNewOXbjectDic->SetRectFor(
"BBox", rcOriginalCB);
372 for (size_t i = 0; i < ObjectArray.size(); ++i) {
382 pAnnotDict->GetMutableDictFor(pdfium::annotation::kAP);
386 RetainPtr<CPDF_Stream> original_ap_stream =
387 pAnnotAP->GetMutableStreamFor(
"N");
388 if (!original_ap_stream) {
390 pAnnotAP->GetMutableDictFor(
"N");
391 if (!original_ap_dict) {
395 if (!sAnnotState.IsEmpty()) {
396 original_ap_stream = original_ap_dict->GetMutableStreamFor(sAnnotState);
398 if (original_ap_dict->size() > 0) {
402 if (pFirstObj->IsReference())
403 pFirstObj = pFirstObj->GetMutableDirect();
404 if (!pFirstObj->IsStream())
406 original_ap_stream.Reset(pFirstObj->AsMutableStream());
411 if (!original_ap_stream) {
416 original_ap_stream->GetDict();
418 if (original_ap_stream_dict->KeyExist(
"Rect")) {
419 rcStream = original_ap_stream_dict->GetRectFor(
"Rect");
420 }
else if (original_ap_stream_dict->KeyExist(
"BBox")) {
421 rcStream = original_ap_stream_dict->GetRectFor(
"BBox");
429 if (original_ap_stream->IsInline()) {
430 ap_stream = ToStream(original_ap_stream->Clone());
433 ap_stream = original_ap_stream;
437 ap_stream_dict->SetNewFor<CPDF_Name>(
"Type",
"XObject");
438 ap_stream_dict->SetNewFor<CPDF_Name>(
"Subtype",
"Form");
439 SanitizeResources(ap_stream_dict->GetMutableDictFor(
"Resources"));
442 pNewXORes->GetOrCreateDictFor(
"XObject");
444 pXObject->SetNewFor<CPDF_Reference>(sFormName, pDocument,
445 ap_stream->GetObjNum());
449 auto pAcc =
pdfium::MakeRetain<CPDF_StreamAcc>(pNewXObject);
450 pAcc->LoadAllDataFiltered();
453 CFX_Matrix matrix = original_ap_stream_dict->GetMatrixFor(
"Matrix");
454 CFX_Matrix m = GetMatrix(rcAnnot, rcStream, matrix);
457 fxcrt::ostringstream buf;
462 pNewXObject->SetDataAndRemoveFilter(sStream.unsigned_span());
464 pPageDict->RemoveFor(
"Annots");
fxcrt::ByteString ByteString
constexpr CFX_FloatRect(float l, float b, float r, float t)
CFX_FloatRect & operator=(const CFX_FloatRect &that)=default
constexpr CFX_Matrix()=default
CFX_FloatRect TransformRect(const CFX_FloatRect &rect) const
constexpr CFX_Matrix(float a1, float b1, float c1, float d1, float e1, float f1)
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
bool KeyExist(const ByteString &key) const
void ConvertToIndirectObjectFor(const ByteString &key, CPDF_IndirectObjectHolder *pHolder)
ByteString GetByteStringFor(const ByteString &key) const
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
CFX_FloatRect GetRectFor(const ByteString &key) const
uint32_t AddIndirectObject(RetainPtr< CPDF_Object > pObj)
CPDF_Document * GetDocument() const override
static ByteString Format(const char *pFormat,...)
bool operator==(const char *ptr) const
ByteString & operator+=(const char *str)
ByteString & operator=(ByteString &&that) noexcept
CPDF_Page * CPDFPageFromFPDFPage(FPDF_PAGE page)
FPDF_EXPORT int FPDF_CALLCONV FPDFPage_Flatten(FPDF_PAGE page, int nFlag)
#define FLATTEN_NOTHINGTODO
#define FLAT_NORMALDISPLAY
ByteString operator+(const ByteString &str1, const char *str2)
ByteString operator+(const char *str1, const ByteString &str2)
const char kMacExpertEncoding[]
const char kWinAnsiEncoding[]
const char kMacRomanEncoding[]
fxcrt::ByteStringView ByteStringView