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 "../../../include/fpdfapi/fpdf_page.h" | 7 #include "../../../include/fpdfapi/fpdf_page.h" |
8 #include "../../../include/fpdfapi/fpdf_serial.h" | 8 #include "../../../include/fpdfapi/fpdf_serial.h" |
9 #include "../../../include/fpdfapi/fpdf_module.h" | 9 #include "../../../include/fpdfapi/fpdf_module.h" |
10 #include "../../../include/fxcodec/fx_codec.h" | 10 #include "../../../include/fxcodec/fx_codec.h" |
11 #include "../fpdf_page/pageint.h" | 11 #include "../fpdf_page/pageint.h" |
12 CFX_ByteTextBuf& operator << (CFX_ByteTextBuf& ar, CFX_AffineMatrix& matrix) | 12 CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& ar, CFX_AffineMatrix& matrix) { |
13 { | 13 ar << matrix.a << " " << matrix.b << " " << matrix.c << " " << matrix.d << " " |
14 ar << matrix.a << " " << matrix.b << " " << matrix.c << " " << matrix.d << "
" << matrix.e << " " << matrix.f; | 14 << matrix.e << " " << matrix.f; |
15 return ar; | 15 return ar; |
16 } | 16 } |
17 CPDF_PageContentGenerate::CPDF_PageContentGenerate(CPDF_Page* pPage) : m_pPage(p
Page) | 17 CPDF_PageContentGenerate::CPDF_PageContentGenerate(CPDF_Page* pPage) |
18 { | 18 : m_pPage(pPage) { |
19 m_pDocument = NULL; | 19 m_pDocument = NULL; |
20 if (m_pPage) { | 20 if (m_pPage) { |
21 m_pDocument = m_pPage->m_pDocument; | 21 m_pDocument = m_pPage->m_pDocument; |
| 22 } |
| 23 } |
| 24 CPDF_PageContentGenerate::~CPDF_PageContentGenerate() { |
| 25 for (int i = 0; i < m_pageObjects.GetSize(); ++i) { |
| 26 CPDF_PageObject* pPageObj = (CPDF_PageObject*)m_pageObjects[i]; |
| 27 if (pPageObj) { |
| 28 pPageObj->Release(); |
22 } | 29 } |
| 30 } |
23 } | 31 } |
24 CPDF_PageContentGenerate::~CPDF_PageContentGenerate() | 32 FX_BOOL CPDF_PageContentGenerate::InsertPageObject( |
25 { | 33 CPDF_PageObject* pPageObject) { |
26 for (int i = 0; i < m_pageObjects.GetSize(); ++i) { | 34 if (!pPageObject) { |
27 CPDF_PageObject* pPageObj = (CPDF_PageObject*)m_pageObjects[i]; | 35 return FALSE; |
28 if (pPageObj) { | 36 } |
29 pPageObj->Release(); | 37 return m_pageObjects.Add(pPageObject); |
30 } | 38 } |
| 39 void CPDF_PageContentGenerate::GenerateContent() { |
| 40 CFX_ByteTextBuf buf; |
| 41 CPDF_Dictionary* pPageDict = m_pPage->m_pFormDict; |
| 42 for (int i = 0; i < m_pageObjects.GetSize(); ++i) { |
| 43 CPDF_PageObject* pPageObj = (CPDF_PageObject*)m_pageObjects[i]; |
| 44 if (!pPageObj || pPageObj->m_Type != PDFPAGE_IMAGE) { |
| 45 continue; |
31 } | 46 } |
| 47 ProcessImage(buf, (CPDF_ImageObject*)pPageObj); |
| 48 } |
| 49 CPDF_Object* pContent = |
| 50 pPageDict ? pPageDict->GetElementValue("Contents") : NULL; |
| 51 if (pContent != NULL) { |
| 52 pPageDict->RemoveAt("Contents"); |
| 53 } |
| 54 CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL, 0, NULL); |
| 55 pStream->SetData(buf.GetBuffer(), buf.GetLength(), FALSE, FALSE); |
| 56 m_pDocument->AddIndirectObject(pStream); |
| 57 pPageDict->SetAtReference("Contents", m_pDocument, pStream->GetObjNum()); |
32 } | 58 } |
33 FX_BOOL CPDF_PageContentGenerate::InsertPageObject(CPDF_PageObject* pPageObject) | 59 CFX_ByteString CPDF_PageContentGenerate::RealizeResource( |
34 { | 60 CPDF_Object* pResourceObj, |
35 if (!pPageObject) { | 61 const FX_CHAR* szType) { |
36 return FALSE; | 62 if (m_pPage->m_pResources == NULL) { |
| 63 m_pPage->m_pResources = FX_NEW CPDF_Dictionary; |
| 64 int objnum = m_pDocument->AddIndirectObject(m_pPage->m_pResources); |
| 65 m_pPage->m_pFormDict->SetAtReference("Resources", m_pDocument, objnum); |
| 66 } |
| 67 CPDF_Dictionary* pResList = m_pPage->m_pResources->GetDict(szType); |
| 68 if (pResList == NULL) { |
| 69 pResList = FX_NEW CPDF_Dictionary; |
| 70 m_pPage->m_pResources->SetAt(szType, pResList); |
| 71 } |
| 72 m_pDocument->AddIndirectObject(pResourceObj); |
| 73 CFX_ByteString name; |
| 74 int idnum = 1; |
| 75 while (1) { |
| 76 name.Format("FX%c%d", szType[0], idnum); |
| 77 if (!pResList->KeyExist(name)) { |
| 78 break; |
37 } | 79 } |
38 return m_pageObjects.Add(pPageObject); | 80 idnum++; |
| 81 } |
| 82 pResList->AddReference(name, m_pDocument, pResourceObj->GetObjNum()); |
| 83 return name; |
39 } | 84 } |
40 void CPDF_PageContentGenerate::GenerateContent() | 85 void CPDF_PageContentGenerate::ProcessImage(CFX_ByteTextBuf& buf, |
41 { | 86 CPDF_ImageObject* pImageObj) { |
42 CFX_ByteTextBuf buf; | 87 if ((pImageObj->m_Matrix.a == 0 && pImageObj->m_Matrix.b == 0) || |
43 CPDF_Dictionary* pPageDict = m_pPage->m_pFormDict; | 88 (pImageObj->m_Matrix.c == 0 && pImageObj->m_Matrix.d == 0)) { |
44 for (int i = 0; i < m_pageObjects.GetSize(); ++i) { | 89 return; |
45 CPDF_PageObject* pPageObj = (CPDF_PageObject*)m_pageObjects[i]; | 90 } |
46 if (!pPageObj || pPageObj->m_Type != PDFPAGE_IMAGE) { | 91 buf << "q " << pImageObj->m_Matrix << " cm "; |
47 continue; | 92 if (!pImageObj->m_pImage->IsInline()) { |
48 } | 93 CPDF_Stream* pStream = pImageObj->m_pImage->GetStream(); |
49 ProcessImage(buf, (CPDF_ImageObject*)pPageObj); | 94 FX_DWORD dwSavedObjNum = pStream->GetObjNum(); |
| 95 CFX_ByteString name = RealizeResource(pStream, "XObject"); |
| 96 if (dwSavedObjNum == 0) { |
| 97 if (pImageObj->m_pImage) |
| 98 pImageObj->m_pImage->Release(); |
| 99 pImageObj->m_pImage = m_pDocument->GetPageData()->GetImage(pStream); |
50 } | 100 } |
51 CPDF_Object* pContent = pPageDict ? pPageDict->GetElementValue("Contents") :
NULL; | 101 buf << "/" << PDF_NameEncode(name) << " Do Q\n"; |
52 if (pContent != NULL) { | 102 } |
53 pPageDict->RemoveAt("Contents"); | 103 } |
| 104 void CPDF_PageContentGenerate::ProcessForm(CFX_ByteTextBuf& buf, |
| 105 FX_LPCBYTE data, |
| 106 FX_DWORD size, |
| 107 CFX_Matrix& matrix) { |
| 108 if (!data || !size) { |
| 109 return; |
| 110 } |
| 111 CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL, 0, NULL); |
| 112 CPDF_Dictionary* pFormDict = CPDF_Dictionary::Create(); |
| 113 pFormDict->SetAtName(FX_BSTR("Type"), FX_BSTR("XObject")); |
| 114 pFormDict->SetAtName(FX_BSTR("Subtype"), FX_BSTR("Form")); |
| 115 CFX_FloatRect bbox = m_pPage->GetPageBBox(); |
| 116 matrix.TransformRect(bbox); |
| 117 pFormDict->SetAtRect(FX_BSTR("BBox"), bbox); |
| 118 pStream->InitStream((FX_LPBYTE)data, size, pFormDict); |
| 119 buf << "q " << matrix << " cm "; |
| 120 CFX_ByteString name = RealizeResource(pStream, "XObject"); |
| 121 buf << "/" << PDF_NameEncode(name) << " Do Q\n"; |
| 122 } |
| 123 void CPDF_PageContentGenerate::TransformContent(CFX_Matrix& matrix) { |
| 124 CPDF_Dictionary* pDict = m_pPage->m_pFormDict; |
| 125 CPDF_Object* pContent = pDict ? pDict->GetElementValue("Contents") : NULL; |
| 126 if (!pContent) { |
| 127 return; |
| 128 } |
| 129 CFX_ByteTextBuf buf; |
| 130 int type = pContent->GetType(); |
| 131 if (type == PDFOBJ_ARRAY) { |
| 132 CPDF_Array* pArray = (CPDF_Array*)pContent; |
| 133 int iCount = pArray->GetCount(); |
| 134 CPDF_StreamAcc** pContentArray = |
| 135 (CPDF_StreamAcc**)FX_Alloc(CPDF_StreamAcc*, iCount); |
| 136 int size = 0; |
| 137 int i = 0; |
| 138 for (i = 0; i < iCount; ++i) { |
| 139 pContent = pArray->GetElement(i); |
| 140 if (!pContent || pContent->GetType() != PDFOBJ_STREAM) { |
| 141 continue; |
| 142 } |
| 143 CPDF_StreamAcc* pStream = FX_NEW CPDF_StreamAcc(); |
| 144 pStream->LoadAllData((CPDF_Stream*)pContent); |
| 145 pContentArray[i] = pStream; |
| 146 size += pContentArray[i]->GetSize() + 1; |
54 } | 147 } |
55 CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL, 0, NULL); | 148 int pos = 0; |
56 pStream->SetData(buf.GetBuffer(), buf.GetLength(), FALSE, FALSE); | 149 FX_LPBYTE pBuf = FX_Alloc(FX_BYTE, size); |
57 m_pDocument->AddIndirectObject(pStream); | 150 for (i = 0; i < iCount; ++i) { |
58 pPageDict->SetAtReference("Contents", m_pDocument, pStream->GetObjNum()); | 151 FXSYS_memcpy32( |
| 152 pBuf + pos, pContentArray[i]->GetData(), pContentArray[i]->GetSize()); |
| 153 pos += pContentArray[i]->GetSize() + 1; |
| 154 pBuf[pos - 1] = ' '; |
| 155 delete pContentArray[i]; |
| 156 } |
| 157 ProcessForm(buf, pBuf, size, matrix); |
| 158 FX_Free(pBuf); |
| 159 FX_Free(pContentArray); |
| 160 } else if (type == PDFOBJ_STREAM) { |
| 161 CPDF_StreamAcc contentStream; |
| 162 contentStream.LoadAllData((CPDF_Stream*)pContent); |
| 163 ProcessForm(buf, contentStream.GetData(), contentStream.GetSize(), matrix); |
| 164 } |
| 165 CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL, 0, NULL); |
| 166 pStream->SetData(buf.GetBuffer(), buf.GetLength(), FALSE, FALSE); |
| 167 m_pDocument->AddIndirectObject(pStream); |
| 168 m_pPage->m_pFormDict->SetAtReference( |
| 169 "Contents", m_pDocument, pStream->GetObjNum()); |
59 } | 170 } |
60 CFX_ByteString CPDF_PageContentGenerate::RealizeResource(CPDF_Object* pResourceO
bj, const FX_CHAR* szType) | |
61 { | |
62 if (m_pPage->m_pResources == NULL) { | |
63 m_pPage->m_pResources = FX_NEW CPDF_Dictionary; | |
64 int objnum = m_pDocument->AddIndirectObject(m_pPage->m_pResources); | |
65 m_pPage->m_pFormDict->SetAtReference("Resources", m_pDocument, objnum); | |
66 } | |
67 CPDF_Dictionary* pResList = m_pPage->m_pResources->GetDict(szType); | |
68 if (pResList == NULL) { | |
69 pResList = FX_NEW CPDF_Dictionary; | |
70 m_pPage->m_pResources->SetAt(szType, pResList); | |
71 } | |
72 m_pDocument->AddIndirectObject(pResourceObj); | |
73 CFX_ByteString name; | |
74 int idnum = 1; | |
75 while (1) { | |
76 name.Format("FX%c%d", szType[0], idnum); | |
77 if (!pResList->KeyExist(name)) { | |
78 break; | |
79 } | |
80 idnum ++; | |
81 } | |
82 pResList->AddReference(name, m_pDocument, pResourceObj->GetObjNum()); | |
83 return name; | |
84 } | |
85 void CPDF_PageContentGenerate::ProcessImage(CFX_ByteTextBuf& buf, CPDF_ImageObje
ct* pImageObj) | |
86 { | |
87 if ((pImageObj->m_Matrix.a == 0 && pImageObj->m_Matrix.b == 0) || | |
88 (pImageObj->m_Matrix.c == 0 && pImageObj->m_Matrix.d == 0)) { | |
89 return; | |
90 } | |
91 buf << "q " << pImageObj->m_Matrix << " cm "; | |
92 if (!pImageObj->m_pImage->IsInline()) { | |
93 CPDF_Stream* pStream = pImageObj->m_pImage->GetStream(); | |
94 FX_DWORD dwSavedObjNum = pStream->GetObjNum(); | |
95 CFX_ByteString name = RealizeResource(pStream, "XObject"); | |
96 if (dwSavedObjNum == 0) { | |
97 if (pImageObj->m_pImage) | |
98 pImageObj->m_pImage->Release(); | |
99 pImageObj->m_pImage = m_pDocument->GetPageData()->GetImage(pStream); | |
100 } | |
101 buf << "/" << PDF_NameEncode(name) << " Do Q\n"; | |
102 } | |
103 } | |
104 void CPDF_PageContentGenerate::ProcessForm(CFX_ByteTextBuf& buf, FX_LPCBYTE data
, FX_DWORD size, CFX_Matrix& matrix) | |
105 { | |
106 if (!data || !size) { | |
107 return; | |
108 } | |
109 CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL, 0, NULL); | |
110 CPDF_Dictionary* pFormDict = CPDF_Dictionary::Create(); | |
111 pFormDict->SetAtName(FX_BSTR("Type"), FX_BSTR("XObject")); | |
112 pFormDict->SetAtName(FX_BSTR("Subtype"), FX_BSTR("Form")); | |
113 CFX_FloatRect bbox = m_pPage->GetPageBBox(); | |
114 matrix.TransformRect(bbox); | |
115 pFormDict->SetAtRect(FX_BSTR("BBox"), bbox); | |
116 pStream->InitStream((FX_LPBYTE)data, size, pFormDict); | |
117 buf << "q " << matrix << " cm "; | |
118 CFX_ByteString name = RealizeResource(pStream, "XObject"); | |
119 buf << "/" << PDF_NameEncode(name) << " Do Q\n"; | |
120 } | |
121 void CPDF_PageContentGenerate::TransformContent(CFX_Matrix& matrix) | |
122 { | |
123 CPDF_Dictionary* pDict = m_pPage->m_pFormDict; | |
124 CPDF_Object* pContent = pDict ? pDict->GetElementValue("Contents") : NULL; | |
125 if (!pContent) { | |
126 return; | |
127 } | |
128 CFX_ByteTextBuf buf; | |
129 int type = pContent->GetType(); | |
130 if (type == PDFOBJ_ARRAY) { | |
131 CPDF_Array* pArray = (CPDF_Array*)pContent; | |
132 int iCount = pArray->GetCount(); | |
133 CPDF_StreamAcc** pContentArray = (CPDF_StreamAcc**)FX_Alloc(CPDF_StreamA
cc*, iCount); | |
134 int size = 0; | |
135 int i = 0; | |
136 for (i = 0; i < iCount; ++i) { | |
137 pContent = pArray->GetElement(i); | |
138 if (!pContent || pContent->GetType() != PDFOBJ_STREAM) { | |
139 continue; | |
140 } | |
141 CPDF_StreamAcc* pStream = FX_NEW CPDF_StreamAcc(); | |
142 pStream->LoadAllData((CPDF_Stream*)pContent); | |
143 pContentArray[i] = pStream; | |
144 size += pContentArray[i]->GetSize() + 1; | |
145 } | |
146 int pos = 0; | |
147 FX_LPBYTE pBuf = FX_Alloc(FX_BYTE, size); | |
148 for (i = 0; i < iCount; ++i) { | |
149 FXSYS_memcpy32(pBuf + pos, pContentArray[i]->GetData(), pContentArra
y[i]->GetSize()); | |
150 pos += pContentArray[i]->GetSize() + 1; | |
151 pBuf[pos - 1] = ' '; | |
152 delete pContentArray[i]; | |
153 } | |
154 ProcessForm(buf, pBuf, size, matrix); | |
155 FX_Free(pBuf); | |
156 FX_Free(pContentArray); | |
157 } else if (type == PDFOBJ_STREAM) { | |
158 CPDF_StreamAcc contentStream; | |
159 contentStream.LoadAllData((CPDF_Stream*)pContent); | |
160 ProcessForm(buf, contentStream.GetData(), contentStream.GetSize(), matri
x); | |
161 } | |
162 CPDF_Stream* pStream = FX_NEW CPDF_Stream(NULL, 0, NULL); | |
163 pStream->SetData(buf.GetBuffer(), buf.GetLength(), FALSE, FALSE); | |
164 m_pDocument->AddIndirectObject(pStream); | |
165 m_pPage->m_pFormDict->SetAtReference("Contents", m_pDocument, pStream->GetOb
jNum()); | |
166 } | |
OLD | NEW |