FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFLink_Enumerate(FPDF_PAGE page, int* start_pos, FPDF_LINK* link_annot) { if (!start_pos || !link_annot) return false; CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage || !pPage->GetDict()) return false; CPDF_Array* pAnnots = pPage->GetDict()->GetArrayFor("Annots"); if (!pAnnots) return false; for (size_t i = *start_pos; i < pAnnots->size(); i++) { CPDF_Dictionary* pDict = ToDictionary(pAnnots->GetDirectObjectAt(i)); if (!pDict) continue; if (pDict->GetStringFor("Subtype") == "Link") { *start_pos = static_cast<int>(i + 1); *link_annot = FPDFLinkFromCPDFDictionary(pDict); return true; } } return false; }
FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertClipPath(FPDF_PAGE page, FPDF_CLIPPATH clipPath) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return; CPDF_Dictionary* pPageDict = pPage->GetDict(); CPDF_Object* pContentObj = GetPageContent(pPageDict); if (!pContentObj) return; std::ostringstream strClip; CPDF_ClipPath* pClipPath = CPDFClipPathFromFPDFClipPath(clipPath); for (size_t i = 0; i < pClipPath->GetPathCount(); ++i) { CPDF_Path path = pClipPath->GetPath(i); if (path.GetPoints().empty()) { // Empty clipping (totally clipped out) strClip << "0 0 m W n "; } else { OutputPath(strClip, path); if (pClipPath->GetClipType(i) == FXFILL_WINDING) strClip << "W n\n"; else strClip << "W* n\n"; } } CPDF_Document* pDoc = pPage->GetDocument(); if (!pDoc) return; CPDF_Stream* pStream = pDoc->NewIndirect<CPDF_Stream>(nullptr, 0, pDoc->New<CPDF_Dictionary>()); pStream->SetDataFromStringstream(&strClip); if (CPDF_Array* pArray = ToArray(pContentObj)) { pArray->InsertAt(0, pStream->MakeReference(pDoc)); } else if (pContentObj->IsStream() && !pContentObj->IsInline()) { CPDF_Array* pContentArray = pDoc->NewIndirect<CPDF_Array>(); pContentArray->Add(pStream->MakeReference(pDoc)); pContentArray->Add(pContentObj->MakeReference(pDoc)); pPageDict->SetFor(pdfium::page_object::kContents, pContentArray->MakeReference(pDoc)); } }
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_TransFormWithClip(FPDF_PAGE page, const FS_MATRIX* matrix, const FS_RECTF* clipRect) { if (!matrix && !clipRect) return false; CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return false; std::ostringstream textBuf; textBuf << "q "; if (clipRect) { CFX_FloatRect rect = CFXFloatRectFromFSRECTF(*clipRect); rect.Normalize(); textBuf << ByteString::Format("%f %f %f %f re W* n ", rect.left, rect.bottom, rect.Width(), rect.Height()); } if (matrix) { textBuf << ByteString::Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, matrix->f); } CPDF_Dictionary* pPageDict = pPage->GetDict(); CPDF_Object* pContentObj = GetPageContent(pPageDict); if (!pContentObj) return false; CPDF_Document* pDoc = pPage->GetDocument(); if (!pDoc) return false; CPDF_Stream* pStream = pDoc->NewIndirect<CPDF_Stream>(nullptr, 0, pDoc->New<CPDF_Dictionary>()); pStream->SetDataFromStringstream(&textBuf); CPDF_Stream* pEndStream = pDoc->NewIndirect<CPDF_Stream>(nullptr, 0, pDoc->New<CPDF_Dictionary>()); pEndStream->SetData(ByteStringView(" Q").span()); if (CPDF_Array* pContentArray = ToArray(pContentObj)) { pContentArray->InsertAt(0, pStream->MakeReference(pDoc)); pContentArray->Add(pEndStream->MakeReference(pDoc)); } else if (pContentObj->IsStream() && !pContentObj->IsInline()) { pContentArray = pDoc->NewIndirect<CPDF_Array>(); pContentArray->Add(pStream->MakeReference(pDoc)); pContentArray->Add(pContentObj->MakeReference(pDoc)); pContentArray->Add(pEndStream->MakeReference(pDoc)); pPageDict->SetFor(pdfium::page_object::kContents, pContentArray->MakeReference(pDoc)); } // Need to transform the patterns as well. CPDF_Dictionary* pRes = pPageDict->GetDictFor(pdfium::page_object::kResources); if (!pRes) return true; CPDF_Dictionary* pPatternDict = pRes->GetDictFor("Pattern"); if (!pPatternDict) return true; CPDF_DictionaryLocker locker(pPatternDict); for (const auto& it : locker) { CPDF_Object* pObj = it.second.get(); if (pObj->IsReference()) pObj = pObj->GetDirect(); CPDF_Dictionary* pDict = nullptr; if (pObj->IsDictionary()) pDict = pObj->AsDictionary(); else if (CPDF_Stream* pObjStream = pObj->AsStream()) pDict = pObjStream->GetDict(); else continue; if (matrix) { CFX_Matrix m = CFXMatrixFromFSMatrix(*matrix); pDict->SetMatrixFor("Matrix", pDict->GetMatrixFor("Matrix") * m); } } return true; }