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