| 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 |