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 10DLLEXPORT 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 26DLLEXPORT 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 42DLLEXPORT 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 60DLLEXPORT 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 78DLLEXPORT 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 187DLLEXPORT 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 201DLLEXPORT 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 212DLLEXPORT void STDCALL FPDF_DestroyClipPath(FPDF_CLIPPATH clipPath) 213{ 214 if(clipPath) 215 delete (CPDF_ClipPath*)clipPath; 216} 217 218void 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 255DLLEXPORT 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