CPDF_Stream* CPDF_Stream::Clone(FX_BOOL bDirect, FPDF_LPFCloneStreamCallback lpfCallback, FX_LPVOID pUserData) const { CPDF_Dictionary *pCloneDict = (CPDF_Dictionary*)m_pDict->Clone(bDirect); IFX_FileStream *pFS = NULL; if (lpfCallback) { pFS = lpfCallback((CPDF_Stream*)this, pUserData); } if (!pFS) { CPDF_StreamAcc acc; acc.LoadAllData(this, TRUE); FX_DWORD streamSize = acc.GetSize(); CPDF_Stream* pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, pCloneDict); return pObj; } CPDF_Stream* pObj = FX_NEW CPDF_Stream(NULL, 0, NULL); CPDF_StreamFilter *pSF = GetStreamFilter(TRUE); if (pSF) { FX_LPBYTE pBuf = FX_Alloc(FX_BYTE, 4096); FX_DWORD dwRead; do { dwRead = pSF->ReadBlock(pBuf, 4096); if (dwRead) { pFS->WriteBlock(pBuf, dwRead); } } while (dwRead == 4096); pFS->Flush(); FX_Free(pBuf); delete pSF; } pObj->InitStream((IFX_FileRead*)pFS, pCloneDict); return pObj; }
DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, FS_MATRIX* matrix, FS_RECTF* clipRect) { if(!page) 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_Page* pPage = (CPDF_Page*)page; CPDF_Dictionary* pPageDic = pPage->m_pFormDict; CPDF_Object* pContentObj = pPageDic->GetElement("Contents"); if(!pContentObj) pContentObj = pPageDic->GetArray("Contents"); if(!pContentObj) return FALSE; CPDF_Dictionary* pDic = FX_NEW CPDF_Dictionary; CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL,0, pDic); pStream->SetData(textBuf.GetBuffer(), textBuf.GetSize(), FALSE, FALSE); CPDF_Document* pDoc = pPage->m_pDocument; if(!pDoc) return FALSE; pDoc->AddIndirectObject(pStream); pDic = FX_NEW CPDF_Dictionary; CPDF_Stream* pEndStream = FX_NEW CPDF_Stream(NULL,0, pDic); pEndStream->SetData((FX_LPCBYTE)" Q", 2, FALSE, FALSE); pDoc->AddIndirectObject(pEndStream); CPDF_Array* pContentArray = NULL; if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY) { pContentArray = (CPDF_Array*)pContentObj; CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum()); pContentArray->InsertAt(0, pRef); pContentArray->AddReference(pDoc,pEndStream); } else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE) { CPDF_Reference* pReference = (CPDF_Reference*)pContentObj; CPDF_Object* pDirectObj = pReference->GetDirect(); if(pDirectObj != NULL) { if(pDirectObj->GetType() == PDFOBJ_ARRAY) { pContentArray = (CPDF_Array*)pDirectObj; CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum()); pContentArray->InsertAt(0, pRef); pContentArray->AddReference(pDoc,pEndStream); } else if(pDirectObj->GetType() == PDFOBJ_STREAM) { pContentArray = FX_NEW CPDF_Array(); pContentArray->AddReference(pDoc,pStream->GetObjNum()); pContentArray->AddReference(pDoc,pDirectObj->GetObjNum()); pContentArray->AddReference(pDoc, pEndStream); pPageDic->SetAtReference("Contents", pDoc, pDoc->AddIndirectObject(pContentArray)); } } } //Need to transform the patterns as well. CPDF_Dictionary* pRes = pPageDic->GetDict(FX_BSTRC("Resources")); if(pRes) { CPDF_Dictionary* pPattenDict = pRes->GetDict(FX_BSTRC("Pattern")); if(pPattenDict) { FX_POSITION pos = pPattenDict->GetStartPos(); while(pos) { CPDF_Dictionary* pDict = NULL; CFX_ByteString key; CPDF_Object* pObj = pPattenDict->GetNextElement(pos, key); if(pObj->GetType() == PDFOBJ_REFERENCE) pObj = pObj->GetDirect(); if(pObj->GetType() == PDFOBJ_DICTIONARY) { pDict = (CPDF_Dictionary*)pObj; } else if(pObj->GetType() == PDFOBJ_STREAM) { pDict = ((CPDF_Stream*)pObj)->GetDict(); } else continue; CFX_AffineMatrix m = pDict->GetMatrix(FX_BSTRC("Matrix")); CFX_AffineMatrix t = *(CFX_AffineMatrix*)matrix; m.Concat(t); pDict->SetAtMatrix(FX_BSTRC("Matrix"), m); } } } return TRUE; }
DLLEXPORT void STDCALL FPDFPage_InsertClipPath(FPDF_PAGE page,FPDF_CLIPPATH clipPath) { if(!page) return; CPDF_Page* pPage = (CPDF_Page*)page; CPDF_Dictionary* pPageDic = pPage->m_pFormDict; CPDF_Object* pContentObj = pPageDic->GetElement("Contents"); if(!pContentObj) pContentObj = pPageDic->GetArray("Contents"); if(!pContentObj) return; CFX_ByteTextBuf strClip; CPDF_ClipPath* pClipPath = (CPDF_ClipPath*)clipPath; FX_DWORD i; for (i = 0; i < pClipPath->GetPathCount(); i ++) { CPDF_Path path = pClipPath->GetPath(i); int iClipType = pClipPath->GetClipType(i); if (path.GetPointCount() == 0) { // Empty clipping (totally clipped out) strClip << "0 0 m W n "; } else { OutputPath(strClip, path); if (iClipType == FXFILL_WINDING) strClip << "W n\n"; else strClip << "W* n\n"; } } CPDF_Dictionary* pDic = FX_NEW CPDF_Dictionary; CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL,0, pDic); pStream->SetData(strClip.GetBuffer(), strClip.GetSize(), FALSE, FALSE); CPDF_Document* pDoc = pPage->m_pDocument; if(!pDoc) return; pDoc->AddIndirectObject(pStream); CPDF_Array* pContentArray = NULL; if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY) { pContentArray = (CPDF_Array*)pContentObj; CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum()); pContentArray->InsertAt(0, pRef); } else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE) { CPDF_Reference* pReference = (CPDF_Reference*)pContentObj; CPDF_Object* pDirectObj = pReference->GetDirect(); if(pDirectObj != NULL) { if(pDirectObj->GetType() == PDFOBJ_ARRAY) { pContentArray = (CPDF_Array*)pDirectObj; CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum()); pContentArray->InsertAt(0, pRef); } else if(pDirectObj->GetType() == PDFOBJ_STREAM) { pContentArray = FX_NEW CPDF_Array(); pContentArray->AddReference(pDoc,pStream->GetObjNum()); pContentArray->AddReference(pDoc,pDirectObj->GetObjNum()); pPageDic->SetAtReference("Contents", pDoc, pDoc->AddIndirectObject(pContentArray)); } } } }
CPDF_Object* CPDF_Object::CloneInternal(FX_BOOL bDirect, CFX_MapPtrToPtr* visited) const { if (this == NULL) { return NULL; } switch (m_Type) { case PDFOBJ_BOOLEAN: return FX_NEW CPDF_Boolean(((CPDF_Boolean*)this)->m_bValue); case PDFOBJ_NUMBER: return FX_NEW CPDF_Number(((CPDF_Number*)this)->m_bInteger, &((CPDF_Number*)this)->m_Integer); case PDFOBJ_STRING: return FX_NEW CPDF_String(((CPDF_String*)this)->m_String, ((CPDF_String*)this)->IsHex()); case PDFOBJ_NAME: return FX_NEW CPDF_Name(((CPDF_Name*)this)->m_Name); case PDFOBJ_ARRAY: { CPDF_Array* pCopy = FX_NEW CPDF_Array(); CPDF_Array* pThis = (CPDF_Array*)this; int n = pThis->GetCount(); for (int i = 0; i < n; i ++) { CPDF_Object* value = (CPDF_Object*)pThis->m_Objects.GetAt(i); pCopy->m_Objects.Add(value->CloneInternal(bDirect, visited)); } return pCopy; } case PDFOBJ_DICTIONARY: { CPDF_Dictionary* pCopy = FX_NEW CPDF_Dictionary(); CPDF_Dictionary* pThis = (CPDF_Dictionary*)this; FX_POSITION pos = pThis->m_Map.GetStartPosition(); while (pos) { CFX_ByteString key; CPDF_Object* value; pThis->m_Map.GetNextAssoc(pos, key, (void*&)value); pCopy->m_Map.SetAt(key, value->CloneInternal(bDirect, visited)); } return pCopy; } case PDFOBJ_NULL: { return FX_NEW CPDF_Null; } case PDFOBJ_STREAM: { CPDF_Stream* pThis = (CPDF_Stream*)this; CPDF_StreamAcc acc; acc.LoadAllData(pThis, TRUE); FX_DWORD streamSize = acc.GetSize(); CPDF_Stream* pObj = FX_NEW CPDF_Stream(acc.DetachData(), streamSize, (CPDF_Dictionary*)((CPDF_Object*)pThis->GetDict())->CloneInternal(bDirect, visited)); return pObj; } case PDFOBJ_REFERENCE: { CPDF_Reference* pRef = (CPDF_Reference*)this; FX_DWORD obj_num = pRef->m_RefObjNum; if (bDirect && !visited->GetValueAt((void*)(FX_UINTPTR)obj_num)) { visited->SetAt((void*)(FX_UINTPTR)obj_num, (void*)1); CPDF_Object* ret = pRef->GetDirect()->CloneInternal(TRUE, visited); return ret; } else { return FX_NEW CPDF_Reference(pRef->m_pObjList, obj_num); } } } return NULL; }
void CPDFSDK_Annot::WriteAppearance(const CFX_ByteString& sAPType, const CPDF_Rect& rcBBox, const CPDF_Matrix& matrix, const CFX_ByteString& sContents, const CFX_ByteString& sAPState) { ASSERT(m_pAnnot != NULL); ASSERT(m_pAnnot->m_pAnnotDict != NULL); CPDF_Dictionary* pAPDict = m_pAnnot->m_pAnnotDict->GetDict("AP"); if (!pAPDict) { pAPDict = FX_NEW CPDF_Dictionary; m_pAnnot->m_pAnnotDict->SetAt("AP", pAPDict); } CPDF_Stream* pStream = NULL; CPDF_Dictionary* pParentDict = NULL; if (sAPState.IsEmpty()) { pParentDict = pAPDict; pStream = pAPDict->GetStream(sAPType); } else { CPDF_Dictionary* pAPTypeDict = pAPDict->GetDict(sAPType); if (!pAPTypeDict) { pAPTypeDict = FX_NEW CPDF_Dictionary; pAPDict->SetAt(sAPType, pAPTypeDict); } pParentDict = pAPTypeDict; pStream = pAPTypeDict->GetStream(sAPState); } if (!pStream) { ASSERT(m_pPageView != NULL); CPDF_Document* pDoc = m_pPageView->GetPDFDocument(); ASSERT(pDoc != NULL); pStream = FX_NEW CPDF_Stream(NULL, 0, NULL); FX_INT32 objnum = pDoc->AddIndirectObject(pStream); //pAPDict->SetAtReference(sAPType, pDoc, objnum); ASSERT(pParentDict != NULL); pParentDict->SetAtReference(sAPType, pDoc, objnum); } CPDF_Dictionary * pStreamDict = pStream->GetDict(); if (!pStreamDict) { pStreamDict = FX_NEW CPDF_Dictionary; pStreamDict->SetAtName("Type", "XObject"); pStreamDict->SetAtName("Subtype", "Form"); pStreamDict->SetAtInteger("FormType", 1); pStream->InitStream(NULL,0,pStreamDict); } if (pStreamDict) { pStreamDict->SetAtMatrix("Matrix",matrix); pStreamDict->SetAtRect("BBox", rcBBox); } pStream->SetData((FX_BYTE*)sContents.c_str(), sContents.GetLength(), FALSE, FALSE); }
DLLEXPORT int STDCALL FPDFPage_Flatten( FPDF_PAGE page, int nFlag) { if (!page) { return FLATTEN_FAIL; } CPDF_Page * pPage = (CPDF_Page*)( page ); CPDF_Document * pDocument = pPage->m_pDocument; CPDF_Dictionary * pPageDict = pPage->m_pFormDict; if ( !pDocument || !pPageDict ) { return FLATTEN_FAIL; } CPDF_ObjectArray ObjectArray; CPDF_RectArray RectArray; int iRet = FLATTEN_FAIL; iRet = ParserAnnots( pDocument, pPageDict, &RectArray, &ObjectArray, nFlag); if (iRet == FLATTEN_NOTINGTODO) { return FLATTEN_NOTINGTODO; }else if (iRet == FLATTEN_FAIL) { return FLATTEN_FAIL; } CPDF_Rect rcOriginalCB; CPDF_Rect rcMerger = CalculateRect( &RectArray ); CPDF_Rect rcOriginalMB = pPageDict->GetRect("MediaBox"); if (pPageDict->KeyExist("CropBox")) rcOriginalMB = pPageDict->GetRect("CropBox"); if (rcOriginalMB.IsEmpty()) { rcOriginalMB = CPDF_Rect(0.0f, 0.0f, 612.0f, 792.0f); } rcMerger.left = rcMerger.left < rcOriginalMB.left? rcOriginalMB.left : rcMerger.left; rcMerger.right = rcMerger.right > rcOriginalMB.right? rcOriginalMB.right : rcMerger.right; rcMerger.top = rcMerger.top > rcOriginalMB.top? rcOriginalMB.top : rcMerger.top; rcMerger.bottom = rcMerger.bottom < rcOriginalMB.bottom? rcOriginalMB.bottom : rcMerger.bottom; if (pPageDict->KeyExist("ArtBox")) rcOriginalCB = pPageDict->GetRect("ArtBox"); else rcOriginalCB = rcOriginalMB; if (!rcOriginalMB.IsEmpty()) { CPDF_Array* pMediaBox = FX_NEW CPDF_Array(); pMediaBox->Add(FX_NEW CPDF_Number(rcOriginalMB.left)); pMediaBox->Add(FX_NEW CPDF_Number(rcOriginalMB.bottom)); pMediaBox->Add(FX_NEW CPDF_Number(rcOriginalMB.right)); pMediaBox->Add(FX_NEW CPDF_Number(rcOriginalMB.top)); pPageDict->SetAt("MediaBox",pMediaBox); } if (!rcOriginalCB.IsEmpty()) { CPDF_Array* pCropBox = FX_NEW CPDF_Array(); pCropBox->Add(FX_NEW CPDF_Number(rcOriginalCB.left)); pCropBox->Add(FX_NEW CPDF_Number(rcOriginalCB.bottom)); pCropBox->Add(FX_NEW CPDF_Number(rcOriginalCB.right)); pCropBox->Add(FX_NEW CPDF_Number(rcOriginalCB.top)); pPageDict->SetAt("ArtBox", pCropBox); } CPDF_Dictionary* pRes = NULL; pRes = pPageDict->GetDict("Resources"); if (!pRes) { pRes = FX_NEW CPDF_Dictionary; pPageDict->SetAt( "Resources", pRes ); } CPDF_Stream* pNewXObject = FX_NEW CPDF_Stream(NULL, 0, FX_NEW CPDF_Dictionary); FX_DWORD dwObjNum = pDocument->AddIndirectObject(pNewXObject); CPDF_Dictionary* pPageXObject = pRes->GetDict("XObject"); if (!pPageXObject) { pPageXObject = FX_NEW CPDF_Dictionary; pRes->SetAt("XObject", pPageXObject); } CFX_ByteString key = ""; int nStreams = ObjectArray.GetSize(); if (nStreams > 0) { for (int iKey = 0; /*iKey < 100*/; iKey++) { char sExtend[5] = {0}; FXSYS_itoa(iKey, sExtend, 10); key = CFX_ByteString("FFT") + CFX_ByteString(sExtend); if (!pPageXObject->KeyExist(key)) break; } } SetPageContents(key, pPageDict, pDocument); CPDF_Dictionary* pNewXORes = NULL; if (!key.IsEmpty()) { pPageXObject->SetAtReference(key, pDocument, dwObjNum); CPDF_Dictionary* pNewOXbjectDic = pNewXObject->GetDict(); pNewXORes = FX_NEW CPDF_Dictionary; pNewOXbjectDic->SetAt("Resources", pNewXORes); pNewOXbjectDic->SetAtName("Type", "XObject"); pNewOXbjectDic->SetAtName("Subtype", "Form"); pNewOXbjectDic->SetAtInteger("FormType", 1); pNewOXbjectDic->SetAtName("Name", "FRM"); CPDF_Rect rcBBox = pPageDict->GetRect("ArtBox"); pNewOXbjectDic->SetAtRect("BBox", rcBBox); } for (int i = 0; i < nStreams; i++) { CPDF_Dictionary* pAnnotDic = ObjectArray.GetAt(i); if (!pAnnotDic)continue; CPDF_Rect rcAnnot = pAnnotDic->GetRect("Rect"); rcAnnot.Normalize(); CFX_ByteString sAnnotState = pAnnotDic->GetString("AS"); CPDF_Dictionary* pAnnotAP = pAnnotDic->GetDict("AP"); if (!pAnnotAP)continue; CPDF_Stream* pAPStream = pAnnotAP->GetStream("N"); if (!pAPStream) { CPDF_Dictionary* pAPDic = pAnnotAP->GetDict("N"); if (!pAPDic)continue; if (!sAnnotState.IsEmpty()) { pAPStream = pAPDic->GetStream(sAnnotState); } else { FX_POSITION pos = pAPDic->GetStartPos(); if (pos) { CFX_ByteString sKey; CPDF_Object* pFirstObj = pAPDic->GetNextElement(pos, sKey); if (pFirstObj) { if (pFirstObj->GetType() == PDFOBJ_REFERENCE) pFirstObj = pFirstObj->GetDirect(); if (pFirstObj->GetType() != PDFOBJ_STREAM) continue; pAPStream = (CPDF_Stream*)pFirstObj; } } } } if (!pAPStream)continue; CPDF_Dictionary* pAPDic = pAPStream->GetDict(); CFX_AffineMatrix matrix = pAPDic->GetMatrix("Matrix"); CPDF_Rect rcStream; if (pAPDic->KeyExist("Rect")) rcStream = pAPDic->GetRect("Rect"); else if (pAPDic->KeyExist("BBox")) rcStream = pAPDic->GetRect("BBox"); if (rcStream.IsEmpty())continue; CPDF_Object* pObj = pAPStream; if (pObj) { CPDF_Dictionary* pObjDic = pObj->GetDict(); if (pObjDic) { pObjDic->SetAtName("Type", "XObject"); pObjDic->SetAtName("Subtype", "Form"); } } CPDF_Dictionary* pXObject = pNewXORes->GetDict("XObject"); if (!pXObject) { pXObject = FX_NEW CPDF_Dictionary; pNewXORes->SetAt("XObject", pXObject); } CFX_ByteString sFormName; sFormName.Format("F%d", i); FX_DWORD dwObjNum = pDocument->AddIndirectObject(pObj); pXObject->SetAtReference(sFormName, pDocument, dwObjNum); CPDF_StreamAcc acc; acc.LoadAllData(pNewXObject); FX_LPCBYTE pData = acc.GetData(); CFX_ByteString sStream(pData, acc.GetSize()); CFX_ByteString sTemp; if (matrix.IsIdentity()) { matrix.a = 1.0f; matrix.b = 0.0f; matrix.c = 0.0f; matrix.d = 1.0f; matrix.e = 0.0f; matrix.f = 0.0f; } CFX_AffineMatrix m = GetMatrix(rcAnnot, rcStream, matrix); sTemp.Format("q %f 0 0 %f %f %f cm /%s Do Q\n", m.a, m.d, m.e, m.f, sFormName.c_str()); sStream += sTemp; pNewXObject->SetData((FX_LPCBYTE)sStream, sStream.GetLength(), FALSE, FALSE); } pPageDict->RemoveAt( "Annots" ); ObjectArray.RemoveAll(); RectArray.RemoveAll(); return FLATTEN_SUCCESS; }
void SetPageContents(CFX_ByteString key, CPDF_Dictionary* pPage, CPDF_Document* pDocument) { CPDF_Object* pContentsObj = pPage->GetStream("Contents"); if (!pContentsObj) { pContentsObj = pPage->GetArray("Contents"); } if (!pContentsObj) { //Create a new contents dictionary if (!key.IsEmpty()) { CPDF_Stream* pNewContents = FX_NEW CPDF_Stream(NULL, 0, FX_NEW CPDF_Dictionary); if (!pNewContents)return; pPage->SetAtReference("Contents", pDocument, pDocument->AddIndirectObject(pNewContents)); CFX_ByteString sStream; sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); pNewContents->SetData((FX_LPCBYTE)sStream, sStream.GetLength(), FALSE, FALSE); } return; } int iType = pContentsObj->GetType(); CPDF_Array* pContentsArray = NULL; switch(iType) { case PDFOBJ_STREAM: { pContentsArray = FX_NEW CPDF_Array; CPDF_Stream* pContents = (CPDF_Stream*)pContentsObj; FX_DWORD dwObjNum = pDocument->AddIndirectObject(pContents); CPDF_StreamAcc acc; acc.LoadAllData(pContents); CFX_ByteString sStream = "q\n"; CFX_ByteString sBody = CFX_ByteString((FX_LPCSTR)acc.GetData(), acc.GetSize()); sStream = sStream + sBody + "\nQ"; pContents->SetData((FX_LPCBYTE)sStream, sStream.GetLength(), FALSE, FALSE); pContentsArray->AddReference(pDocument, dwObjNum); break; } case PDFOBJ_ARRAY: { pContentsArray = (CPDF_Array*)pContentsObj; break; } default: break; } if (!pContentsArray)return; FX_DWORD dwObjNum = pDocument->AddIndirectObject(pContentsArray); pPage->SetAtReference("Contents", pDocument, dwObjNum); if (!key.IsEmpty()) { CPDF_Stream* pNewContents = FX_NEW CPDF_Stream(NULL, 0, FX_NEW CPDF_Dictionary); dwObjNum = pDocument->AddIndirectObject(pNewContents); pContentsArray->AddReference(pDocument, dwObjNum); CFX_ByteString sStream; sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); pNewContents->SetData((FX_LPCBYTE)sStream, sStream.GetLength(), FALSE, FALSE); } }