Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: fpdfsdk/fpdf_flatten.cpp

Issue 2403143002: Add method to convert an indirect object in a dictionary (Closed)
Patch Set: Const ref Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/fpdfapi/parser/cpdf_object_unittest.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "core/fpdfapi/page/cpdf_page.h" 11 #include "core/fpdfapi/page/cpdf_page.h"
12 #include "core/fpdfapi/page/cpdf_pageobject.h" 12 #include "core/fpdfapi/page/cpdf_pageobject.h"
13 #include "core/fpdfapi/parser/cpdf_array.h" 13 #include "core/fpdfapi/parser/cpdf_array.h"
14 #include "core/fpdfapi/parser/cpdf_document.h" 14 #include "core/fpdfapi/parser/cpdf_document.h"
15 #include "core/fpdfapi/parser/cpdf_number.h" 15 #include "core/fpdfapi/parser/cpdf_number.h"
16 #include "core/fpdfapi/parser/cpdf_stream.h" 16 #include "core/fpdfapi/parser/cpdf_stream.h"
17 #include "core/fpdfapi/parser/cpdf_stream_acc.h" 17 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
18 #include "core/fpdfdoc/cpdf_annot.h" 18 #include "core/fpdfdoc/cpdf_annot.h"
19 #include "fpdfsdk/fsdk_define.h" 19 #include "fpdfsdk/fsdk_define.h"
20 20
21 typedef CFX_ArrayTemplate<CPDF_Dictionary*> CPDF_ObjectArray; 21 typedef CFX_ArrayTemplate<CPDF_Dictionary*> CPDF_ObjectArray;
22 typedef CFX_ArrayTemplate<CFX_FloatRect> CPDF_RectArray; 22 typedef CFX_ArrayTemplate<CFX_FloatRect> CPDF_RectArray;
23 23
24 enum FPDF_TYPE { MAX, MIN }; 24 enum FPDF_TYPE { MAX, MIN };
25 enum FPDF_VALUE { TOP, LEFT, RIGHT, BOTTOM }; 25 enum FPDF_VALUE { TOP, LEFT, RIGHT, BOTTOM };
26 26
27 namespace {
28
27 FX_BOOL IsValiableRect(CFX_FloatRect rect, CFX_FloatRect rcPage) { 29 FX_BOOL IsValiableRect(CFX_FloatRect rect, CFX_FloatRect rcPage) {
28 if (rect.left - rect.right > 0.000001f || rect.bottom - rect.top > 0.000001f) 30 if (rect.left - rect.right > 0.000001f || rect.bottom - rect.top > 0.000001f)
29 return FALSE; 31 return FALSE;
30 32
31 if (rect.left == 0.0f && rect.top == 0.0f && rect.right == 0.0f && 33 if (rect.left == 0.0f && rect.top == 0.0f && rect.right == 0.0f &&
32 rect.bottom == 0.0f) 34 rect.bottom == 0.0f)
33 return FALSE; 35 return FALSE;
34 36
35 if (!rcPage.IsEmpty()) { 37 if (!rcPage.IsEmpty()) {
36 if (rect.left - rcPage.left < -10.000001f || 38 if (rect.left - rcPage.left < -10.000001f ||
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 CFX_FloatRect rcRet; 177 CFX_FloatRect rcRet;
176 178
177 rcRet.left = GetMinMaxValue(*pRectArray, MIN, LEFT); 179 rcRet.left = GetMinMaxValue(*pRectArray, MIN, LEFT);
178 rcRet.top = GetMinMaxValue(*pRectArray, MAX, TOP); 180 rcRet.top = GetMinMaxValue(*pRectArray, MAX, TOP);
179 rcRet.right = GetMinMaxValue(*pRectArray, MAX, RIGHT); 181 rcRet.right = GetMinMaxValue(*pRectArray, MAX, RIGHT);
180 rcRet.bottom = GetMinMaxValue(*pRectArray, MIN, BOTTOM); 182 rcRet.bottom = GetMinMaxValue(*pRectArray, MIN, BOTTOM);
181 183
182 return rcRet; 184 return rcRet;
183 } 185 }
184 186
185 void SetPageContents(CFX_ByteString key, 187 uint32_t NewIndirectContentsStream(const CFX_ByteString& key,
188 CPDF_Document* pDocument) {
189 CPDF_Stream* pNewContents = new CPDF_Stream(
190 nullptr, 0, new CPDF_Dictionary(pDocument->GetByteStringPool()));
191 CFX_ByteString sStream;
192 sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str());
193 pNewContents->SetData(sStream.raw_str(), sStream.GetLength());
194 return pDocument->AddIndirectObject(pNewContents);
195 }
196
197 void SetPageContents(const CFX_ByteString& key,
186 CPDF_Dictionary* pPage, 198 CPDF_Dictionary* pPage,
187 CPDF_Document* pDocument) { 199 CPDF_Document* pDocument) {
188 CPDF_Object* pContentsObj = pPage->GetStreamFor("Contents"); 200 CPDF_Array* pContentsArray = nullptr;
189 if (!pContentsObj) { 201 CPDF_Stream* pContentsStream = pPage->GetStreamFor("Contents");
190 pContentsObj = pPage->GetArrayFor("Contents"); 202 if (!pContentsStream) {
203 pContentsArray = pPage->GetArrayFor("Contents");
204 if (!pContentsArray) {
205 if (!key.IsEmpty()) {
206 pPage->SetReferenceFor("Contents", pDocument,
207 NewIndirectContentsStream(key, pDocument));
208 }
209 return;
210 }
191 } 211 }
192 212 pPage->ConvertToIndirectObjectFor("Contents", pDocument);
193 if (!pContentsObj) { 213 if (!pContentsArray) {
194 // Create a new contents dictionary 214 pContentsArray = new CPDF_Array;
195 if (!key.IsEmpty()) { 215 CPDF_StreamAcc acc;
196 CPDF_Stream* pNewContents = new CPDF_Stream( 216 acc.LoadAllData(pContentsStream);
197 nullptr, 0, new CPDF_Dictionary(pDocument->GetByteStringPool())); 217 CFX_ByteString sStream = "q\n";
198 CFX_ByteString sStream; 218 CFX_ByteString sBody =
199 sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str()); 219 CFX_ByteString((const FX_CHAR*)acc.GetData(), acc.GetSize());
200 pNewContents->SetData(sStream.raw_str(), sStream.GetLength()); 220 sStream = sStream + sBody + "\nQ";
201 pPage->SetReferenceFor("Contents", pDocument, 221 pContentsStream->SetData(sStream.raw_str(), sStream.GetLength());
202 pDocument->AddIndirectObject(pNewContents)); 222 pContentsArray->AddReference(pDocument, pContentsStream->GetObjNum());
203 } 223 pPage->SetReferenceFor("Contents", pDocument,
204 return; 224 pDocument->AddIndirectObject(pContentsArray));
205 } 225 }
206
207 CPDF_Array* pContentsArray = nullptr;
208 switch (pContentsObj->GetType()) {
209 case CPDF_Object::STREAM: {
210 pContentsArray = new CPDF_Array;
211 CPDF_Stream* pContents = pContentsObj->AsStream();
212 uint32_t dwObjNum = pDocument->AddIndirectObject(pContents);
213 CPDF_StreamAcc acc;
214 acc.LoadAllData(pContents);
215 CFX_ByteString sStream = "q\n";
216 CFX_ByteString sBody =
217 CFX_ByteString((const FX_CHAR*)acc.GetData(), acc.GetSize());
218 sStream = sStream + sBody + "\nQ";
219 pContents->SetData(sStream.raw_str(), sStream.GetLength());
220 pContentsArray->AddReference(pDocument, dwObjNum);
221 break;
222 }
223
224 case CPDF_Object::ARRAY: {
225 pContentsArray = pContentsObj->AsArray();
226 break;
227 }
228 default:
229 break;
230 }
231
232 if (!pContentsArray)
233 return;
234
235 pPage->SetReferenceFor("Contents", pDocument,
236 pDocument->AddIndirectObject(pContentsArray));
237
238 if (!key.IsEmpty()) { 226 if (!key.IsEmpty()) {
239 CPDF_Stream* pNewContents = new CPDF_Stream(
240 nullptr, 0, new CPDF_Dictionary(pDocument->GetByteStringPool()));
241 CFX_ByteString sStream;
242 sStream.Format("q 1 0 0 1 0 0 cm /%s Do Q", key.c_str());
243 pNewContents->SetData(sStream.raw_str(), sStream.GetLength());
244 pContentsArray->AddReference(pDocument, 227 pContentsArray->AddReference(pDocument,
245 pDocument->AddIndirectObject(pNewContents)); 228 NewIndirectContentsStream(key, pDocument));
246 } 229 }
247 } 230 }
248 231
249 CFX_Matrix GetMatrix(CFX_FloatRect rcAnnot, 232 CFX_Matrix GetMatrix(CFX_FloatRect rcAnnot,
250 CFX_FloatRect rcStream, 233 CFX_FloatRect rcStream,
251 const CFX_Matrix& matrix) { 234 const CFX_Matrix& matrix) {
252 if (rcStream.IsEmpty()) 235 if (rcStream.IsEmpty())
253 return CFX_Matrix(); 236 return CFX_Matrix();
254 237
255 matrix.TransformRect(rcStream); 238 matrix.TransformRect(rcStream);
256 rcStream.Normalize(); 239 rcStream.Normalize();
257 240
258 FX_FLOAT a = rcAnnot.Width() / rcStream.Width(); 241 FX_FLOAT a = rcAnnot.Width() / rcStream.Width();
259 FX_FLOAT d = rcAnnot.Height() / rcStream.Height(); 242 FX_FLOAT d = rcAnnot.Height() / rcStream.Height();
260 243
261 FX_FLOAT e = rcAnnot.left - rcStream.left * a; 244 FX_FLOAT e = rcAnnot.left - rcStream.left * a;
262 FX_FLOAT f = rcAnnot.bottom - rcStream.bottom * d; 245 FX_FLOAT f = rcAnnot.bottom - rcStream.bottom * d;
263 return CFX_Matrix(a, 0, 0, d, e, f); 246 return CFX_Matrix(a, 0, 0, d, e, f);
264 } 247 }
265 248
266 void GetOffset(FX_FLOAT& fa, 249 } // namespace
267 FX_FLOAT& fd,
268 FX_FLOAT& fe,
269 FX_FLOAT& ff,
270 CFX_FloatRect rcAnnot,
271 CFX_FloatRect rcStream,
272 const CFX_Matrix& matrix) {
273 FX_FLOAT fStreamWidth = 0.0f;
274 FX_FLOAT fStreamHeight = 0.0f;
275
276 if (matrix.a != 0 && matrix.d != 0) {
277 fStreamWidth = rcStream.right - rcStream.left;
278 fStreamHeight = rcStream.top - rcStream.bottom;
279 } else {
280 fStreamWidth = rcStream.top - rcStream.bottom;
281 fStreamHeight = rcStream.right - rcStream.left;
282 }
283
284 FX_FLOAT x1 =
285 matrix.a * rcStream.left + matrix.c * rcStream.bottom + matrix.e;
286 FX_FLOAT y1 =
287 matrix.b * rcStream.left + matrix.d * rcStream.bottom + matrix.f;
288 FX_FLOAT x2 = matrix.a * rcStream.left + matrix.c * rcStream.top + matrix.e;
289 FX_FLOAT y2 = matrix.b * rcStream.left + matrix.d * rcStream.top + matrix.f;
290 FX_FLOAT x3 =
291 matrix.a * rcStream.right + matrix.c * rcStream.bottom + matrix.e;
292 FX_FLOAT y3 =
293 matrix.b * rcStream.right + matrix.d * rcStream.bottom + matrix.f;
294 FX_FLOAT x4 = matrix.a * rcStream.right + matrix.c * rcStream.top + matrix.e;
295 FX_FLOAT y4 = matrix.b * rcStream.right + matrix.d * rcStream.top + matrix.f;
296
297 FX_FLOAT left = std::min(std::min(x1, x2), std::min(x3, x4));
298 FX_FLOAT bottom = std::min(std::min(y1, y2), std::min(y3, y4));
299
300 fa = (rcAnnot.right - rcAnnot.left) / fStreamWidth;
301 fd = (rcAnnot.top - rcAnnot.bottom) / fStreamHeight;
302 fe = rcAnnot.left - left * fa;
303 ff = rcAnnot.bottom - bottom * fd;
304 }
305 250
306 DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) { 251 DLLEXPORT int STDCALL FPDFPage_Flatten(FPDF_PAGE page, int nFlag) {
307 CPDF_Page* pPage = CPDFPageFromFPDFPage(page); 252 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
308 if (!page) { 253 if (!page) {
309 return FLATTEN_FAIL; 254 return FLATTEN_FAIL;
310 } 255 }
311 256
312 CPDF_Document* pDocument = pPage->m_pDocument; 257 CPDF_Document* pDocument = pPage->m_pDocument;
313 CPDF_Dictionary* pPageDict = pPage->m_pFormDict; 258 CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
314 259
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 sStream += sTemp; 451 sStream += sTemp;
507 pNewXObject->SetData(sStream.raw_str(), sStream.GetLength()); 452 pNewXObject->SetData(sStream.raw_str(), sStream.GetLength());
508 } 453 }
509 pPageDict->RemoveFor("Annots"); 454 pPageDict->RemoveFor("Annots");
510 455
511 ObjectArray.RemoveAll(); 456 ObjectArray.RemoveAll();
512 RectArray.RemoveAll(); 457 RectArray.RemoveAll();
513 458
514 return FLATTEN_SUCCESS; 459 return FLATTEN_SUCCESS;
515 } 460 }
OLDNEW
« no previous file with comments | « core/fpdfapi/parser/cpdf_object_unittest.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698