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; }
DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, FS_MATRIX* matrix, FS_RECTF* clipRect) { CPDF_Page* pPage = CPDFPageFromFPDFPage(page); if (!pPage) return false; CFX_ByteTextBuf textBuf; textBuf << "q "; CFX_FloatRect rect(clipRect->left, clipRect->bottom, clipRect->right, clipRect->top); rect.Normalize(); CFX_ByteString bsClipping; bsClipping.Format("%f %f %f %f re W* n ", rect.left, rect.bottom, rect.Width(), rect.Height()); textBuf << bsClipping; CFX_ByteString bsMatix; bsMatix.Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b, matrix->c, matrix->d, matrix->e, matrix->f); textBuf << bsMatix; CPDF_Dictionary* pPageDic = pPage->m_pFormDict; CPDF_Object* pContentObj = pPageDic ? pPageDic->GetObjectFor("Contents") : nullptr; if (!pContentObj) pContentObj = pPageDic ? pPageDic->GetArrayFor("Contents") : nullptr; if (!pContentObj) return false; CPDF_Document* pDoc = pPage->m_pDocument; if (!pDoc) return false; CPDF_Stream* pStream = pDoc->NewIndirect<CPDF_Stream>( nullptr, 0, pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool())); pStream->SetData(textBuf.GetBuffer(), textBuf.GetSize()); CPDF_Stream* pEndStream = pDoc->NewIndirect<CPDF_Stream>( nullptr, 0, pdfium::MakeUnique<CPDF_Dictionary>(pDoc->GetByteStringPool())); pEndStream->SetData((const uint8_t*)" Q", 2); CPDF_Array* pContentArray = nullptr; CPDF_Array* pArray = ToArray(pContentObj); if (pArray) { pContentArray = pArray; pContentArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum()); pContentArray->AddNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum()); } else if (CPDF_Reference* pReference = ToReference(pContentObj)) { CPDF_Object* pDirectObj = pReference->GetDirect(); if (pDirectObj) { CPDF_Array* pObjArray = pDirectObj->AsArray(); if (pObjArray) { pContentArray = pObjArray; pContentArray->InsertNewAt<CPDF_Reference>(0, pDoc, pStream->GetObjNum()); pContentArray->AddNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum()); } else if (pDirectObj->IsStream()) { pContentArray = pDoc->NewIndirect<CPDF_Array>(); pContentArray->AddNew<CPDF_Reference>(pDoc, pStream->GetObjNum()); pContentArray->AddNew<CPDF_Reference>(pDoc, pDirectObj->GetObjNum()); pContentArray->AddNew<CPDF_Reference>(pDoc, pEndStream->GetObjNum()); pPageDic->SetNewFor<CPDF_Reference>("Contents", pDoc, pContentArray->GetObjNum()); } } } // Need to transform the patterns as well. CPDF_Dictionary* pRes = pPageDic->GetDictFor("Resources"); if (pRes) { CPDF_Dictionary* pPattenDict = pRes->GetDictFor("Pattern"); if (pPattenDict) { for (const auto& it : *pPattenDict) { 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; CFX_Matrix m = pDict->GetMatrixFor("Matrix"); CFX_Matrix t = *(CFX_Matrix*)matrix; m.Concat(t); pDict->SetMatrixFor("Matrix", m); } } } return true; }