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.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../public/fpdf_transformpage.h"
8 #include "../include/fsdk_define.h"
9
FPDFPage_SetMediaBox(FPDF_PAGE page,float left,float bottom,float right,float top)10 DLLEXPORT void STDCALL FPDFPage_SetMediaBox(FPDF_PAGE page, float left, float bottom, float right, float top)
11 {
12 if(!page)
13 return;
14
15 CPDF_Page* pPage = (CPDF_Page*)page;
16 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
17 CPDF_Array* pMediaBoxArray = new CPDF_Array;
18 pMediaBoxArray->Add(new CPDF_Number(left));
19 pMediaBoxArray->Add(new CPDF_Number(bottom));
20 pMediaBoxArray->Add(new CPDF_Number(FX_FLOAT(right)));
21 pMediaBoxArray->Add(new CPDF_Number(FX_FLOAT(top)));
22 pPageDict->SetAt("MediaBox", pMediaBoxArray);
23 }
24
25
FPDFPage_SetCropBox(FPDF_PAGE page,float left,float bottom,float right,float top)26 DLLEXPORT void STDCALL FPDFPage_SetCropBox(FPDF_PAGE page, float left, float bottom, float right, float top)
27 {
28 if(!page)
29 return;
30
31 CPDF_Page* pPage = (CPDF_Page*)page;
32 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
33 CPDF_Array* pCropBoxArray = new CPDF_Array;
34 pCropBoxArray->Add(new CPDF_Number(left));
35 pCropBoxArray->Add(new CPDF_Number(bottom));
36 pCropBoxArray->Add(new CPDF_Number(FX_FLOAT(right)));
37 pCropBoxArray->Add(new CPDF_Number(FX_FLOAT(top)));
38 pPageDict->SetAt("CropBox", pCropBoxArray);
39 }
40
41
FPDFPage_GetMediaBox(FPDF_PAGE page,float * left,float * bottom,float * right,float * top)42 DLLEXPORT FX_BOOL STDCALL FPDFPage_GetMediaBox(FPDF_PAGE page, float* left, float* bottom, float* right, float* top)
43 {
44 if(!page)
45 return FALSE;
46 CPDF_Page* pPage = (CPDF_Page*)page;
47 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
48 CPDF_Array* pArray = pPageDict->GetArray("MediaBox");
49 if(pArray)
50 {
51 *left = pArray->GetFloat(0);
52 *bottom = pArray->GetFloat(1);
53 *right = pArray->GetFloat(2);
54 *top = pArray->GetFloat(3);
55 return TRUE;
56 }
57 return FALSE;
58 }
59
FPDFPage_GetCropBox(FPDF_PAGE page,float * left,float * bottom,float * right,float * top)60 DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetCropBox(FPDF_PAGE page, float* left, float* bottom, float* right, float* top)
61 {
62 if(!page)
63 return FALSE;
64 CPDF_Page* pPage = (CPDF_Page*)page;
65 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
66 CPDF_Array* pArray = pPageDict->GetArray("CropBox");
67 if(pArray)
68 {
69 *left = pArray->GetFloat(0);
70 *bottom = pArray->GetFloat(1);
71 *right = pArray->GetFloat(2);
72 *top = pArray->GetFloat(3);
73 return TRUE;
74 }
75 return FALSE;
76 }
77
FPDFPage_TransFormWithClip(FPDF_PAGE page,FS_MATRIX * matrix,FS_RECTF * clipRect)78 DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, FS_MATRIX* matrix, FS_RECTF* clipRect)
79 {
80 if(!page)
81 return FALSE;
82
83 CFX_ByteTextBuf textBuf;
84 textBuf<<"q ";
85 CFX_FloatRect rect(clipRect->left, clipRect->bottom, clipRect->right, clipRect->top);
86 rect.Normalize();
87 CFX_ByteString bsClipping;
88 bsClipping.Format("%f %f %f %f re W* n ", rect.left, rect.bottom, rect.Width(), rect.Height());
89 textBuf<<bsClipping;
90
91 CFX_ByteString bsMatix;
92 bsMatix.Format("%f %f %f %f %f %f cm ", matrix->a, matrix->b,matrix->c,matrix->d,matrix->e,matrix->f);
93 textBuf<<bsMatix;
94
95
96 CPDF_Page* pPage = (CPDF_Page*)page;
97 CPDF_Dictionary* pPageDic = pPage->m_pFormDict;
98 CPDF_Object* pContentObj = pPageDic ? pPageDic->GetElement("Contents") : NULL;
99 if(!pContentObj)
100 pContentObj = pPageDic ? pPageDic->GetArray("Contents") : NULL;
101 if(!pContentObj)
102 return FALSE;
103
104 CPDF_Dictionary* pDic = new CPDF_Dictionary;
105 CPDF_Stream* pStream = new CPDF_Stream(NULL,0, pDic);
106 pStream->SetData(textBuf.GetBuffer(), textBuf.GetSize(), FALSE, FALSE);
107 CPDF_Document* pDoc = pPage->m_pDocument;
108 if(!pDoc)
109 return FALSE;
110 pDoc->AddIndirectObject(pStream);
111
112 pDic = new CPDF_Dictionary;
113 CPDF_Stream* pEndStream = new CPDF_Stream(NULL,0, pDic);
114 pEndStream->SetData((FX_LPCBYTE)" Q", 2, FALSE, FALSE);
115 pDoc->AddIndirectObject(pEndStream);
116
117 CPDF_Array* pContentArray = NULL;
118 if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY)
119 {
120 pContentArray = (CPDF_Array*)pContentObj;
121 CPDF_Reference* pRef = new CPDF_Reference(pDoc, pStream->GetObjNum());
122 pContentArray->InsertAt(0, pRef);
123 pContentArray->AddReference(pDoc,pEndStream);
124
125 }
126 else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE)
127 {
128 CPDF_Reference* pReference = (CPDF_Reference*)pContentObj;
129 CPDF_Object* pDirectObj = pReference->GetDirect();
130 if(pDirectObj != NULL)
131 {
132 if(pDirectObj->GetType() == PDFOBJ_ARRAY)
133 {
134 pContentArray = (CPDF_Array*)pDirectObj;
135 CPDF_Reference* pRef = new CPDF_Reference(pDoc, pStream->GetObjNum());
136 pContentArray->InsertAt(0, pRef);
137 pContentArray->AddReference(pDoc,pEndStream);
138 }
139 else if(pDirectObj->GetType() == PDFOBJ_STREAM)
140 {
141 pContentArray = new CPDF_Array();
142 pContentArray->AddReference(pDoc,pStream->GetObjNum());
143 pContentArray->AddReference(pDoc,pDirectObj->GetObjNum());
144 pContentArray->AddReference(pDoc, pEndStream);
145 pPageDic->SetAtReference("Contents", pDoc, pDoc->AddIndirectObject(pContentArray));
146 }
147 }
148 }
149
150 //Need to transform the patterns as well.
151 CPDF_Dictionary* pRes = pPageDic->GetDict(FX_BSTRC("Resources"));
152 if(pRes)
153 {
154 CPDF_Dictionary* pPattenDict = pRes->GetDict(FX_BSTRC("Pattern"));
155 if(pPattenDict)
156 {
157 FX_POSITION pos = pPattenDict->GetStartPos();
158 while(pos)
159 {
160 CPDF_Dictionary* pDict = NULL;
161 CFX_ByteString key;
162 CPDF_Object* pObj = pPattenDict->GetNextElement(pos, key);
163 if(pObj->GetType() == PDFOBJ_REFERENCE)
164 pObj = pObj->GetDirect();
165 if(pObj->GetType() == PDFOBJ_DICTIONARY)
166 {
167 pDict = (CPDF_Dictionary*)pObj;
168 }
169 else if(pObj->GetType() == PDFOBJ_STREAM)
170 {
171 pDict = ((CPDF_Stream*)pObj)->GetDict();
172 }
173 else
174 continue;
175
176 CFX_AffineMatrix m = pDict->GetMatrix(FX_BSTRC("Matrix"));
177 CFX_AffineMatrix t = *(CFX_AffineMatrix*)matrix;
178 m.Concat(t);
179 pDict->SetAtMatrix(FX_BSTRC("Matrix"), m);
180 }
181 }
182 }
183
184 return TRUE;
185 }
186
FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object,double a,double b,double c,double d,double e,double f)187 DLLEXPORT void STDCALL FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object,double a, double b, double c, double d, double e, double f)
188 {
189 CPDF_PageObject* pPageObj = (CPDF_PageObject*)page_object;
190 if(pPageObj == NULL)
191 return;
192 CFX_AffineMatrix matrix((FX_FLOAT)a,(FX_FLOAT)b,(FX_FLOAT)c,(FX_FLOAT)d,(FX_FLOAT)e,(FX_FLOAT)f);
193
194 //Special treatment to shading object, because the ClipPath for shading object is already transformed.
195 if(pPageObj->m_Type != PDFPAGE_SHADING)
196 pPageObj->TransformClipPath(matrix);
197 pPageObj->TransformGeneralState(matrix);
198 }
199
200
FPDF_CreateClipPath(float left,float bottom,float right,float top)201 DLLEXPORT FPDF_CLIPPATH STDCALL FPDF_CreateClipPath(float left, float bottom, float right, float top)
202 {
203 CPDF_ClipPath* pNewClipPath = new CPDF_ClipPath();
204 pNewClipPath->GetModify();
205 CPDF_Path Path;
206 Path.GetModify();
207 Path.AppendRect(left, bottom, right, top);
208 pNewClipPath->AppendPath(Path, FXFILL_ALTERNATE, FALSE);
209 return pNewClipPath;
210 }
211
FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath)212 DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath)
213 {
214 if(clipPath)
215 delete (CPDF_ClipPath*)clipPath;
216 }
217
OutputPath(CFX_ByteTextBuf & buf,CPDF_Path path)218 void OutputPath(CFX_ByteTextBuf& buf, CPDF_Path path)
219 {
220 const CFX_PathData* pPathData = path;
221 if (pPathData == NULL) return;
222
223 FX_PATHPOINT* pPoints = pPathData->GetPoints();
224
225 if (path.IsRect()) {
226 buf << (pPoints[0].m_PointX) << " " << (pPoints[0].m_PointY) << " "
227 << (pPoints[2].m_PointX - pPoints[0].m_PointX) << " "
228 << (pPoints[2].m_PointY - pPoints[0].m_PointY) << " re\n";
229 return;
230 }
231
232 CFX_ByteString temp;
233 for (int i = 0; i < pPathData->GetPointCount(); i ++) {
234 buf << (pPoints[i].m_PointX) << " " << (pPoints[i].m_PointY);
235 int point_type = pPoints[i].m_Flag & FXPT_TYPE;
236 if (point_type == FXPT_MOVETO)
237 buf << " m\n";
238 else if (point_type == FXPT_BEZIERTO) {
239 buf << " " << (pPoints[i+1].m_PointX) << " " << (pPoints[i+1].m_PointY) << " " <<
240 (pPoints[i+2].m_PointX) << " " << (pPoints[i+2].m_PointY);
241 if (pPoints[i+2].m_Flag & FXPT_CLOSEFIGURE)
242 buf << " c h\n";
243 else
244 buf << " c\n";
245 i += 2;
246 } else if (point_type == FXPT_LINETO) {
247 if (pPoints[i].m_Flag & FXPT_CLOSEFIGURE)
248 buf << " l h\n";
249 else
250 buf << " l\n";
251 }
252 }
253 }
254
FPDFPage_InsertClipPath(FPDF_PAGE page,FPDF_CLIPPATH clipPath)255 DLLEXPORT void STDCALL FPDFPage_InsertClipPath(FPDF_PAGE page,FPDF_CLIPPATH clipPath)
256 {
257 if(!page)
258 return;
259 CPDF_Page* pPage = (CPDF_Page*)page;
260 CPDF_Dictionary* pPageDic = pPage->m_pFormDict;
261 CPDF_Object* pContentObj = pPageDic ? pPageDic->GetElement("Contents") : NULL;
262 if(!pContentObj)
263 pContentObj = pPageDic ? pPageDic->GetArray("Contents") : NULL;
264 if(!pContentObj)
265 return;
266
267 CFX_ByteTextBuf strClip;
268 CPDF_ClipPath* pClipPath = (CPDF_ClipPath*)clipPath;
269 FX_DWORD i;
270 for (i = 0; i < pClipPath->GetPathCount(); i ++) {
271 CPDF_Path path = pClipPath->GetPath(i);
272 int iClipType = pClipPath->GetClipType(i);
273 if (path.GetPointCount() == 0) {
274 // Empty clipping (totally clipped out)
275 strClip << "0 0 m W n ";
276 } else {
277 OutputPath(strClip, path);
278 if (iClipType == FXFILL_WINDING)
279 strClip << "W n\n";
280 else
281 strClip << "W* n\n";
282 }
283 }
284 CPDF_Dictionary* pDic = new CPDF_Dictionary;
285 CPDF_Stream* pStream = new CPDF_Stream(NULL,0, pDic);
286 pStream->SetData(strClip.GetBuffer(), strClip.GetSize(), FALSE, FALSE);
287 CPDF_Document* pDoc = pPage->m_pDocument;
288 if(!pDoc)
289 return;
290 pDoc->AddIndirectObject(pStream);
291
292 CPDF_Array* pContentArray = NULL;
293 if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY)
294 {
295 pContentArray = (CPDF_Array*)pContentObj;
296 CPDF_Reference* pRef = new CPDF_Reference(pDoc, pStream->GetObjNum());
297 pContentArray->InsertAt(0, pRef);
298 }
299 else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE)
300 {
301 CPDF_Reference* pReference = (CPDF_Reference*)pContentObj;
302 CPDF_Object* pDirectObj = pReference->GetDirect();
303 if(pDirectObj != NULL)
304 {
305 if(pDirectObj->GetType() == PDFOBJ_ARRAY)
306 {
307 pContentArray = (CPDF_Array*)pDirectObj;
308 CPDF_Reference* pRef = new CPDF_Reference(pDoc, pStream->GetObjNum());
309 pContentArray->InsertAt(0, pRef);
310 }
311 else if(pDirectObj->GetType() == PDFOBJ_STREAM)
312 {
313 pContentArray = new CPDF_Array();
314 pContentArray->AddReference(pDoc,pStream->GetObjNum());
315 pContentArray->AddReference(pDoc,pDirectObj->GetObjNum());
316 pPageDic->SetAtReference("Contents", pDoc, pDoc->AddIndirectObject(pContentArray));
317 }
318 }
319 }
320 }
321
322