• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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