1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
7 #include "../include/fsdk_define.h"
8 #include "../include/fpdf_transformpage.h"
10 DLLEXPORT void STDCALL FPDFPage_SetMediaBox(FPDF_PAGE page, float left, float bottom, float right, float top)
14 CPDF_Page* pPage = (CPDF_Page*)page;
15 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
16 CPDF_Array* pMediaBoxArray = FX_NEW CPDF_Array;
17 pMediaBoxArray->Add(FX_NEW CPDF_Number(left));
18 pMediaBoxArray->Add(FX_NEW CPDF_Number(bottom));
19 pMediaBoxArray->Add(FX_NEW CPDF_Number(FX_FLOAT(right)));
20 pMediaBoxArray->Add(FX_NEW CPDF_Number(FX_FLOAT(top)));
22 pPageDict->SetAt("MediaBox", pMediaBoxArray);
26 DLLEXPORT void STDCALL FPDFPage_SetCropBox(FPDF_PAGE page, float left, float bottom, float right, float top)
30 CPDF_Page* pPage = (CPDF_Page*)page;
31 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
32 CPDF_Array* pCropBoxArray = FX_NEW CPDF_Array;
33 pCropBoxArray->Add(FX_NEW CPDF_Number(left));
34 pCropBoxArray->Add(FX_NEW CPDF_Number(bottom));
35 pCropBoxArray->Add(FX_NEW CPDF_Number(FX_FLOAT(right)));
36 pCropBoxArray->Add(FX_NEW CPDF_Number(FX_FLOAT(top)));
39 pPageDict->SetAt("CropBox", pCropBoxArray);
43 DLLEXPORT FX_BOOL STDCALL FPDFPage_GetMediaBox(FPDF_PAGE page, float* left, float* bottom, float* right, float* top)
47 CPDF_Page* pPage = (CPDF_Page*)page;
48 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
49 CPDF_Array* pArray = pPageDict->GetArray("MediaBox");
52 *left = pArray->GetFloat(0);
53 *bottom = pArray->GetFloat(1);
54 *right = pArray->GetFloat(2);
55 *top = pArray->GetFloat(3);
61 DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetCropBox(FPDF_PAGE page, float* left, float* bottom, float* right, float* top)
65 CPDF_Page* pPage = (CPDF_Page*)page;
66 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
67 CPDF_Array* pArray = pPageDict->GetArray("CropBox");
70 *left = pArray->GetFloat(0);
71 *bottom = pArray->GetFloat(1);
72 *right = pArray->GetFloat(2);
73 *top = pArray->GetFloat(3);
79 DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, FS_MATRIX* matrix, FS_RECTF* clipRect)
84 CFX_ByteTextBuf textBuf;
86 CFX_FloatRect rect(clipRect->left, clipRect->bottom, clipRect->right, clipRect->top);
88 CFX_ByteString bsClipping;
89 bsClipping.Format("%f %f %f %f re W* n ", rect.left, rect.bottom, rect.Width(), rect.Height());
92 CFX_ByteString bsMatix;
93 bsMatix.Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b,matrix->c,matrix->d,matrix->e,matrix->f);
97 CPDF_Page* pPage = (CPDF_Page*)page;
98 CPDF_Dictionary* pPageDic = pPage->m_pFormDict;
99 CPDF_Object* pContentObj = pPageDic->GetElement("Contents");
101 pContentObj = pPageDic->GetArray("Contents");
105 CPDF_Dictionary* pDic = FX_NEW CPDF_Dictionary;
106 CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL,0, pDic);
107 pStream->SetData(textBuf.GetBuffer(), textBuf.GetSize(), FALSE, FALSE);
108 CPDF_Document* pDoc = pPage->m_pDocument;
111 pDoc->AddIndirectObject(pStream);
113 pDic = FX_NEW CPDF_Dictionary;
114 CPDF_Stream* pEndStream = FX_NEW CPDF_Stream(NULL,0, pDic);
115 pEndStream->SetData((FX_LPCBYTE)" Q", 2, FALSE, FALSE);
116 pDoc->AddIndirectObject(pEndStream);
118 CPDF_Array* pContentArray = NULL;
119 if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY)
121 pContentArray = (CPDF_Array*)pContentObj;
122 CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum());
123 pContentArray->InsertAt(0, pRef);
124 pContentArray->AddReference(pDoc,pEndStream);
127 else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE)
129 CPDF_Reference* pReference = (CPDF_Reference*)pContentObj;
130 CPDF_Object* pDirectObj = pReference->GetDirect();
131 if(pDirectObj != NULL)
133 if(pDirectObj->GetType() == PDFOBJ_ARRAY)
135 pContentArray = (CPDF_Array*)pDirectObj;
136 CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum());
137 pContentArray->InsertAt(0, pRef);
138 pContentArray->AddReference(pDoc,pEndStream);
141 else if(pDirectObj->GetType() == PDFOBJ_STREAM)
143 pContentArray = FX_NEW CPDF_Array();
144 pContentArray->AddReference(pDoc,pStream->GetObjNum());
145 pContentArray->AddReference(pDoc,pDirectObj->GetObjNum());
146 pContentArray->AddReference(pDoc, pEndStream);
147 pPageDic->SetAtReference("Contents", pDoc, pDoc->AddIndirectObject(pContentArray));
152 //Need to transform the patterns as well.
153 CPDF_Dictionary* pRes = pPageDic->GetDict(FX_BSTRC("Resources"));
156 CPDF_Dictionary* pPattenDict = pRes->GetDict(FX_BSTRC("Pattern"));
159 FX_POSITION pos = pPattenDict->GetStartPos();
162 CPDF_Dictionary* pDict = NULL;
164 CPDF_Object* pObj = pPattenDict->GetNextElement(pos, key);
165 if(pObj->GetType() == PDFOBJ_REFERENCE)
166 pObj = pObj->GetDirect();
167 if(pObj->GetType() == PDFOBJ_DICTIONARY)
169 pDict = (CPDF_Dictionary*)pObj;
171 else if(pObj->GetType() == PDFOBJ_STREAM)
173 pDict = ((CPDF_Stream*)pObj)->GetDict();
178 CFX_AffineMatrix m = pDict->GetMatrix(FX_BSTRC("Matrix"));
179 CFX_AffineMatrix t = *(CFX_AffineMatrix*)matrix;
181 pDict->SetAtMatrix(FX_BSTRC("Matrix"), m);
189 DLLEXPORT void STDCALL FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object,double a, double b, double c, double d, double e, double f)
191 CPDF_PageObject* pPageObj = (CPDF_PageObject*)page_object;
194 CFX_AffineMatrix matrix((FX_FLOAT)a,(FX_FLOAT)b,(FX_FLOAT)c,(FX_FLOAT)d,(FX_FLOAT)e,(FX_FLOAT)f);
196 //Special treatment to shading object, because the ClipPath for shading object is already transformed.
197 if(pPageObj->m_Type != PDFPAGE_SHADING)
198 pPageObj->TransformClipPath(matrix);
199 pPageObj->TransformGeneralState(matrix);
203 DLLEXPORT FPDF_CLIPPATH STDCALL FPDF_CreateClipPath(float left, float bottom, float right, float top)
205 CPDF_ClipPath* pNewClipPath = FX_NEW CPDF_ClipPath();
206 pNewClipPath->GetModify();
209 Path.AppendRect(left, bottom, right, top);
210 pNewClipPath->AppendPath(Path, FXFILL_ALTERNATE, FALSE);
214 DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath)
217 delete (CPDF_ClipPath*)clipPath;
220 void OutputPath(CFX_ByteTextBuf& buf, CPDF_Path path)
222 const CFX_PathData* pPathData = path;
223 if (pPathData == NULL) return;
225 FX_PATHPOINT* pPoints = pPathData->GetPoints();
228 buf << (pPoints[0].m_PointX) << " " << (pPoints[0].m_PointY) << " "
229 << (pPoints[2].m_PointX - pPoints[0].m_PointX) << " "
230 << (pPoints[2].m_PointY - pPoints[0].m_PointY) << " re\n";
235 for (int i = 0; i < pPathData->GetPointCount(); i ++) {
236 buf << (pPoints[i].m_PointX) << " " << (pPoints[i].m_PointY);
237 int point_type = pPoints[i].m_Flag & FXPT_TYPE;
238 if (point_type == FXPT_MOVETO)
240 else if (point_type == FXPT_BEZIERTO) {
241 buf << " " << (pPoints[i+1].m_PointX) << " " << (pPoints[i+1].m_PointY) << " " <<
242 (pPoints[i+2].m_PointX) << " " << (pPoints[i+2].m_PointY);
243 if (pPoints[i+2].m_Flag & FXPT_CLOSEFIGURE)
248 } else if (point_type == FXPT_LINETO) {
249 if (pPoints[i].m_Flag & FXPT_CLOSEFIGURE)
257 DLLEXPORT void STDCALL FPDFPage_InsertClipPath(FPDF_PAGE page,FPDF_CLIPPATH clipPath)
261 CPDF_Page* pPage = (CPDF_Page*)page;
262 CPDF_Dictionary* pPageDic = pPage->m_pFormDict;
263 CPDF_Object* pContentObj = pPageDic->GetElement("Contents");
265 pContentObj = pPageDic->GetArray("Contents");
269 CFX_ByteTextBuf strClip;
270 CPDF_ClipPath* pClipPath = (CPDF_ClipPath*)clipPath;
272 for (i = 0; i < pClipPath->GetPathCount(); i ++) {
273 CPDF_Path path = pClipPath->GetPath(i);
274 int iClipType = pClipPath->GetClipType(i);
275 if (path.GetPointCount() == 0) {
276 // Empty clipping (totally clipped out)
277 strClip << "0 0 m W n ";
279 OutputPath(strClip, path);
280 if (iClipType == FXFILL_WINDING)
286 CPDF_Dictionary* pDic = FX_NEW CPDF_Dictionary;
287 CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL,0, pDic);
288 pStream->SetData(strClip.GetBuffer(), strClip.GetSize(), FALSE, FALSE);
289 CPDF_Document* pDoc = pPage->m_pDocument;
292 pDoc->AddIndirectObject(pStream);
294 CPDF_Array* pContentArray = NULL;
295 if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY)
297 pContentArray = (CPDF_Array*)pContentObj;
298 CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum());
299 pContentArray->InsertAt(0, pRef);
302 else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE)
304 CPDF_Reference* pReference = (CPDF_Reference*)pContentObj;
305 CPDF_Object* pDirectObj = pReference->GetDirect();
306 if(pDirectObj != NULL)
308 if(pDirectObj->GetType() == PDFOBJ_ARRAY)
310 pContentArray = (CPDF_Array*)pDirectObj;
311 CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum());
312 pContentArray->InsertAt(0, pRef);
315 else if(pDirectObj->GetType() == PDFOBJ_STREAM)
317 pContentArray = FX_NEW CPDF_Array();
318 pContentArray->AddReference(pDoc,pStream->GetObjNum());
319 pContentArray->AddReference(pDoc,pDirectObj->GetObjNum());
320 pPageDic->SetAtReference("Contents", pDoc, pDoc->AddIndirectObject(pContentArray));