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 "../include/fsdk_define.h"
      8 #include "../include/fpdf_transformpage.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 	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 
     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 
     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 
     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 
     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 
    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 
    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 
    214 DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath)
    215 {
    216 	if(clipPath)
    217 		delete (CPDF_ClipPath*)clipPath;
    218 }
    219 
    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 
    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