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 "../include/fsdk_define.h"
8 #include "../include/fpdf_transformpage.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 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)));
21
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 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)));
37
38
39 pPageDict->SetAt("CropBox", pCropBoxArray);
40 }
41
42
FPDFPage_GetMediaBox(FPDF_PAGE page,float * left,float * bottom,float * right,float * top)43 DLLEXPORT FX_BOOL STDCALL FPDFPage_GetMediaBox(FPDF_PAGE page, float* left, float* bottom, float* right, float* top)
44 {
45 if(!page)
46 return FALSE;
47 CPDF_Page* pPage = (CPDF_Page*)page;
48 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
49 CPDF_Array* pArray = pPageDict->GetArray("MediaBox");
50 if(pArray)
51 {
52 *left = pArray->GetFloat(0);
53 *bottom = pArray->GetFloat(1);
54 *right = pArray->GetFloat(2);
55 *top = pArray->GetFloat(3);
56 return TRUE;
57 }
58 return FALSE;
59 }
60
FPDFPage_GetCropBox(FPDF_PAGE page,float * left,float * bottom,float * right,float * top)61 DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GetCropBox(FPDF_PAGE page, float* left, float* bottom, float* right, float* top)
62 {
63 if(!page)
64 return FALSE;
65 CPDF_Page* pPage = (CPDF_Page*)page;
66 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
67 CPDF_Array* pArray = pPageDict->GetArray("CropBox");
68 if(pArray)
69 {
70 *left = pArray->GetFloat(0);
71 *bottom = pArray->GetFloat(1);
72 *right = pArray->GetFloat(2);
73 *top = pArray->GetFloat(3);
74 return TRUE;
75 }
76 return FALSE;
77 }
78
FPDFPage_TransFormWithClip(FPDF_PAGE page,FS_MATRIX * matrix,FS_RECTF * clipRect)79 DLLEXPORT FPDF_BOOL STDCALL FPDFPage_TransFormWithClip(FPDF_PAGE page, FS_MATRIX* matrix, FS_RECTF* clipRect)
80 {
81 if(!page)
82 return FALSE;
83
84 CFX_ByteTextBuf textBuf;
85 textBuf<<"q ";
86 CFX_FloatRect rect(clipRect->left, clipRect->bottom, clipRect->right, clipRect->top);
87 rect.Normalize();
88 CFX_ByteString bsClipping;
89 bsClipping.Format("%f %f %f %f re W* n ", rect.left, rect.bottom, rect.Width(), rect.Height());
90 textBuf<<bsClipping;
91
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);
94 textBuf<<bsMatix;
95
96
97 CPDF_Page* pPage = (CPDF_Page*)page;
98 CPDF_Dictionary* pPageDic = pPage->m_pFormDict;
99 CPDF_Object* pContentObj = pPageDic->GetElement("Contents");
100 if(!pContentObj)
101 pContentObj = pPageDic->GetArray("Contents");
102 if(!pContentObj)
103 return FALSE;
104
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;
109 if(!pDoc)
110 return FALSE;
111 pDoc->AddIndirectObject(pStream);
112
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);
117
118 CPDF_Array* pContentArray = NULL;
119 if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY)
120 {
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);
125
126 }
127 else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE)
128 {
129 CPDF_Reference* pReference = (CPDF_Reference*)pContentObj;
130 CPDF_Object* pDirectObj = pReference->GetDirect();
131 if(pDirectObj != NULL)
132 {
133 if(pDirectObj->GetType() == PDFOBJ_ARRAY)
134 {
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);
139
140 }
141 else if(pDirectObj->GetType() == PDFOBJ_STREAM)
142 {
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));
148 }
149 }
150 }
151
152 //Need to transform the patterns as well.
153 CPDF_Dictionary* pRes = pPageDic->GetDict(FX_BSTRC("Resources"));
154 if(pRes)
155 {
156 CPDF_Dictionary* pPattenDict = pRes->GetDict(FX_BSTRC("Pattern"));
157 if(pPattenDict)
158 {
159 FX_POSITION pos = pPattenDict->GetStartPos();
160 while(pos)
161 {
162 CPDF_Dictionary* pDict = NULL;
163 CFX_ByteString key;
164 CPDF_Object* pObj = pPattenDict->GetNextElement(pos, key);
165 if(pObj->GetType() == PDFOBJ_REFERENCE)
166 pObj = pObj->GetDirect();
167 if(pObj->GetType() == PDFOBJ_DICTIONARY)
168 {
169 pDict = (CPDF_Dictionary*)pObj;
170 }
171 else if(pObj->GetType() == PDFOBJ_STREAM)
172 {
173 pDict = ((CPDF_Stream*)pObj)->GetDict();
174 }
175 else
176 continue;
177
178 CFX_AffineMatrix m = pDict->GetMatrix(FX_BSTRC("Matrix"));
179 CFX_AffineMatrix t = *(CFX_AffineMatrix*)matrix;
180 m.Concat(t);
181 pDict->SetAtMatrix(FX_BSTRC("Matrix"), m);
182 }
183 }
184 }
185
186 return TRUE;
187 }
188
FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object,double a,double b,double c,double d,double e,double f)189 DLLEXPORT void STDCALL FPDFPageObj_TransformClipPath(FPDF_PAGEOBJECT page_object,double a, double b, double c, double d, double e, double f)
190 {
191 CPDF_PageObject* pPageObj = (CPDF_PageObject*)page_object;
192 if(pPageObj == NULL)
193 return;
194 CFX_AffineMatrix matrix((FX_FLOAT)a,(FX_FLOAT)b,(FX_FLOAT)c,(FX_FLOAT)d,(FX_FLOAT)e,(FX_FLOAT)f);
195
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);
200 }
201
202
FPDF_CreateClipPath(float left,float bottom,float right,float top)203 DLLEXPORT FPDF_CLIPPATH STDCALL FPDF_CreateClipPath(float left, float bottom, float right, float top)
204 {
205 CPDF_ClipPath* pNewClipPath = FX_NEW CPDF_ClipPath();
206 pNewClipPath->GetModify();
207 CPDF_Path Path;
208 Path.GetModify();
209 Path.AppendRect(left, bottom, right, top);
210 pNewClipPath->AppendPath(Path, FXFILL_ALTERNATE, FALSE);
211 return pNewClipPath;
212 }
213
FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath)214 DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath)
215 {
216 if(clipPath)
217 delete (CPDF_ClipPath*)clipPath;
218 }
219
OutputPath(CFX_ByteTextBuf & buf,CPDF_Path path)220 void OutputPath(CFX_ByteTextBuf& buf, CPDF_Path path)
221 {
222 const CFX_PathData* pPathData = path;
223 if (pPathData == NULL) return;
224
225 FX_PATHPOINT* pPoints = pPathData->GetPoints();
226
227 if (path.IsRect()) {
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";
231 return;
232 }
233
234 CFX_ByteString temp;
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)
239 buf << " m\n";
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)
244 buf << " c h\n";
245 else
246 buf << " c\n";
247 i += 2;
248 } else if (point_type == FXPT_LINETO) {
249 if (pPoints[i].m_Flag & FXPT_CLOSEFIGURE)
250 buf << " l h\n";
251 else
252 buf << " l\n";
253 }
254 }
255 }
256
FPDFPage_InsertClipPath(FPDF_PAGE page,FPDF_CLIPPATH clipPath)257 DLLEXPORT void STDCALL FPDFPage_InsertClipPath(FPDF_PAGE page,FPDF_CLIPPATH clipPath)
258 {
259 if(!page)
260 return;
261 CPDF_Page* pPage = (CPDF_Page*)page;
262 CPDF_Dictionary* pPageDic = pPage->m_pFormDict;
263 CPDF_Object* pContentObj = pPageDic->GetElement("Contents");
264 if(!pContentObj)
265 pContentObj = pPageDic->GetArray("Contents");
266 if(!pContentObj)
267 return;
268
269 CFX_ByteTextBuf strClip;
270 CPDF_ClipPath* pClipPath = (CPDF_ClipPath*)clipPath;
271 FX_DWORD i;
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 ";
278 } else {
279 OutputPath(strClip, path);
280 if (iClipType == FXFILL_WINDING)
281 strClip << "W n\n";
282 else
283 strClip << "W* n\n";
284 }
285 }
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;
290 if(!pDoc)
291 return;
292 pDoc->AddIndirectObject(pStream);
293
294 CPDF_Array* pContentArray = NULL;
295 if (pContentObj && pContentObj->GetType() == PDFOBJ_ARRAY)
296 {
297 pContentArray = (CPDF_Array*)pContentObj;
298 CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum());
299 pContentArray->InsertAt(0, pRef);
300
301 }
302 else if(pContentObj && pContentObj->GetType() == PDFOBJ_REFERENCE)
303 {
304 CPDF_Reference* pReference = (CPDF_Reference*)pContentObj;
305 CPDF_Object* pDirectObj = pReference->GetDirect();
306 if(pDirectObj != NULL)
307 {
308 if(pDirectObj->GetType() == PDFOBJ_ARRAY)
309 {
310 pContentArray = (CPDF_Array*)pDirectObj;
311 CPDF_Reference* pRef = FX_NEW CPDF_Reference(pDoc, pStream->GetObjNum());
312 pContentArray->InsertAt(0, pRef);
313
314 }
315 else if(pDirectObj->GetType() == PDFOBJ_STREAM)
316 {
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));
321 }
322 }
323 }
324 }
325
326