Home | History | Annotate | Download | only in src
      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 
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    212 DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath)
    213 {
    214 	if(clipPath)
    215 		delete (CPDF_ClipPath*)clipPath;
    216 }
    217 
    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 
    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