OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "public/fpdf_flatten.h" | 7 #include "public/fpdf_flatten.h" |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
11 #include "fpdfsdk/include/fsdk_define.h" | 11 #include "fpdfsdk/include/fsdk_define.h" |
12 | 12 |
13 typedef CFX_ArrayTemplate<CPDF_Dictionary*> CPDF_ObjectArray; | 13 typedef CFX_ArrayTemplate<CPDF_Dictionary*> CPDF_ObjectArray; |
14 typedef CFX_ArrayTemplate<CPDF_Rect> CPDF_RectArray; | 14 typedef CFX_ArrayTemplate<CFX_FloatRect> CPDF_RectArray; |
15 | 15 |
16 enum FPDF_TYPE { MAX, MIN }; | 16 enum FPDF_TYPE { MAX, MIN }; |
17 enum FPDF_VALUE { TOP, LEFT, RIGHT, BOTTOM }; | 17 enum FPDF_VALUE { TOP, LEFT, RIGHT, BOTTOM }; |
18 | 18 |
19 FX_BOOL IsValiableRect(CPDF_Rect rect, CPDF_Rect rcPage) { | 19 FX_BOOL IsValiableRect(CFX_FloatRect rect, CFX_FloatRect rcPage) { |
20 if (rect.left - rect.right > 0.000001f || rect.bottom - rect.top > 0.000001f) | 20 if (rect.left - rect.right > 0.000001f || rect.bottom - rect.top > 0.000001f) |
21 return FALSE; | 21 return FALSE; |
22 | 22 |
23 if (rect.left == 0.0f && rect.top == 0.0f && rect.right == 0.0f && | 23 if (rect.left == 0.0f && rect.top == 0.0f && rect.right == 0.0f && |
24 rect.bottom == 0.0f) | 24 rect.bottom == 0.0f) |
25 return FALSE; | 25 return FALSE; |
26 | 26 |
27 if (!rcPage.IsEmpty()) { | 27 if (!rcPage.IsEmpty()) { |
28 if (rect.left - rcPage.left < -10.000001f || | 28 if (rect.left - rcPage.left < -10.000001f || |
29 rect.right - rcPage.right > 10.000001f || | 29 rect.right - rcPage.right > 10.000001f || |
30 rect.top - rcPage.top > 10.000001f || | 30 rect.top - rcPage.top > 10.000001f || |
31 rect.bottom - rcPage.bottom < -10.000001f) | 31 rect.bottom - rcPage.bottom < -10.000001f) |
32 return FALSE; | 32 return FALSE; |
33 } | 33 } |
34 | 34 |
35 return TRUE; | 35 return TRUE; |
36 } | 36 } |
37 | 37 |
38 void GetContentsRect(CPDF_Document* pDoc, | 38 void GetContentsRect(CPDF_Document* pDoc, |
39 CPDF_Dictionary* pDict, | 39 CPDF_Dictionary* pDict, |
40 CPDF_RectArray* pRectArray) { | 40 CPDF_RectArray* pRectArray) { |
41 std::unique_ptr<CPDF_Page> pPDFPage(new CPDF_Page); | 41 std::unique_ptr<CPDF_Page> pPDFPage(new CPDF_Page); |
42 pPDFPage->Load(pDoc, pDict, FALSE); | 42 pPDFPage->Load(pDoc, pDict, FALSE); |
43 pPDFPage->ParseContent(nullptr); | 43 pPDFPage->ParseContent(nullptr); |
44 | 44 |
45 for (auto& pPageObject : *pPDFPage->GetPageObjectList()) { | 45 for (auto& pPageObject : *pPDFPage->GetPageObjectList()) { |
46 if (!pPageObject) | 46 if (!pPageObject) |
47 continue; | 47 continue; |
48 | 48 |
49 CPDF_Rect rc; | 49 CFX_FloatRect rc; |
50 rc.left = pPageObject->m_Left; | 50 rc.left = pPageObject->m_Left; |
51 rc.right = pPageObject->m_Right; | 51 rc.right = pPageObject->m_Right; |
52 rc.bottom = pPageObject->m_Bottom; | 52 rc.bottom = pPageObject->m_Bottom; |
53 rc.top = pPageObject->m_Top; | 53 rc.top = pPageObject->m_Top; |
54 if (IsValiableRect(rc, pDict->GetRectBy("MediaBox"))) | 54 if (IsValiableRect(rc, pDict->GetRectBy("MediaBox"))) |
55 pRectArray->Add(rc); | 55 pRectArray->Add(rc); |
56 } | 56 } |
57 } | 57 } |
58 | 58 |
59 void ParserStream(CPDF_Dictionary* pPageDic, | 59 void ParserStream(CPDF_Dictionary* pPageDic, |
60 CPDF_Dictionary* pStream, | 60 CPDF_Dictionary* pStream, |
61 CPDF_RectArray* pRectArray, | 61 CPDF_RectArray* pRectArray, |
62 CPDF_ObjectArray* pObjectArray) { | 62 CPDF_ObjectArray* pObjectArray) { |
63 if (!pStream) | 63 if (!pStream) |
64 return; | 64 return; |
65 CPDF_Rect rect; | 65 CFX_FloatRect rect; |
66 if (pStream->KeyExist("Rect")) | 66 if (pStream->KeyExist("Rect")) |
67 rect = pStream->GetRectBy("Rect"); | 67 rect = pStream->GetRectBy("Rect"); |
68 else if (pStream->KeyExist("BBox")) | 68 else if (pStream->KeyExist("BBox")) |
69 rect = pStream->GetRectBy("BBox"); | 69 rect = pStream->GetRectBy("BBox"); |
70 | 70 |
71 if (IsValiableRect(rect, pPageDic->GetRectBy("MediaBox"))) | 71 if (IsValiableRect(rect, pPageDic->GetRectBy("MediaBox"))) |
72 pRectArray->Add(rect); | 72 pRectArray->Add(rect); |
73 | 73 |
74 pObjectArray->Add(pStream); | 74 pObjectArray->Add(pStream); |
75 } | 75 } |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 int nRects = array.GetSize(); | 120 int nRects = array.GetSize(); |
121 FX_FLOAT fRet = 0.0f; | 121 FX_FLOAT fRet = 0.0f; |
122 | 122 |
123 if (nRects <= 0) | 123 if (nRects <= 0) |
124 return 0.0f; | 124 return 0.0f; |
125 | 125 |
126 FX_FLOAT* pArray = new FX_FLOAT[nRects]; | 126 FX_FLOAT* pArray = new FX_FLOAT[nRects]; |
127 switch (value) { | 127 switch (value) { |
128 case LEFT: { | 128 case LEFT: { |
129 for (int i = 0; i < nRects; i++) | 129 for (int i = 0; i < nRects; i++) |
130 pArray[i] = CPDF_Rect(array.GetAt(i)).left; | 130 pArray[i] = CFX_FloatRect(array.GetAt(i)).left; |
131 | 131 |
132 break; | 132 break; |
133 } | 133 } |
134 case TOP: { | 134 case TOP: { |
135 for (int i = 0; i < nRects; i++) | 135 for (int i = 0; i < nRects; i++) |
136 pArray[i] = CPDF_Rect(array.GetAt(i)).top; | 136 pArray[i] = CFX_FloatRect(array.GetAt(i)).top; |
137 | 137 |
138 break; | 138 break; |
139 } | 139 } |
140 case RIGHT: { | 140 case RIGHT: { |
141 for (int i = 0; i < nRects; i++) | 141 for (int i = 0; i < nRects; i++) |
142 pArray[i] = CPDF_Rect(array.GetAt(i)).right; | 142 pArray[i] = CFX_FloatRect(array.GetAt(i)).right; |
143 | 143 |
144 break; | 144 break; |
145 } | 145 } |
146 case BOTTOM: { | 146 case BOTTOM: { |
147 for (int i = 0; i < nRects; i++) | 147 for (int i = 0; i < nRects; i++) |
148 pArray[i] = CPDF_Rect(array.GetAt(i)).bottom; | 148 pArray[i] = CFX_FloatRect(array.GetAt(i)).bottom; |
149 | 149 |
150 break; | 150 break; |
151 } | 151 } |
152 default: | 152 default: |
153 break; | 153 break; |
154 } | 154 } |
155 fRet = pArray[0]; | 155 fRet = pArray[0]; |
156 if (type == MAX) { | 156 if (type == MAX) { |
157 for (int i = 1; i < nRects; i++) | 157 for (int i = 1; i < nRects; i++) |
158 if (fRet <= pArray[i]) | 158 if (fRet <= pArray[i]) |
159 fRet = pArray[i]; | 159 fRet = pArray[i]; |
160 } else { | 160 } else { |
161 for (int i = 1; i < nRects; i++) | 161 for (int i = 1; i < nRects; i++) |
162 if (fRet >= pArray[i]) | 162 if (fRet >= pArray[i]) |
163 fRet = pArray[i]; | 163 fRet = pArray[i]; |
164 } | 164 } |
165 delete[] pArray; | 165 delete[] pArray; |
166 return fRet; | 166 return fRet; |
167 } | 167 } |
168 | 168 |
169 CPDF_Rect CalculateRect(CPDF_RectArray* pRectArray) { | 169 CFX_FloatRect CalculateRect(CPDF_RectArray* pRectArray) { |
170 CPDF_Rect rcRet; | 170 CFX_FloatRect rcRet; |
171 | 171 |
172 rcRet.left = GetMinMaxValue(*pRectArray, MIN, LEFT); | 172 rcRet.left = GetMinMaxValue(*pRectArray, MIN, LEFT); |
173 rcRet.top = GetMinMaxValue(*pRectArray, MAX, TOP); | 173 rcRet.top = GetMinMaxValue(*pRectArray, MAX, TOP); |
174 rcRet.right = GetMinMaxValue(*pRectArray, MAX, RIGHT); | 174 rcRet.right = GetMinMaxValue(*pRectArray, MAX, RIGHT); |
175 rcRet.bottom = GetMinMaxValue(*pRectArray, MIN, BOTTOM); | 175 rcRet.bottom = GetMinMaxValue(*pRectArray, MIN, BOTTOM); |
176 | 176 |
177 return rcRet; | 177 return rcRet; |
178 } | 178 } |
179 | 179 |
180 void SetPageContents(CFX_ByteString key, | 180 void SetPageContents(CFX_ByteString key, |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 dwObjNum = pDocument->AddIndirectObject(pNewContents); | 238 dwObjNum = pDocument->AddIndirectObject(pNewContents); |
239 pContentsArray->AddReference(pDocument, dwObjNum); | 239 pContentsArray->AddReference(pDocument, dwObjNum); |
240 | 240 |
241 CFX_ByteString sStream; | 241 CFX_ByteString sStream; |
242 sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); | 242 sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); |
243 pNewContents->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE, | 243 pNewContents->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE, |
244 FALSE); | 244 FALSE); |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 CFX_Matrix GetMatrix(CPDF_Rect rcAnnot, | 248 CFX_Matrix GetMatrix(CFX_FloatRect rcAnnot, |
249 CPDF_Rect rcStream, | 249 CFX_FloatRect rcStream, |
250 const CFX_Matrix& matrix) { | 250 const CFX_Matrix& matrix) { |
251 if (rcStream.IsEmpty()) | 251 if (rcStream.IsEmpty()) |
252 return CFX_Matrix(); | 252 return CFX_Matrix(); |
253 | 253 |
254 matrix.TransformRect(rcStream); | 254 matrix.TransformRect(rcStream); |
255 rcStream.Normalize(); | 255 rcStream.Normalize(); |
256 | 256 |
257 FX_FLOAT a = rcAnnot.Width() / rcStream.Width(); | 257 FX_FLOAT a = rcAnnot.Width() / rcStream.Width(); |
258 FX_FLOAT d = rcAnnot.Height() / rcStream.Height(); | 258 FX_FLOAT d = rcAnnot.Height() / rcStream.Height(); |
259 | 259 |
260 FX_FLOAT e = rcAnnot.left - rcStream.left * a; | 260 FX_FLOAT e = rcAnnot.left - rcStream.left * a; |
261 FX_FLOAT f = rcAnnot.bottom - rcStream.bottom * d; | 261 FX_FLOAT f = rcAnnot.bottom - rcStream.bottom * d; |
262 return CFX_Matrix(a, 0, 0, d, e, f); | 262 return CFX_Matrix(a, 0, 0, d, e, f); |
263 } | 263 } |
264 | 264 |
265 void GetOffset(FX_FLOAT& fa, | 265 void GetOffset(FX_FLOAT& fa, |
266 FX_FLOAT& fd, | 266 FX_FLOAT& fd, |
267 FX_FLOAT& fe, | 267 FX_FLOAT& fe, |
268 FX_FLOAT& ff, | 268 FX_FLOAT& ff, |
269 CPDF_Rect rcAnnot, | 269 CFX_FloatRect rcAnnot, |
270 CPDF_Rect rcStream, | 270 CFX_FloatRect rcStream, |
271 const CFX_Matrix& matrix) { | 271 const CFX_Matrix& matrix) { |
272 FX_FLOAT fStreamWidth = 0.0f; | 272 FX_FLOAT fStreamWidth = 0.0f; |
273 FX_FLOAT fStreamHeight = 0.0f; | 273 FX_FLOAT fStreamHeight = 0.0f; |
274 | 274 |
275 if (matrix.a != 0 && matrix.d != 0) { | 275 if (matrix.a != 0 && matrix.d != 0) { |
276 fStreamWidth = rcStream.right - rcStream.left; | 276 fStreamWidth = rcStream.right - rcStream.left; |
277 fStreamHeight = rcStream.top - rcStream.bottom; | 277 fStreamHeight = rcStream.top - rcStream.bottom; |
278 } else { | 278 } else { |
279 fStreamWidth = rcStream.top - rcStream.bottom; | 279 fStreamWidth = rcStream.top - rcStream.bottom; |
280 fStreamHeight = rcStream.right - rcStream.left; | 280 fStreamHeight = rcStream.right - rcStream.left; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 } | 316 } |
317 | 317 |
318 CPDF_ObjectArray ObjectArray; | 318 CPDF_ObjectArray ObjectArray; |
319 CPDF_RectArray RectArray; | 319 CPDF_RectArray RectArray; |
320 | 320 |
321 int iRet = FLATTEN_FAIL; | 321 int iRet = FLATTEN_FAIL; |
322 iRet = ParserAnnots(pDocument, pPageDict, &RectArray, &ObjectArray, nFlag); | 322 iRet = ParserAnnots(pDocument, pPageDict, &RectArray, &ObjectArray, nFlag); |
323 if (iRet == FLATTEN_NOTHINGTODO || iRet == FLATTEN_FAIL) | 323 if (iRet == FLATTEN_NOTHINGTODO || iRet == FLATTEN_FAIL) |
324 return iRet; | 324 return iRet; |
325 | 325 |
326 CPDF_Rect rcOriginalCB; | 326 CFX_FloatRect rcOriginalCB; |
327 CPDF_Rect rcMerger = CalculateRect(&RectArray); | 327 CFX_FloatRect rcMerger = CalculateRect(&RectArray); |
328 CPDF_Rect rcOriginalMB = pPageDict->GetRectBy("MediaBox"); | 328 CFX_FloatRect rcOriginalMB = pPageDict->GetRectBy("MediaBox"); |
329 | 329 |
330 if (pPageDict->KeyExist("CropBox")) | 330 if (pPageDict->KeyExist("CropBox")) |
331 rcOriginalMB = pPageDict->GetRectBy("CropBox"); | 331 rcOriginalMB = pPageDict->GetRectBy("CropBox"); |
332 | 332 |
333 if (rcOriginalMB.IsEmpty()) { | 333 if (rcOriginalMB.IsEmpty()) { |
334 rcOriginalMB = CPDF_Rect(0.0f, 0.0f, 612.0f, 792.0f); | 334 rcOriginalMB = CFX_FloatRect(0.0f, 0.0f, 612.0f, 792.0f); |
335 } | 335 } |
336 | 336 |
337 rcMerger.left = | 337 rcMerger.left = |
338 rcMerger.left < rcOriginalMB.left ? rcOriginalMB.left : rcMerger.left; | 338 rcMerger.left < rcOriginalMB.left ? rcOriginalMB.left : rcMerger.left; |
339 rcMerger.right = | 339 rcMerger.right = |
340 rcMerger.right > rcOriginalMB.right ? rcOriginalMB.right : rcMerger.right; | 340 rcMerger.right > rcOriginalMB.right ? rcOriginalMB.right : rcMerger.right; |
341 rcMerger.top = | 341 rcMerger.top = |
342 rcMerger.top > rcOriginalMB.top ? rcOriginalMB.top : rcMerger.top; | 342 rcMerger.top > rcOriginalMB.top ? rcOriginalMB.top : rcMerger.top; |
343 rcMerger.bottom = rcMerger.bottom < rcOriginalMB.bottom ? rcOriginalMB.bottom | 343 rcMerger.bottom = rcMerger.bottom < rcOriginalMB.bottom ? rcOriginalMB.bottom |
344 : rcMerger.bottom; | 344 : rcMerger.bottom; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
400 | 400 |
401 if (!key.IsEmpty()) { | 401 if (!key.IsEmpty()) { |
402 pPageXObject->SetAtReference(key, pDocument, dwObjNum); | 402 pPageXObject->SetAtReference(key, pDocument, dwObjNum); |
403 CPDF_Dictionary* pNewOXbjectDic = pNewXObject->GetDict(); | 403 CPDF_Dictionary* pNewOXbjectDic = pNewXObject->GetDict(); |
404 pNewXORes = new CPDF_Dictionary; | 404 pNewXORes = new CPDF_Dictionary; |
405 pNewOXbjectDic->SetAt("Resources", pNewXORes); | 405 pNewOXbjectDic->SetAt("Resources", pNewXORes); |
406 pNewOXbjectDic->SetAtName("Type", "XObject"); | 406 pNewOXbjectDic->SetAtName("Type", "XObject"); |
407 pNewOXbjectDic->SetAtName("Subtype", "Form"); | 407 pNewOXbjectDic->SetAtName("Subtype", "Form"); |
408 pNewOXbjectDic->SetAtInteger("FormType", 1); | 408 pNewOXbjectDic->SetAtInteger("FormType", 1); |
409 pNewOXbjectDic->SetAtName("Name", "FRM"); | 409 pNewOXbjectDic->SetAtName("Name", "FRM"); |
410 CPDF_Rect rcBBox = pPageDict->GetRectBy("ArtBox"); | 410 CFX_FloatRect rcBBox = pPageDict->GetRectBy("ArtBox"); |
411 pNewOXbjectDic->SetAtRect("BBox", rcBBox); | 411 pNewOXbjectDic->SetAtRect("BBox", rcBBox); |
412 } | 412 } |
413 | 413 |
414 for (int i = 0; i < nStreams; i++) { | 414 for (int i = 0; i < nStreams; i++) { |
415 CPDF_Dictionary* pAnnotDic = ObjectArray.GetAt(i); | 415 CPDF_Dictionary* pAnnotDic = ObjectArray.GetAt(i); |
416 if (!pAnnotDic) | 416 if (!pAnnotDic) |
417 continue; | 417 continue; |
418 | 418 |
419 CPDF_Rect rcAnnot = pAnnotDic->GetRectBy("Rect"); | 419 CFX_FloatRect rcAnnot = pAnnotDic->GetRectBy("Rect"); |
420 rcAnnot.Normalize(); | 420 rcAnnot.Normalize(); |
421 | 421 |
422 CFX_ByteString sAnnotState = pAnnotDic->GetStringBy("AS"); | 422 CFX_ByteString sAnnotState = pAnnotDic->GetStringBy("AS"); |
423 CPDF_Dictionary* pAnnotAP = pAnnotDic->GetDictBy("AP"); | 423 CPDF_Dictionary* pAnnotAP = pAnnotDic->GetDictBy("AP"); |
424 if (!pAnnotAP) | 424 if (!pAnnotAP) |
425 continue; | 425 continue; |
426 | 426 |
427 CPDF_Stream* pAPStream = pAnnotAP->GetStreamBy("N"); | 427 CPDF_Stream* pAPStream = pAnnotAP->GetStreamBy("N"); |
428 if (!pAPStream) { | 428 if (!pAPStream) { |
429 CPDF_Dictionary* pAPDic = pAnnotAP->GetDictBy("N"); | 429 CPDF_Dictionary* pAPDic = pAnnotAP->GetDictBy("N"); |
(...skipping 15 matching lines...) Expand all Loading... |
445 } | 445 } |
446 } | 446 } |
447 } | 447 } |
448 } | 448 } |
449 if (!pAPStream) | 449 if (!pAPStream) |
450 continue; | 450 continue; |
451 | 451 |
452 CPDF_Dictionary* pAPDic = pAPStream->GetDict(); | 452 CPDF_Dictionary* pAPDic = pAPStream->GetDict(); |
453 CFX_Matrix matrix = pAPDic->GetMatrixBy("Matrix"); | 453 CFX_Matrix matrix = pAPDic->GetMatrixBy("Matrix"); |
454 | 454 |
455 CPDF_Rect rcStream; | 455 CFX_FloatRect rcStream; |
456 if (pAPDic->KeyExist("Rect")) | 456 if (pAPDic->KeyExist("Rect")) |
457 rcStream = pAPDic->GetRectBy("Rect"); | 457 rcStream = pAPDic->GetRectBy("Rect"); |
458 else if (pAPDic->KeyExist("BBox")) | 458 else if (pAPDic->KeyExist("BBox")) |
459 rcStream = pAPDic->GetRectBy("BBox"); | 459 rcStream = pAPDic->GetRectBy("BBox"); |
460 | 460 |
461 if (rcStream.IsEmpty()) | 461 if (rcStream.IsEmpty()) |
462 continue; | 462 continue; |
463 | 463 |
464 CPDF_Object* pObj = pAPStream; | 464 CPDF_Object* pObj = pAPStream; |
465 | 465 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 pNewXObject->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE, | 506 pNewXObject->SetData((const uint8_t*)sStream, sStream.GetLength(), FALSE, |
507 FALSE); | 507 FALSE); |
508 } | 508 } |
509 pPageDict->RemoveAt("Annots"); | 509 pPageDict->RemoveAt("Annots"); |
510 | 510 |
511 ObjectArray.RemoveAll(); | 511 ObjectArray.RemoveAll(); |
512 RectArray.RemoveAll(); | 512 RectArray.RemoveAll(); |
513 | 513 |
514 return FLATTEN_SUCCESS; | 514 return FLATTEN_SUCCESS; |
515 } | 515 } |
OLD | NEW |