| 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_module.h" | 8 #include "../../../include/fpdfapi/fpdf_module.h" |
| 9 #include "pageint.h" | 9 #include "pageint.h" |
| 10 CPDF_PageObject* CPDF_PageObject::Create(int type) | 10 CPDF_PageObject* CPDF_PageObject::Create(int type) { |
| 11 { | 11 switch (type) { |
| 12 switch (type) { | 12 case PDFPAGE_TEXT: |
| 13 case PDFPAGE_TEXT: | 13 return new CPDF_TextObject; |
| 14 return new CPDF_TextObject; | 14 case PDFPAGE_IMAGE: |
| 15 case PDFPAGE_IMAGE: | 15 return new CPDF_ImageObject; |
| 16 return new CPDF_ImageObject; | 16 case PDFPAGE_PATH: |
| 17 case PDFPAGE_PATH: | 17 return new CPDF_PathObject; |
| 18 return new CPDF_PathObject; | 18 case PDFPAGE_SHADING: |
| 19 case PDFPAGE_SHADING: | 19 return new CPDF_ShadingObject; |
| 20 return new CPDF_ShadingObject; | 20 case PDFPAGE_FORM: |
| 21 case PDFPAGE_FORM: | 21 return new CPDF_FormObject; |
| 22 return new CPDF_FormObject; | 22 } |
| 23 } | 23 return NULL; |
| 24 return NULL; | |
| 25 } | 24 } |
| 26 CPDF_PageObject::~CPDF_PageObject() | 25 CPDF_PageObject::~CPDF_PageObject() {} |
| 27 { | 26 CPDF_PageObject* CPDF_PageObject::Clone() const { |
| 27 CPDF_PageObject* pObj = Create(m_Type); |
| 28 pObj->Copy(this); |
| 29 return pObj; |
| 28 } | 30 } |
| 29 CPDF_PageObject* CPDF_PageObject::Clone() const | 31 void CPDF_PageObject::Copy(const CPDF_PageObject* pSrc) { |
| 30 { | 32 if (m_Type != pSrc->m_Type) { |
| 31 CPDF_PageObject* pObj = Create(m_Type); | 33 return; |
| 32 pObj->Copy(this); | 34 } |
| 33 return pObj; | 35 CopyData(pSrc); |
| 36 CopyStates(*pSrc); |
| 37 m_Left = pSrc->m_Left; |
| 38 m_Right = pSrc->m_Right; |
| 39 m_Top = pSrc->m_Top; |
| 40 m_Bottom = pSrc->m_Bottom; |
| 34 } | 41 } |
| 35 void CPDF_PageObject::Copy(const CPDF_PageObject* pSrc) | 42 void CPDF_PageObject::AppendClipPath(CPDF_Path path, |
| 36 { | 43 int type, |
| 37 if (m_Type != pSrc->m_Type) { | 44 FX_BOOL bAutoMerge) { |
| 38 return; | 45 m_ClipPath.AppendPath(path, type, bAutoMerge); |
| 39 } | |
| 40 CopyData(pSrc); | |
| 41 CopyStates(*pSrc); | |
| 42 m_Left = pSrc->m_Left; | |
| 43 m_Right = pSrc->m_Right; | |
| 44 m_Top = pSrc->m_Top; | |
| 45 m_Bottom = pSrc->m_Bottom; | |
| 46 } | 46 } |
| 47 void CPDF_PageObject::AppendClipPath(CPDF_Path path, int type, FX_BOOL bAutoMerg
e) | 47 void CPDF_PageObject::CopyClipPath(CPDF_PageObject* pObj) { |
| 48 { | 48 m_ClipPath = pObj->m_ClipPath; |
| 49 m_ClipPath.AppendPath(path, type, bAutoMerge); | |
| 50 } | 49 } |
| 51 void CPDF_PageObject::CopyClipPath(CPDF_PageObject* pObj) | 50 void CPDF_PageObject::RemoveClipPath() { |
| 52 { | 51 m_ClipPath.SetNull(); |
| 53 m_ClipPath = pObj->m_ClipPath; | |
| 54 } | 52 } |
| 55 void CPDF_PageObject::RemoveClipPath() | 53 void CPDF_PageObject::RecalcBBox() { |
| 56 { | 54 switch (m_Type) { |
| 57 m_ClipPath.SetNull(); | 55 case PDFPAGE_TEXT: |
| 56 ((CPDF_TextObject*)this)->RecalcPositionData(); |
| 57 break; |
| 58 case PDFPAGE_PATH: |
| 59 ((CPDF_PathObject*)this)->CalcBoundingBox(); |
| 60 break; |
| 61 case PDFPAGE_SHADING: |
| 62 ((CPDF_ShadingObject*)this)->CalcBoundingBox(); |
| 63 break; |
| 64 } |
| 58 } | 65 } |
| 59 void CPDF_PageObject::RecalcBBox() | 66 void CPDF_PageObject::TransformClipPath(CFX_AffineMatrix& matrix) { |
| 60 { | 67 if (m_ClipPath.IsNull()) { |
| 61 switch (m_Type) { | 68 return; |
| 62 case PDFPAGE_TEXT: | 69 } |
| 63 ((CPDF_TextObject*)this)->RecalcPositionData(); | 70 m_ClipPath.GetModify(); |
| 64 break; | 71 m_ClipPath.Transform(matrix); |
| 65 case PDFPAGE_PATH: | |
| 66 ((CPDF_PathObject*)this)->CalcBoundingBox(); | |
| 67 break; | |
| 68 case PDFPAGE_SHADING: | |
| 69 ((CPDF_ShadingObject*)this)->CalcBoundingBox(); | |
| 70 break; | |
| 71 } | |
| 72 } | 72 } |
| 73 void CPDF_PageObject::TransformClipPath(CFX_AffineMatrix& matrix) | 73 void CPDF_PageObject::TransformGeneralState(CFX_AffineMatrix& matrix) { |
| 74 { | 74 if (m_GeneralState.IsNull()) { |
| 75 if (m_ClipPath.IsNull()) { | 75 return; |
| 76 return; | 76 } |
| 77 } | 77 CPDF_GeneralStateData* pGS = m_GeneralState.GetModify(); |
| 78 m_ClipPath.GetModify(); | 78 pGS->m_Matrix.Concat(matrix); |
| 79 m_ClipPath.Transform(matrix); | |
| 80 } | 79 } |
| 81 void CPDF_PageObject::TransformGeneralState(CFX_AffineMatrix& matrix) | 80 FX_RECT CPDF_PageObject::GetBBox(const CFX_AffineMatrix* pMatrix) const { |
| 82 { | 81 CFX_FloatRect rect(m_Left, m_Bottom, m_Right, m_Top); |
| 83 if(m_GeneralState.IsNull()) { | 82 if (pMatrix) { |
| 84 return; | 83 pMatrix->TransformRect(rect); |
| 85 } | 84 } |
| 86 CPDF_GeneralStateData* pGS = m_GeneralState.GetModify(); | 85 return rect.GetOutterRect(); |
| 87 pGS->m_Matrix.Concat(matrix); | |
| 88 } | |
| 89 FX_RECT CPDF_PageObject::GetBBox(const CFX_AffineMatrix* pMatrix) const | |
| 90 { | |
| 91 CFX_FloatRect rect(m_Left, m_Bottom, m_Right, m_Top); | |
| 92 if (pMatrix) { | |
| 93 pMatrix->TransformRect(rect); | |
| 94 } | |
| 95 return rect.GetOutterRect(); | |
| 96 } | 86 } |
| 97 | 87 |
| 98 CPDF_TextObject::CPDF_TextObject() | 88 CPDF_TextObject::CPDF_TextObject() |
| 99 : m_PosX(0), | 89 : m_PosX(0), |
| 100 m_PosY(0), | 90 m_PosY(0), |
| 101 m_nChars(0), | 91 m_nChars(0), |
| 102 m_pCharCodes(nullptr), | 92 m_pCharCodes(nullptr), |
| 103 m_pCharPos(nullptr) | 93 m_pCharPos(nullptr) { |
| 104 { | 94 m_Type = PDFPAGE_TEXT; |
| 105 m_Type = PDFPAGE_TEXT; | 95 } |
| 106 } | 96 |
| 107 | 97 CPDF_TextObject::~CPDF_TextObject() { |
| 108 CPDF_TextObject::~CPDF_TextObject() | 98 if (m_nChars > 1 && m_pCharCodes) { |
| 109 { | 99 FX_Free(m_pCharCodes); |
| 110 if (m_nChars > 1 && m_pCharCodes) { | 100 } |
| 111 FX_Free(m_pCharCodes); | 101 if (m_pCharPos) { |
| 112 } | 102 FX_Free(m_pCharPos); |
| 113 if (m_pCharPos) { | 103 } |
| 114 FX_Free(m_pCharPos); | 104 } |
| 115 } | 105 |
| 116 } | 106 void CPDF_TextObject::GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const { |
| 117 | 107 pInfo->m_CharCode = |
| 118 void CPDF_TextObject::GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const | 108 m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[index]; |
| 119 { | 109 pInfo->m_OriginX = index ? m_pCharPos[index - 1] : 0; |
| 120 pInfo->m_CharCode = | 110 pInfo->m_OriginY = 0; |
| 121 m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[index]; | 111 if (pInfo->m_CharCode == -1) { |
| 122 pInfo->m_OriginX = index ? m_pCharPos[index - 1] : 0; | 112 return; |
| 123 pInfo->m_OriginY = 0; | 113 } |
| 124 if (pInfo->m_CharCode == -1) { | 114 CPDF_Font* pFont = m_TextState.GetFont(); |
| 125 return; | 115 if (pFont->GetFontType() != PDFFONT_CIDFONT) { |
| 126 } | 116 return; |
| 127 CPDF_Font* pFont = m_TextState.GetFont(); | 117 } |
| 128 if (pFont->GetFontType() != PDFFONT_CIDFONT) { | 118 if (!((CPDF_CIDFont*)pFont)->IsVertWriting()) { |
| 129 return; | 119 return; |
| 130 } | 120 } |
| 131 if (!((CPDF_CIDFont*)pFont)->IsVertWriting()) { | 121 FX_WORD CID = ((CPDF_CIDFont*)pFont)->CIDFromCharCode(pInfo->m_CharCode); |
| 132 return; | 122 pInfo->m_OriginY = pInfo->m_OriginX; |
| 133 } | 123 pInfo->m_OriginX = 0; |
| 134 FX_WORD CID = ((CPDF_CIDFont*)pFont)->CIDFromCharCode(pInfo->m_CharCode); | 124 short vx, vy; |
| 135 pInfo->m_OriginY = pInfo->m_OriginX; | 125 ((CPDF_CIDFont*)pFont)->GetVertOrigin(CID, vx, vy); |
| 136 pInfo->m_OriginX = 0; | 126 FX_FLOAT fontsize = m_TextState.GetFontSize(); |
| 137 short vx, vy; | 127 pInfo->m_OriginX -= fontsize * vx / 1000; |
| 138 ((CPDF_CIDFont*)pFont)->GetVertOrigin(CID, vx, vy); | 128 pInfo->m_OriginY -= fontsize * vy / 1000; |
| 139 FX_FLOAT fontsize = m_TextState.GetFontSize(); | 129 } |
| 140 pInfo->m_OriginX -= fontsize * vx / 1000; | 130 |
| 141 pInfo->m_OriginY -= fontsize * vy / 1000; | 131 int CPDF_TextObject::CountChars() const { |
| 142 } | 132 if (m_nChars == 1) { |
| 143 | 133 return 1; |
| 144 int CPDF_TextObject::CountChars() const | 134 } |
| 145 { | 135 int count = 0; |
| 146 if (m_nChars == 1) { | 136 for (int i = 0; i < m_nChars; ++i) |
| 147 return 1; | 137 if (m_pCharCodes[i] != (FX_DWORD)-1) { |
| 148 } | 138 ++count; |
| 149 int count = 0; | 139 } |
| 150 for (int i = 0; i < m_nChars; ++i) | 140 return count; |
| 151 if (m_pCharCodes[i] != (FX_DWORD) - 1) { | |
| 152 ++count; | |
| 153 } | |
| 154 return count; | |
| 155 } | 141 } |
| 156 | 142 |
| 157 void CPDF_TextObject::GetCharInfo(int index, | 143 void CPDF_TextObject::GetCharInfo(int index, |
| 158 FX_DWORD& charcode, | 144 FX_DWORD& charcode, |
| 159 FX_FLOAT& kerning) const | 145 FX_FLOAT& kerning) const { |
| 160 { | 146 if (m_nChars == 1) { |
| 161 if (m_nChars == 1) { | 147 charcode = (FX_DWORD)(uintptr_t)m_pCharCodes; |
| 162 charcode = (FX_DWORD)(uintptr_t)m_pCharCodes; | 148 kerning = 0; |
| 163 kerning = 0; | 149 return; |
| 150 } |
| 151 int count = 0; |
| 152 for (int i = 0; i < m_nChars; ++i) { |
| 153 if (m_pCharCodes[i] != (FX_DWORD)-1) { |
| 154 if (count == index) { |
| 155 charcode = m_pCharCodes[i]; |
| 156 if (i == m_nChars - 1 || m_pCharCodes[i + 1] != (FX_DWORD)-1) { |
| 157 kerning = 0; |
| 158 } else { |
| 159 kerning = m_pCharPos[i]; |
| 160 } |
| 164 return; | 161 return; |
| 165 } | 162 } |
| 166 int count = 0; | 163 ++count; |
| 164 } |
| 165 } |
| 166 } |
| 167 |
| 168 void CPDF_TextObject::GetCharInfo(int index, CPDF_TextObjectItem* pInfo) const { |
| 169 if (m_nChars == 1) { |
| 170 GetItemInfo(0, pInfo); |
| 171 return; |
| 172 } |
| 173 int count = 0; |
| 174 for (int i = 0; i < m_nChars; ++i) { |
| 175 FX_DWORD charcode = m_pCharCodes[i]; |
| 176 if (charcode == (FX_DWORD)-1) { |
| 177 continue; |
| 178 } |
| 179 if (count == index) { |
| 180 GetItemInfo(i, pInfo); |
| 181 break; |
| 182 } |
| 183 ++count; |
| 184 } |
| 185 } |
| 186 |
| 187 void CPDF_TextObject::CopyData(const CPDF_PageObject* pSrc) { |
| 188 const CPDF_TextObject* pSrcObj = (const CPDF_TextObject*)pSrc; |
| 189 if (m_nChars > 1 && m_pCharCodes) { |
| 190 FX_Free(m_pCharCodes); |
| 191 m_pCharCodes = nullptr; |
| 192 } |
| 193 if (m_pCharPos) { |
| 194 FX_Free(m_pCharPos); |
| 195 m_pCharPos = nullptr; |
| 196 } |
| 197 m_nChars = pSrcObj->m_nChars; |
| 198 if (m_nChars > 1) { |
| 199 m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars); |
| 200 m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1); |
| 167 for (int i = 0; i < m_nChars; ++i) { | 201 for (int i = 0; i < m_nChars; ++i) { |
| 168 if (m_pCharCodes[i] != (FX_DWORD) - 1) { | 202 m_pCharCodes[i] = pSrcObj->m_pCharCodes[i]; |
| 169 if (count == index) { | 203 } |
| 170 charcode = m_pCharCodes[i]; | 204 for (int i = 0; i < m_nChars - 1; ++i) { |
| 171 if (i == m_nChars - 1 || | 205 m_pCharPos[i] = pSrcObj->m_pCharPos[i]; |
| 172 m_pCharCodes[i + 1] != (FX_DWORD) - 1) { | 206 } |
| 173 kerning = 0; | 207 } else { |
| 174 } else { | 208 m_pCharCodes = pSrcObj->m_pCharCodes; |
| 175 kerning = m_pCharPos[i]; | 209 } |
| 176 } | 210 m_PosX = pSrcObj->m_PosX; |
| 177 return; | 211 m_PosY = pSrcObj->m_PosY; |
| 178 } | 212 } |
| 179 ++count; | 213 |
| 180 } | 214 void CPDF_TextObject::GetTextMatrix(CFX_AffineMatrix* pMatrix) const { |
| 181 } | 215 FX_FLOAT* pTextMatrix = m_TextState.GetMatrix(); |
| 182 } | 216 pMatrix->Set(pTextMatrix[0], pTextMatrix[2], pTextMatrix[1], pTextMatrix[3], |
| 183 | 217 m_PosX, m_PosY); |
| 184 void CPDF_TextObject::GetCharInfo(int index, CPDF_TextObjectItem* pInfo) const | |
| 185 { | |
| 186 if (m_nChars == 1) { | |
| 187 GetItemInfo(0, pInfo); | |
| 188 return; | |
| 189 } | |
| 190 int count = 0; | |
| 191 for (int i = 0; i < m_nChars; ++i) { | |
| 192 FX_DWORD charcode = m_pCharCodes[i]; | |
| 193 if (charcode == (FX_DWORD) - 1) { | |
| 194 continue; | |
| 195 } | |
| 196 if (count == index) { | |
| 197 GetItemInfo(i, pInfo); | |
| 198 break; | |
| 199 } | |
| 200 ++count; | |
| 201 } | |
| 202 } | |
| 203 | |
| 204 void CPDF_TextObject::CopyData(const CPDF_PageObject* pSrc) | |
| 205 { | |
| 206 const CPDF_TextObject* pSrcObj = (const CPDF_TextObject*)pSrc; | |
| 207 if (m_nChars > 1 && m_pCharCodes) { | |
| 208 FX_Free(m_pCharCodes); | |
| 209 m_pCharCodes = nullptr; | |
| 210 } | |
| 211 if (m_pCharPos) { | |
| 212 FX_Free(m_pCharPos); | |
| 213 m_pCharPos = nullptr; | |
| 214 } | |
| 215 m_nChars = pSrcObj->m_nChars; | |
| 216 if (m_nChars > 1) { | |
| 217 m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars); | |
| 218 m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1); | |
| 219 for (int i = 0; i < m_nChars; ++i) { | |
| 220 m_pCharCodes[i] = pSrcObj->m_pCharCodes[i]; | |
| 221 } | |
| 222 for (int i = 0; i < m_nChars - 1; ++i) { | |
| 223 m_pCharPos[i] = pSrcObj->m_pCharPos[i]; | |
| 224 } | |
| 225 } else { | |
| 226 m_pCharCodes = pSrcObj->m_pCharCodes; | |
| 227 } | |
| 228 m_PosX = pSrcObj->m_PosX; | |
| 229 m_PosY = pSrcObj->m_PosY; | |
| 230 } | |
| 231 | |
| 232 void CPDF_TextObject::GetTextMatrix(CFX_AffineMatrix* pMatrix) const | |
| 233 { | |
| 234 FX_FLOAT* pTextMatrix = m_TextState.GetMatrix(); | |
| 235 pMatrix->Set(pTextMatrix[0], | |
| 236 pTextMatrix[2], | |
| 237 pTextMatrix[1], | |
| 238 pTextMatrix[3], | |
| 239 m_PosX, | |
| 240 m_PosY); | |
| 241 } | 218 } |
| 242 | 219 |
| 243 void CPDF_TextObject::SetSegments(const CFX_ByteString* pStrs, | 220 void CPDF_TextObject::SetSegments(const CFX_ByteString* pStrs, |
| 244 FX_FLOAT* pKerning, | 221 FX_FLOAT* pKerning, |
| 245 int nsegs) | 222 int nsegs) { |
| 246 { | 223 if (m_nChars > 1 && m_pCharCodes) { |
| 247 if (m_nChars > 1 && m_pCharCodes) { | 224 FX_Free(m_pCharCodes); |
| 248 FX_Free(m_pCharCodes); | 225 m_pCharCodes = nullptr; |
| 249 m_pCharCodes = nullptr; | 226 } |
| 250 } | 227 if (m_pCharPos) { |
| 251 if (m_pCharPos) { | 228 FX_Free(m_pCharPos); |
| 252 FX_Free(m_pCharPos); | 229 m_pCharPos = nullptr; |
| 253 m_pCharPos = nullptr; | 230 } |
| 254 } | 231 CPDF_Font* pFont = m_TextState.GetFont(); |
| 255 CPDF_Font* pFont = m_TextState.GetFont(); | 232 m_nChars = 0; |
| 256 m_nChars = 0; | 233 for (int i = 0; i < nsegs; ++i) { |
| 234 m_nChars += pFont->CountChar(pStrs[i], pStrs[i].GetLength()); |
| 235 } |
| 236 m_nChars += nsegs - 1; |
| 237 if (m_nChars > 1) { |
| 238 m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars); |
| 239 m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1); |
| 240 int index = 0; |
| 257 for (int i = 0; i < nsegs; ++i) { | 241 for (int i = 0; i < nsegs; ++i) { |
| 258 m_nChars += pFont->CountChar(pStrs[i], pStrs[i].GetLength()); | 242 const FX_CHAR* segment = pStrs[i]; |
| 259 } | 243 int offset = 0, len = pStrs[i].GetLength(); |
| 260 m_nChars += nsegs - 1; | 244 while (offset < len) { |
| 261 if (m_nChars > 1) { | 245 m_pCharCodes[index++] = pFont->GetNextChar(segment, len, offset); |
| 262 m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars); | 246 } |
| 263 m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1); | 247 if (i != nsegs - 1) { |
| 264 int index = 0; | 248 m_pCharPos[index - 1] = pKerning[i]; |
| 265 for (int i = 0; i < nsegs; ++i) { | 249 m_pCharCodes[index++] = (FX_DWORD)-1; |
| 266 const FX_CHAR* segment = pStrs[i]; | 250 } |
| 267 int offset = 0, len = pStrs[i].GetLength(); | 251 } |
| 268 while (offset < len) { | 252 } else { |
| 269 m_pCharCodes[index++] = | 253 int offset = 0; |
| 270 pFont->GetNextChar(segment, len, offset); | 254 m_pCharCodes = (FX_DWORD*)(uintptr_t)pFont->GetNextChar( |
| 271 } | 255 pStrs[0], pStrs[0].GetLength(), offset); |
| 272 if (i != nsegs - 1) { | 256 } |
| 273 m_pCharPos[index - 1] = pKerning[i]; | 257 } |
| 274 m_pCharCodes[index++] = (FX_DWORD) - 1; | 258 |
| 275 } | 259 void CPDF_TextObject::SetText(const CFX_ByteString& str) { |
| 276 } | 260 SetSegments(&str, nullptr, 1); |
| 277 } else { | 261 RecalcPositionData(); |
| 278 int offset = 0; | 262 } |
| 279 m_pCharCodes = | 263 |
| 280 (FX_DWORD*)(uintptr_t)pFont->GetNextChar(pStrs[0], | 264 void CPDF_TextObject::SetEmpty() { |
| 281 pStrs[0].GetLength(), | 265 if (m_nChars > 1 && m_pCharCodes) { |
| 282 offset); | 266 FX_Free(m_pCharCodes); |
| 283 } | 267 } |
| 284 } | 268 if (m_nChars > 1 && m_pCharPos) { |
| 285 | 269 FX_Free(m_pCharPos); |
| 286 void CPDF_TextObject::SetText(const CFX_ByteString& str) | 270 } |
| 287 { | 271 m_nChars = 0; |
| 288 SetSegments(&str, nullptr, 1); | 272 m_pCharCodes = nullptr; |
| 289 RecalcPositionData(); | 273 m_pCharPos = nullptr; |
| 290 } | 274 m_Left = m_Right = m_PosX; |
| 291 | 275 m_Top = m_Bottom = m_PosY; |
| 292 void CPDF_TextObject::SetEmpty() | |
| 293 { | |
| 294 if (m_nChars > 1 && m_pCharCodes) { | |
| 295 FX_Free(m_pCharCodes); | |
| 296 } | |
| 297 if (m_nChars > 1 && m_pCharPos) { | |
| 298 FX_Free(m_pCharPos); | |
| 299 } | |
| 300 m_nChars = 0; | |
| 301 m_pCharCodes = nullptr; | |
| 302 m_pCharPos = nullptr; | |
| 303 m_Left = m_Right = m_PosX; | |
| 304 m_Top = m_Bottom = m_PosY; | |
| 305 } | 276 } |
| 306 | 277 |
| 307 void CPDF_TextObject::SetText(CFX_ByteString* pStrs, | 278 void CPDF_TextObject::SetText(CFX_ByteString* pStrs, |
| 308 FX_FLOAT* pKerning, | 279 FX_FLOAT* pKerning, |
| 309 int nSegs) | 280 int nSegs) { |
| 310 { | 281 SetSegments(pStrs, pKerning, nSegs); |
| 311 SetSegments(pStrs, pKerning, nSegs); | 282 RecalcPositionData(); |
| 312 RecalcPositionData(); | |
| 313 } | 283 } |
| 314 | 284 |
| 315 void CPDF_TextObject::SetText(int nChars, | 285 void CPDF_TextObject::SetText(int nChars, |
| 316 FX_DWORD* pCharCodes, | 286 FX_DWORD* pCharCodes, |
| 317 FX_FLOAT* pKernings) | 287 FX_FLOAT* pKernings) { |
| 318 { | 288 if (m_nChars > 1 && m_pCharCodes) { |
| 319 if (m_nChars > 1 && m_pCharCodes) { | 289 FX_Free(m_pCharCodes); |
| 320 FX_Free(m_pCharCodes); | 290 m_pCharCodes = nullptr; |
| 321 m_pCharCodes = nullptr; | 291 } |
| 322 } | 292 if (m_pCharPos) { |
| 323 if (m_pCharPos) { | 293 FX_Free(m_pCharPos); |
| 324 FX_Free(m_pCharPos); | 294 m_pCharPos = nullptr; |
| 325 m_pCharPos = nullptr; | 295 } |
| 326 } | 296 int nKernings = 0; |
| 327 int nKernings = 0; | 297 int i; |
| 328 int i; | 298 for (i = 0; i < nChars - 1; ++i) { |
| 329 for (i = 0; i < nChars - 1; ++i) { | 299 if (pKernings[i] != 0) { |
| 330 if (pKernings[i] != 0) { | 300 ++nKernings; |
| 331 ++nKernings; | 301 } |
| 332 } | 302 } |
| 333 } | 303 m_nChars = nChars + nKernings; |
| 334 m_nChars = nChars + nKernings; | 304 if (m_nChars > 1) { |
| 335 if (m_nChars > 1) { | 305 m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars); |
| 336 m_pCharCodes = FX_Alloc(FX_DWORD, m_nChars); | 306 m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1); |
| 337 m_pCharPos = FX_Alloc(FX_FLOAT, m_nChars - 1); | 307 for (int i = 0, index = 0; i < nChars; ++i) { |
| 338 for (int i = 0, index = 0; i < nChars; ++i) { | 308 m_pCharCodes[index++] = pCharCodes[i]; |
| 339 m_pCharCodes[index++] = pCharCodes[i]; | 309 if (pKernings[i] != 0 && i != nChars - 1) { |
| 340 if (pKernings[i] != 0 && i != nChars - 1) { | 310 m_pCharCodes[index] = (FX_DWORD)-1; |
| 341 m_pCharCodes[index] = (FX_DWORD) - 1; | 311 m_pCharPos[index - 1] = pKernings[i]; |
| 342 m_pCharPos[index - 1] = pKernings[i]; | 312 ++index; |
| 343 ++index; | 313 } |
| 344 } | 314 } |
| 345 } | 315 } else { |
| 316 m_pCharCodes = (FX_DWORD*)(uintptr_t)pCharCodes[0]; |
| 317 } |
| 318 RecalcPositionData(); |
| 319 } |
| 320 |
| 321 FX_FLOAT CPDF_TextObject::GetCharWidth(FX_DWORD charcode) const { |
| 322 FX_FLOAT fontsize = m_TextState.GetFontSize() / 1000; |
| 323 CPDF_Font* pFont = m_TextState.GetFont(); |
| 324 FX_BOOL bVertWriting = FALSE; |
| 325 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); |
| 326 if (pCIDFont) { |
| 327 bVertWriting = pCIDFont->IsVertWriting(); |
| 328 } |
| 329 if (!bVertWriting) |
| 330 return pFont->GetCharWidthF(charcode, 0) * fontsize; |
| 331 |
| 332 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); |
| 333 return pCIDFont->GetVertWidth(CID) * fontsize; |
| 334 } |
| 335 |
| 336 FX_FLOAT CPDF_TextObject::GetSpaceCharWidth() const { |
| 337 CPDF_Font* pFont = m_TextState.GetFont(); |
| 338 FX_DWORD charCode = m_TextState.GetFont()->CharCodeFromUnicode(32); |
| 339 if (charCode != (FX_DWORD)-1) { |
| 340 return GetCharWidth(charCode); |
| 341 } |
| 342 FX_FLOAT fontSize = m_TextState.GetFontSize() / 4000.0f; |
| 343 FX_BOOL bVertWriting = FALSE; |
| 344 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); |
| 345 if (pCIDFont) { |
| 346 bVertWriting = pCIDFont->IsVertWriting(); |
| 347 } |
| 348 FX_RECT fontRect; |
| 349 pFont->GetFontBBox(fontRect); |
| 350 fontSize *= |
| 351 bVertWriting ? (FX_FLOAT)fontRect.Height() : (FX_FLOAT)fontRect.Width(); |
| 352 return fontSize; |
| 353 } |
| 354 |
| 355 void CPDF_TextObject::GetCharRect(int index, CFX_FloatRect& rect) const { |
| 356 CPDF_Font* pFont = m_TextState.GetFont(); |
| 357 FX_BOOL bVertWriting = FALSE; |
| 358 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); |
| 359 if (pCIDFont) { |
| 360 bVertWriting = pCIDFont->IsVertWriting(); |
| 361 } |
| 362 FX_FLOAT fontsize = m_TextState.GetFontSize() / 1000; |
| 363 int count = 0; |
| 364 for (int i = 0; i < m_nChars; ++i) { |
| 365 FX_DWORD charcode = |
| 366 m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; |
| 367 if (charcode == (FX_DWORD)-1) { |
| 368 continue; |
| 369 } |
| 370 if (count != index) { |
| 371 ++count; |
| 372 continue; |
| 373 } |
| 374 FX_FLOAT curpos = i > 0 ? m_pCharPos[i - 1] : 0; |
| 375 FX_RECT char_rect; |
| 376 pFont->GetCharBBox(charcode, char_rect, 0); |
| 377 if (!bVertWriting) { |
| 378 rect.left = curpos + char_rect.left * fontsize; |
| 379 rect.right = curpos + char_rect.right * fontsize; |
| 380 rect.top = char_rect.top * fontsize; |
| 381 rect.bottom = char_rect.bottom * fontsize; |
| 346 } else { | 382 } else { |
| 347 m_pCharCodes = (FX_DWORD*)(uintptr_t)pCharCodes[0]; | 383 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); |
| 348 } | 384 short vx, vy; |
| 349 RecalcPositionData(); | 385 pCIDFont->GetVertOrigin(CID, vx, vy); |
| 350 } | 386 char_rect.left -= vx; |
| 351 | 387 char_rect.right -= vx; |
| 352 FX_FLOAT CPDF_TextObject::GetCharWidth(FX_DWORD charcode) const | 388 char_rect.top -= vy; |
| 353 { | 389 char_rect.bottom -= vy; |
| 354 FX_FLOAT fontsize = m_TextState.GetFontSize() / 1000; | 390 rect.left = char_rect.left * fontsize; |
| 355 CPDF_Font* pFont = m_TextState.GetFont(); | 391 rect.right = char_rect.right * fontsize; |
| 356 FX_BOOL bVertWriting = FALSE; | 392 rect.top = curpos + char_rect.top * fontsize; |
| 357 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); | 393 rect.bottom = curpos + char_rect.bottom * fontsize; |
| 358 if (pCIDFont) { | 394 } |
| 359 bVertWriting = pCIDFont->IsVertWriting(); | 395 return; |
| 360 } | 396 } |
| 361 if (!bVertWriting) | |
| 362 return pFont->GetCharWidthF(charcode, 0) * fontsize; | |
| 363 | |
| 364 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); | |
| 365 return pCIDFont->GetVertWidth(CID) * fontsize; | |
| 366 } | |
| 367 | |
| 368 FX_FLOAT CPDF_TextObject::GetSpaceCharWidth() const | |
| 369 { | |
| 370 CPDF_Font* pFont = m_TextState.GetFont(); | |
| 371 FX_DWORD charCode = m_TextState.GetFont()->CharCodeFromUnicode(32); | |
| 372 if (charCode != (FX_DWORD) - 1) { | |
| 373 return GetCharWidth(charCode); | |
| 374 } | |
| 375 FX_FLOAT fontSize = m_TextState.GetFontSize() / 4000.0f; | |
| 376 FX_BOOL bVertWriting = FALSE; | |
| 377 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); | |
| 378 if (pCIDFont) { | |
| 379 bVertWriting = pCIDFont->IsVertWriting(); | |
| 380 } | |
| 381 FX_RECT fontRect; | |
| 382 pFont->GetFontBBox(fontRect); | |
| 383 fontSize *= bVertWriting ? | |
| 384 (FX_FLOAT)fontRect.Height() : (FX_FLOAT)fontRect.Width(); | |
| 385 return fontSize; | |
| 386 } | |
| 387 | |
| 388 void CPDF_TextObject::GetCharRect(int index, CFX_FloatRect& rect) const | |
| 389 { | |
| 390 CPDF_Font* pFont = m_TextState.GetFont(); | |
| 391 FX_BOOL bVertWriting = FALSE; | |
| 392 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); | |
| 393 if (pCIDFont) { | |
| 394 bVertWriting = pCIDFont->IsVertWriting(); | |
| 395 } | |
| 396 FX_FLOAT fontsize = m_TextState.GetFontSize() / 1000; | |
| 397 int count = 0; | |
| 398 for (int i = 0; i < m_nChars; ++i) { | |
| 399 FX_DWORD charcode = m_nChars == 1 ? | |
| 400 (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; | |
| 401 if (charcode == (FX_DWORD) - 1) { | |
| 402 continue; | |
| 403 } | |
| 404 if (count != index) { | |
| 405 ++count; | |
| 406 continue; | |
| 407 } | |
| 408 FX_FLOAT curpos = i > 0 ? m_pCharPos[i - 1] : 0; | |
| 409 FX_RECT char_rect; | |
| 410 pFont->GetCharBBox(charcode, char_rect, 0); | |
| 411 if (!bVertWriting) { | |
| 412 rect.left = curpos + char_rect.left * fontsize; | |
| 413 rect.right = curpos + char_rect.right * fontsize; | |
| 414 rect.top = char_rect.top * fontsize; | |
| 415 rect.bottom = char_rect.bottom * fontsize; | |
| 416 } else { | |
| 417 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); | |
| 418 short vx, vy; | |
| 419 pCIDFont->GetVertOrigin(CID, vx, vy); | |
| 420 char_rect.left -= vx; | |
| 421 char_rect.right -= vx; | |
| 422 char_rect.top -= vy; | |
| 423 char_rect.bottom -= vy; | |
| 424 rect.left = char_rect.left * fontsize; | |
| 425 rect.right = char_rect.right * fontsize; | |
| 426 rect.top = curpos + char_rect.top * fontsize; | |
| 427 rect.bottom = curpos + char_rect.bottom * fontsize; | |
| 428 } | |
| 429 return; | |
| 430 } | |
| 431 } | 397 } |
| 432 | 398 |
| 433 void CPDF_TextObject::CalcPositionData(FX_FLOAT* pTextAdvanceX, | 399 void CPDF_TextObject::CalcPositionData(FX_FLOAT* pTextAdvanceX, |
| 434 FX_FLOAT* pTextAdvanceY, | 400 FX_FLOAT* pTextAdvanceY, |
| 435 FX_FLOAT horz_scale, | 401 FX_FLOAT horz_scale, |
| 436 int level) | 402 int level) { |
| 437 { | 403 FX_FLOAT curpos = 0; |
| 438 FX_FLOAT curpos = 0; | 404 FX_FLOAT min_x = 10000 * 1.0f; |
| 439 FX_FLOAT min_x = 10000 * 1.0f; | 405 FX_FLOAT max_x = -10000 * 1.0f; |
| 440 FX_FLOAT max_x = -10000 * 1.0f; | 406 FX_FLOAT min_y = 10000 * 1.0f; |
| 441 FX_FLOAT min_y = 10000 * 1.0f; | 407 FX_FLOAT max_y = -10000 * 1.0f; |
| 442 FX_FLOAT max_y = -10000 * 1.0f; | 408 CPDF_Font* pFont = m_TextState.GetFont(); |
| 443 CPDF_Font* pFont = m_TextState.GetFont(); | 409 FX_BOOL bVertWriting = FALSE; |
| 444 FX_BOOL bVertWriting = FALSE; | 410 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); |
| 445 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); | 411 if (pCIDFont) { |
| 446 if (pCIDFont) { | 412 bVertWriting = pCIDFont->IsVertWriting(); |
| 447 bVertWriting = pCIDFont->IsVertWriting(); | 413 } |
| 448 } | 414 FX_FLOAT fontsize = m_TextState.GetFontSize(); |
| 449 FX_FLOAT fontsize = m_TextState.GetFontSize(); | 415 for (int i = 0; i < m_nChars; ++i) { |
| 450 for (int i = 0; i < m_nChars; ++i) { | 416 FX_DWORD charcode = |
| 451 FX_DWORD charcode = m_nChars == 1 ? | 417 m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; |
| 452 (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; | 418 if (charcode == (FX_DWORD)-1) { |
| 453 if (charcode == (FX_DWORD) - 1) { | 419 curpos -= FXSYS_Mul(m_pCharPos[i - 1], fontsize) / 1000; |
| 454 curpos -= FXSYS_Mul(m_pCharPos[i - 1], fontsize) / 1000; | 420 continue; |
| 455 continue; | 421 } |
| 456 } | 422 if (i) { |
| 457 if (i) { | 423 m_pCharPos[i - 1] = curpos; |
| 458 m_pCharPos[i - 1] = curpos; | 424 } |
| 459 } | 425 FX_RECT char_rect; |
| 460 FX_RECT char_rect; | 426 pFont->GetCharBBox(charcode, char_rect, level); |
| 461 pFont->GetCharBBox(charcode, char_rect, level); | 427 FX_FLOAT charwidth; |
| 462 FX_FLOAT charwidth; | 428 if (!bVertWriting) { |
| 463 if (!bVertWriting) { | 429 if (min_y > char_rect.top) { |
| 464 if (min_y > char_rect.top) { | 430 min_y = (FX_FLOAT)char_rect.top; |
| 465 min_y = (FX_FLOAT)char_rect.top; | 431 } |
| 466 } | 432 if (max_y < char_rect.top) { |
| 467 if (max_y < char_rect.top) { | 433 max_y = (FX_FLOAT)char_rect.top; |
| 468 max_y = (FX_FLOAT)char_rect.top; | 434 } |
| 469 } | 435 if (min_y > char_rect.bottom) { |
| 470 if (min_y > char_rect.bottom) { | 436 min_y = (FX_FLOAT)char_rect.bottom; |
| 471 min_y = (FX_FLOAT)char_rect.bottom; | 437 } |
| 472 } | 438 if (max_y < char_rect.bottom) { |
| 473 if (max_y < char_rect.bottom) { | 439 max_y = (FX_FLOAT)char_rect.bottom; |
| 474 max_y = (FX_FLOAT)char_rect.bottom; | 440 } |
| 475 } | 441 FX_FLOAT char_left = curpos + char_rect.left * fontsize / 1000; |
| 476 FX_FLOAT char_left = curpos + char_rect.left * fontsize / 1000; | 442 FX_FLOAT char_right = curpos + char_rect.right * fontsize / 1000; |
| 477 FX_FLOAT char_right = curpos + char_rect.right * fontsize / 1000; | 443 if (min_x > char_left) { |
| 478 if (min_x > char_left) { | 444 min_x = char_left; |
| 479 min_x = char_left; | 445 } |
| 480 } | 446 if (max_x < char_left) { |
| 481 if (max_x < char_left) { | 447 max_x = char_left; |
| 482 max_x = char_left; | 448 } |
| 483 } | 449 if (min_x > char_right) { |
| 484 if (min_x > char_right) { | 450 min_x = char_right; |
| 485 min_x = char_right; | 451 } |
| 486 } | 452 if (max_x < char_right) { |
| 487 if (max_x < char_right) { | 453 max_x = char_right; |
| 488 max_x = char_right; | 454 } |
| 489 } | 455 charwidth = pFont->GetCharWidthF(charcode, level) * fontsize / 1000; |
| 490 charwidth = pFont->GetCharWidthF(charcode, level) * fontsize / 1000; | 456 } else { |
| 491 } else { | 457 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); |
| 492 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); | 458 short vx; |
| 493 short vx; | 459 short vy; |
| 494 short vy; | 460 pCIDFont->GetVertOrigin(CID, vx, vy); |
| 495 pCIDFont->GetVertOrigin(CID, vx, vy); | 461 char_rect.left -= vx; |
| 496 char_rect.left -= vx; | 462 char_rect.right -= vx; |
| 497 char_rect.right -= vx; | 463 char_rect.top -= vy; |
| 498 char_rect.top -= vy; | 464 char_rect.bottom -= vy; |
| 499 char_rect.bottom -= vy; | 465 if (min_x > char_rect.left) { |
| 500 if (min_x > char_rect.left) { | 466 min_x = (FX_FLOAT)char_rect.left; |
| 501 min_x = (FX_FLOAT)char_rect.left; | 467 } |
| 502 } | 468 if (max_x < char_rect.left) { |
| 503 if (max_x < char_rect.left) { | 469 max_x = (FX_FLOAT)char_rect.left; |
| 504 max_x = (FX_FLOAT)char_rect.left; | 470 } |
| 505 } | 471 if (min_x > char_rect.right) { |
| 506 if (min_x > char_rect.right) { | 472 min_x = (FX_FLOAT)char_rect.right; |
| 507 min_x = (FX_FLOAT)char_rect.right; | 473 } |
| 508 } | 474 if (max_x < char_rect.right) { |
| 509 if (max_x < char_rect.right) { | 475 max_x = (FX_FLOAT)char_rect.right; |
| 510 max_x = (FX_FLOAT)char_rect.right; | 476 } |
| 511 } | 477 FX_FLOAT char_top = curpos + char_rect.top * fontsize / 1000; |
| 512 FX_FLOAT char_top = curpos + char_rect.top * fontsize / 1000; | 478 FX_FLOAT char_bottom = curpos + char_rect.bottom * fontsize / 1000; |
| 513 FX_FLOAT char_bottom = curpos + char_rect.bottom * fontsize / 1000; | 479 if (min_y > char_top) { |
| 514 if (min_y > char_top) { | 480 min_y = char_top; |
| 515 min_y = char_top; | 481 } |
| 516 } | 482 if (max_y < char_top) { |
| 517 if (max_y < char_top) { | 483 max_y = char_top; |
| 518 max_y = char_top; | 484 } |
| 519 } | 485 if (min_y > char_bottom) { |
| 520 if (min_y > char_bottom) { | 486 min_y = char_bottom; |
| 521 min_y = char_bottom; | 487 } |
| 522 } | 488 if (max_y < char_bottom) { |
| 523 if (max_y < char_bottom) { | 489 max_y = char_bottom; |
| 524 max_y = char_bottom; | 490 } |
| 525 } | 491 charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000; |
| 526 charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000; | 492 } |
| 527 } | 493 curpos += charwidth; |
| 528 curpos += charwidth; | 494 if (charcode == ' ' && (!pCIDFont || pCIDFont->GetCharSize(32) == 1)) { |
| 529 if (charcode == ' ' && (!pCIDFont || pCIDFont->GetCharSize(32) == 1)) { | 495 curpos += m_TextState.GetObject()->m_WordSpace; |
| 530 curpos += m_TextState.GetObject()->m_WordSpace; | 496 } |
| 531 } | 497 curpos += m_TextState.GetObject()->m_CharSpace; |
| 532 curpos += m_TextState.GetObject()->m_CharSpace; | 498 } |
| 533 } | 499 if (bVertWriting) { |
| 500 if (pTextAdvanceX) { |
| 501 *pTextAdvanceX = 0; |
| 502 } |
| 503 if (pTextAdvanceY) { |
| 504 *pTextAdvanceY = curpos; |
| 505 } |
| 506 min_x = min_x * fontsize / 1000; |
| 507 max_x = max_x * fontsize / 1000; |
| 508 } else { |
| 509 if (pTextAdvanceX) { |
| 510 *pTextAdvanceX = FXSYS_Mul(curpos, horz_scale); |
| 511 } |
| 512 if (pTextAdvanceY) { |
| 513 *pTextAdvanceY = 0; |
| 514 } |
| 515 min_y = min_y * fontsize / 1000; |
| 516 max_y = max_y * fontsize / 1000; |
| 517 } |
| 518 CFX_AffineMatrix matrix; |
| 519 GetTextMatrix(&matrix); |
| 520 m_Left = min_x; |
| 521 m_Right = max_x; |
| 522 m_Bottom = min_y; |
| 523 m_Top = max_y; |
| 524 matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); |
| 525 int textmode = m_TextState.GetObject()->m_TextMode; |
| 526 if (textmode == 1 || textmode == 2 || textmode == 5 || textmode == 6) { |
| 527 FX_FLOAT half_width = m_GraphState.GetObject()->m_LineWidth / 2; |
| 528 m_Left -= half_width; |
| 529 m_Right += half_width; |
| 530 m_Top += half_width; |
| 531 m_Bottom -= half_width; |
| 532 } |
| 533 } |
| 534 |
| 535 void CPDF_TextObject::CalcCharPos(FX_FLOAT* pPosArray) const { |
| 536 CPDF_Font* pFont = m_TextState.GetFont(); |
| 537 FX_BOOL bVertWriting = FALSE; |
| 538 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); |
| 539 if (pCIDFont) { |
| 540 bVertWriting = pCIDFont->IsVertWriting(); |
| 541 } |
| 542 FX_FLOAT fontsize = m_TextState.GetFontSize(); |
| 543 for (int i = 0, index = 0; i < m_nChars; ++i) { |
| 544 FX_DWORD charcode = |
| 545 m_nChars == 1 ? (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; |
| 546 if (charcode == (FX_DWORD)-1) { |
| 547 continue; |
| 548 } |
| 549 pPosArray[index++] = i ? m_pCharPos[i - 1] : 0; |
| 550 FX_FLOAT charwidth; |
| 534 if (bVertWriting) { | 551 if (bVertWriting) { |
| 535 if (pTextAdvanceX) { | 552 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); |
| 536 *pTextAdvanceX = 0; | 553 charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000; |
| 537 } | |
| 538 if (pTextAdvanceY) { | |
| 539 *pTextAdvanceY = curpos; | |
| 540 } | |
| 541 min_x = min_x * fontsize / 1000; | |
| 542 max_x = max_x * fontsize / 1000; | |
| 543 } else { | 554 } else { |
| 544 if (pTextAdvanceX) { | 555 charwidth = pFont->GetCharWidthF(charcode) * fontsize / 1000; |
| 545 *pTextAdvanceX = FXSYS_Mul(curpos, horz_scale); | 556 } |
| 546 } | 557 pPosArray[index] = pPosArray[index - 1] + charwidth; |
| 547 if (pTextAdvanceY) { | 558 index++; |
| 548 *pTextAdvanceY = 0; | 559 } |
| 549 } | 560 } |
| 550 min_y = min_y * fontsize / 1000; | 561 |
| 551 max_y = max_y * fontsize / 1000; | 562 void CPDF_TextObject::Transform(const CFX_AffineMatrix& matrix) { |
| 552 } | 563 m_TextState.GetModify(); |
| 553 CFX_AffineMatrix matrix; | 564 CFX_AffineMatrix text_matrix; |
| 554 GetTextMatrix(&matrix); | 565 GetTextMatrix(&text_matrix); |
| 555 m_Left = min_x; | 566 text_matrix.Concat(matrix); |
| 556 m_Right = max_x; | 567 FX_FLOAT* pTextMatrix = m_TextState.GetMatrix(); |
| 557 m_Bottom = min_y; | 568 pTextMatrix[0] = text_matrix.GetA(); |
| 558 m_Top = max_y; | 569 pTextMatrix[1] = text_matrix.GetC(); |
| 559 matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); | 570 pTextMatrix[2] = text_matrix.GetB(); |
| 560 int textmode = m_TextState.GetObject()->m_TextMode; | 571 pTextMatrix[3] = text_matrix.GetD(); |
| 561 if (textmode == 1 || textmode == 2 || textmode == 5 || textmode == 6) { | 572 m_PosX = text_matrix.GetE(); |
| 562 FX_FLOAT half_width = m_GraphState.GetObject()->m_LineWidth / 2; | 573 m_PosY = text_matrix.GetF(); |
| 563 m_Left -= half_width; | 574 CalcPositionData(nullptr, nullptr, 0); |
| 564 m_Right += half_width; | 575 } |
| 565 m_Top += half_width; | 576 |
| 566 m_Bottom -= half_width; | 577 void CPDF_TextObject::SetPosition(FX_FLOAT x, FX_FLOAT y) { |
| 567 } | 578 FX_FLOAT dx = x - m_PosX; |
| 568 } | 579 FX_FLOAT dy = y - m_PosY; |
| 569 | 580 m_PosX = x; |
| 570 void CPDF_TextObject::CalcCharPos(FX_FLOAT* pPosArray) const | 581 m_PosY = y; |
| 571 { | 582 m_Left += dx; |
| 572 CPDF_Font* pFont = m_TextState.GetFont(); | 583 m_Right += dx; |
| 573 FX_BOOL bVertWriting = FALSE; | 584 m_Top += dy; |
| 574 CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); | 585 m_Bottom += dy; |
| 575 if (pCIDFont) { | |
| 576 bVertWriting = pCIDFont->IsVertWriting(); | |
| 577 } | |
| 578 FX_FLOAT fontsize = m_TextState.GetFontSize(); | |
| 579 for (int i = 0, index = 0; i < m_nChars; ++i) { | |
| 580 FX_DWORD charcode = m_nChars == 1 ? | |
| 581 (FX_DWORD)(uintptr_t)m_pCharCodes : m_pCharCodes[i]; | |
| 582 if (charcode == (FX_DWORD) - 1) { | |
| 583 continue; | |
| 584 } | |
| 585 pPosArray[index++] = i ? m_pCharPos[i - 1] : 0; | |
| 586 FX_FLOAT charwidth; | |
| 587 if (bVertWriting) { | |
| 588 FX_WORD CID = pCIDFont->CIDFromCharCode(charcode); | |
| 589 charwidth = pCIDFont->GetVertWidth(CID) * fontsize / 1000; | |
| 590 } else { | |
| 591 charwidth = pFont->GetCharWidthF(charcode) * fontsize / 1000; | |
| 592 } | |
| 593 pPosArray[index] = pPosArray[index - 1] + charwidth; | |
| 594 index++; | |
| 595 } | |
| 596 } | |
| 597 | |
| 598 void CPDF_TextObject::Transform(const CFX_AffineMatrix& matrix) | |
| 599 { | |
| 600 m_TextState.GetModify(); | |
| 601 CFX_AffineMatrix text_matrix; | |
| 602 GetTextMatrix(&text_matrix); | |
| 603 text_matrix.Concat(matrix); | |
| 604 FX_FLOAT* pTextMatrix = m_TextState.GetMatrix(); | |
| 605 pTextMatrix[0] = text_matrix.GetA(); | |
| 606 pTextMatrix[1] = text_matrix.GetC(); | |
| 607 pTextMatrix[2] = text_matrix.GetB(); | |
| 608 pTextMatrix[3] = text_matrix.GetD(); | |
| 609 m_PosX = text_matrix.GetE(); | |
| 610 m_PosY = text_matrix.GetF(); | |
| 611 CalcPositionData(nullptr, nullptr, 0); | |
| 612 } | |
| 613 | |
| 614 void CPDF_TextObject::SetPosition(FX_FLOAT x, FX_FLOAT y) | |
| 615 { | |
| 616 FX_FLOAT dx = x - m_PosX; | |
| 617 FX_FLOAT dy = y - m_PosY; | |
| 618 m_PosX = x; | |
| 619 m_PosY = y; | |
| 620 m_Left += dx; | |
| 621 m_Right += dx; | |
| 622 m_Top += dy; | |
| 623 m_Bottom += dy; | |
| 624 } | 586 } |
| 625 | 587 |
| 626 void CPDF_TextObject::SetData(int nChars, | 588 void CPDF_TextObject::SetData(int nChars, |
| 627 FX_DWORD* pCharCodes, | 589 FX_DWORD* pCharCodes, |
| 628 FX_FLOAT* pCharPos, | 590 FX_FLOAT* pCharPos, |
| 629 FX_FLOAT x, | 591 FX_FLOAT x, |
| 630 FX_FLOAT y) | 592 FX_FLOAT y) { |
| 631 { | 593 ASSERT(m_nChars == 0); |
| 632 ASSERT(m_nChars == 0); | 594 m_nChars = nChars; |
| 633 m_nChars = nChars; | 595 m_PosX = x; |
| 634 m_PosX = x; | 596 m_PosY = y; |
| 635 m_PosY = y; | 597 if (nChars == 0) { |
| 636 if (nChars == 0) { | 598 return; |
| 637 return; | 599 } |
| 638 } | 600 if (nChars == 1) { |
| 639 if (nChars == 1) { | 601 m_pCharCodes = (FX_DWORD*)(uintptr_t)*pCharCodes; |
| 640 m_pCharCodes = (FX_DWORD*)(uintptr_t) * pCharCodes; | 602 } else { |
| 641 } else { | 603 m_pCharCodes = FX_Alloc(FX_DWORD, nChars); |
| 642 m_pCharCodes = FX_Alloc(FX_DWORD, nChars); | 604 FXSYS_memcpy(m_pCharCodes, pCharCodes, sizeof(FX_DWORD) * nChars); |
| 643 FXSYS_memcpy(m_pCharCodes, pCharCodes, sizeof(FX_DWORD)*nChars); | 605 m_pCharPos = FX_Alloc(FX_FLOAT, nChars - 1); |
| 644 m_pCharPos = FX_Alloc(FX_FLOAT, nChars - 1); | 606 FXSYS_memcpy(m_pCharPos, pCharPos, sizeof(FX_FLOAT) * (nChars - 1)); |
| 645 FXSYS_memcpy(m_pCharPos, pCharPos, sizeof(FX_FLOAT) * (nChars - 1)); | 607 } |
| 646 } | 608 RecalcPositionData(); |
| 647 RecalcPositionData(); | 609 } |
| 648 } | 610 |
| 649 | 611 void CPDF_TextObject::SetTextState(CPDF_TextState TextState) { |
| 650 void CPDF_TextObject::SetTextState(CPDF_TextState TextState) | 612 m_TextState = TextState; |
| 651 { | 613 CalcPositionData(nullptr, nullptr, 0); |
| 652 m_TextState = TextState; | 614 } |
| 653 CalcPositionData(nullptr, nullptr, 0); | 615 |
| 654 } | 616 CPDF_ShadingObject::CPDF_ShadingObject() { |
| 655 | 617 m_pShading = NULL; |
| 656 CPDF_ShadingObject::CPDF_ShadingObject() | 618 m_Type = PDFPAGE_SHADING; |
| 657 { | 619 } |
| 658 m_pShading = NULL; | 620 CPDF_ShadingObject::~CPDF_ShadingObject() {} |
| 659 m_Type = PDFPAGE_SHADING; | 621 void CPDF_ShadingObject::CopyData(const CPDF_PageObject* pSrc) { |
| 660 } | 622 CPDF_ShadingObject* pSrcObj = (CPDF_ShadingObject*)pSrc; |
| 661 CPDF_ShadingObject::~CPDF_ShadingObject() | 623 m_pShading = pSrcObj->m_pShading; |
| 662 { | 624 if (m_pShading && m_pShading->m_pDocument) { |
| 663 } | 625 CPDF_DocPageData* pDocPageData = m_pShading->m_pDocument->GetPageData(); |
| 664 void CPDF_ShadingObject::CopyData(const CPDF_PageObject* pSrc) | 626 m_pShading = (CPDF_ShadingPattern*)pDocPageData->GetPattern( |
| 665 { | 627 m_pShading->m_pShadingObj, m_pShading->m_bShadingObj, |
| 666 CPDF_ShadingObject* pSrcObj = (CPDF_ShadingObject*)pSrc; | 628 &m_pShading->m_ParentMatrix); |
| 667 m_pShading = pSrcObj->m_pShading; | 629 } |
| 668 if (m_pShading && m_pShading->m_pDocument) { | 630 m_Matrix = pSrcObj->m_Matrix; |
| 669 CPDF_DocPageData* pDocPageData = m_pShading->m_pDocument->GetPageData(); | 631 } |
| 670 m_pShading = (CPDF_ShadingPattern*)pDocPageData->GetPattern(m_pShading->
m_pShadingObj, m_pShading->m_bShadingObj, &m_pShading->m_ParentMatrix); | 632 void CPDF_ShadingObject::Transform(const CFX_AffineMatrix& matrix) { |
| 671 } | 633 if (!m_ClipPath.IsNull()) { |
| 672 m_Matrix = pSrcObj->m_Matrix; | 634 m_ClipPath.GetModify(); |
| 673 } | 635 m_ClipPath.Transform(matrix); |
| 674 void CPDF_ShadingObject::Transform(const CFX_AffineMatrix& matrix) | 636 } |
| 675 { | 637 m_Matrix.Concat(matrix); |
| 676 if (!m_ClipPath.IsNull()) { | 638 if (!m_ClipPath.IsNull()) { |
| 677 m_ClipPath.GetModify(); | |
| 678 m_ClipPath.Transform(matrix); | |
| 679 } | |
| 680 m_Matrix.Concat(matrix); | |
| 681 if (!m_ClipPath.IsNull()) { | |
| 682 CalcBoundingBox(); | |
| 683 } else { | |
| 684 matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); | |
| 685 } | |
| 686 } | |
| 687 void CPDF_ShadingObject::CalcBoundingBox() | |
| 688 { | |
| 689 if (m_ClipPath.IsNull()) { | |
| 690 return; | |
| 691 } | |
| 692 CFX_FloatRect rect = m_ClipPath.GetClipBox(); | |
| 693 m_Left = rect.left; | |
| 694 m_Bottom = rect.bottom; | |
| 695 m_Right = rect.right; | |
| 696 m_Top = rect.top; | |
| 697 } | |
| 698 CPDF_FormObject::~CPDF_FormObject() | |
| 699 { | |
| 700 delete m_pForm; | |
| 701 } | |
| 702 void CPDF_FormObject::Transform(const CFX_AffineMatrix& matrix) | |
| 703 { | |
| 704 m_FormMatrix.Concat(matrix); | |
| 705 CalcBoundingBox(); | 639 CalcBoundingBox(); |
| 706 } | 640 } else { |
| 707 void CPDF_FormObject::CopyData(const CPDF_PageObject* pSrc) | 641 matrix.TransformRect(m_Left, m_Right, m_Top, m_Bottom); |
| 708 { | 642 } |
| 709 const CPDF_FormObject* pSrcObj = (const CPDF_FormObject*)pSrc; | 643 } |
| 710 delete m_pForm; | 644 void CPDF_ShadingObject::CalcBoundingBox() { |
| 711 m_pForm = pSrcObj->m_pForm->Clone(); | 645 if (m_ClipPath.IsNull()) { |
| 712 m_FormMatrix = pSrcObj->m_FormMatrix; | 646 return; |
| 713 } | 647 } |
| 714 void CPDF_FormObject::CalcBoundingBox() | 648 CFX_FloatRect rect = m_ClipPath.GetClipBox(); |
| 715 { | 649 m_Left = rect.left; |
| 716 CFX_FloatRect form_rect = m_pForm->CalcBoundingBox(); | 650 m_Bottom = rect.bottom; |
| 717 form_rect.Transform(&m_FormMatrix); | 651 m_Right = rect.right; |
| 718 m_Left = form_rect.left; | 652 m_Top = rect.top; |
| 719 m_Bottom = form_rect.bottom; | 653 } |
| 720 m_Right = form_rect.right; | 654 CPDF_FormObject::~CPDF_FormObject() { |
| 721 m_Top = form_rect.top; | 655 delete m_pForm; |
| 656 } |
| 657 void CPDF_FormObject::Transform(const CFX_AffineMatrix& matrix) { |
| 658 m_FormMatrix.Concat(matrix); |
| 659 CalcBoundingBox(); |
| 660 } |
| 661 void CPDF_FormObject::CopyData(const CPDF_PageObject* pSrc) { |
| 662 const CPDF_FormObject* pSrcObj = (const CPDF_FormObject*)pSrc; |
| 663 delete m_pForm; |
| 664 m_pForm = pSrcObj->m_pForm->Clone(); |
| 665 m_FormMatrix = pSrcObj->m_FormMatrix; |
| 666 } |
| 667 void CPDF_FormObject::CalcBoundingBox() { |
| 668 CFX_FloatRect form_rect = m_pForm->CalcBoundingBox(); |
| 669 form_rect.Transform(&m_FormMatrix); |
| 670 m_Left = form_rect.left; |
| 671 m_Bottom = form_rect.bottom; |
| 672 m_Right = form_rect.right; |
| 673 m_Top = form_rect.top; |
| 722 } | 674 } |
| 723 CPDF_PageObjects::CPDF_PageObjects(FX_BOOL bReleaseMembers) | 675 CPDF_PageObjects::CPDF_PageObjects(FX_BOOL bReleaseMembers) |
| 724 : m_pFormDict(nullptr), | 676 : m_pFormDict(nullptr), |
| 725 m_pFormStream(nullptr), | 677 m_pFormStream(nullptr), |
| 726 m_pDocument(nullptr), | 678 m_pDocument(nullptr), |
| 727 m_pPageResources(nullptr), | 679 m_pPageResources(nullptr), |
| 728 m_pResources(nullptr), | 680 m_pResources(nullptr), |
| 729 m_Transparency(0), | 681 m_Transparency(0), |
| 730 m_ObjectList(128), | 682 m_ObjectList(128), |
| 731 m_bBackgroundAlphaNeeded(FALSE), | 683 m_bBackgroundAlphaNeeded(FALSE), |
| 732 m_bReleaseMembers(bReleaseMembers), | 684 m_bReleaseMembers(bReleaseMembers), |
| 733 m_pParser(nullptr), | 685 m_pParser(nullptr), |
| 734 m_ParseState(CONTENT_NOT_PARSED) | 686 m_ParseState(CONTENT_NOT_PARSED) {} |
| 735 { | 687 CPDF_PageObjects::~CPDF_PageObjects() { |
| 736 } | 688 delete m_pParser; |
| 737 CPDF_PageObjects::~CPDF_PageObjects() | 689 if (!m_bReleaseMembers) { |
| 738 { | 690 return; |
| 691 } |
| 692 FX_POSITION pos = m_ObjectList.GetHeadPosition(); |
| 693 while (pos) { |
| 694 delete (CPDF_PageObject*)m_ObjectList.GetNext(pos); |
| 695 } |
| 696 } |
| 697 void CPDF_PageObjects::ContinueParse(IFX_Pause* pPause) { |
| 698 if (m_pParser == NULL) { |
| 699 return; |
| 700 } |
| 701 m_pParser->Continue(pPause); |
| 702 if (m_pParser->GetStatus() == CPDF_ContentParser::Done) { |
| 703 m_ParseState = CONTENT_PARSED; |
| 739 delete m_pParser; | 704 delete m_pParser; |
| 740 if (!m_bReleaseMembers) { | 705 m_pParser = NULL; |
| 741 return; | 706 } |
| 742 } | 707 } |
| 708 FX_POSITION CPDF_PageObjects::InsertObject(FX_POSITION posInsertAfter, |
| 709 CPDF_PageObject* pNewObject) { |
| 710 if (!posInsertAfter) { |
| 711 return m_ObjectList.AddHead(pNewObject); |
| 712 } |
| 713 return m_ObjectList.InsertAfter(posInsertAfter, pNewObject); |
| 714 } |
| 715 int CPDF_PageObjects::GetObjectIndex(CPDF_PageObject* pObj) const { |
| 716 int index = 0; |
| 717 FX_POSITION pos = m_ObjectList.GetHeadPosition(); |
| 718 while (pos) { |
| 719 CPDF_PageObject* pThisObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); |
| 720 if (pThisObj == pObj) { |
| 721 return index; |
| 722 } |
| 723 index++; |
| 724 } |
| 725 return -1; |
| 726 } |
| 727 CPDF_PageObject* CPDF_PageObjects::GetObjectByIndex(int index) const { |
| 728 FX_POSITION pos = m_ObjectList.FindIndex(index); |
| 729 if (pos == NULL) { |
| 730 return NULL; |
| 731 } |
| 732 return (CPDF_PageObject*)m_ObjectList.GetAt(pos); |
| 733 } |
| 734 void CPDF_PageObjects::Transform(const CFX_AffineMatrix& matrix) { |
| 735 FX_POSITION pos = m_ObjectList.GetHeadPosition(); |
| 736 while (pos) { |
| 737 CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); |
| 738 pObj->Transform(matrix); |
| 739 } |
| 740 } |
| 741 CFX_FloatRect CPDF_PageObjects::CalcBoundingBox() const { |
| 742 if (m_ObjectList.GetCount() == 0) { |
| 743 return CFX_FloatRect(0, 0, 0, 0); |
| 744 } |
| 745 FX_FLOAT left, right, top, bottom; |
| 746 left = bottom = 1000000 * 1.0f; |
| 747 right = top = -1000000 * 1.0f; |
| 748 FX_POSITION pos = m_ObjectList.GetHeadPosition(); |
| 749 while (pos) { |
| 750 CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); |
| 751 if (left > pObj->m_Left) { |
| 752 left = pObj->m_Left; |
| 753 } |
| 754 if (right < pObj->m_Right) { |
| 755 right = pObj->m_Right; |
| 756 } |
| 757 if (top < pObj->m_Top) { |
| 758 top = pObj->m_Top; |
| 759 } |
| 760 if (bottom > pObj->m_Bottom) { |
| 761 bottom = pObj->m_Bottom; |
| 762 } |
| 763 } |
| 764 return CFX_FloatRect(left, bottom, right, top); |
| 765 } |
| 766 void CPDF_PageObjects::LoadTransInfo() { |
| 767 if (m_pFormDict == NULL) { |
| 768 return; |
| 769 } |
| 770 CPDF_Dictionary* pGroup = m_pFormDict->GetDict(FX_BSTRC("Group")); |
| 771 if (pGroup == NULL) { |
| 772 return; |
| 773 } |
| 774 if (pGroup->GetString(FX_BSTRC("S")) != FX_BSTRC("Transparency")) { |
| 775 return; |
| 776 } |
| 777 m_Transparency |= PDFTRANS_GROUP; |
| 778 if (pGroup->GetInteger(FX_BSTRC("I"))) { |
| 779 m_Transparency |= PDFTRANS_ISOLATED; |
| 780 } |
| 781 if (pGroup->GetInteger(FX_BSTRC("K"))) { |
| 782 m_Transparency |= PDFTRANS_KNOCKOUT; |
| 783 } |
| 784 } |
| 785 void CPDF_PageObjects::ClearCacheObjects() { |
| 786 m_ParseState = CONTENT_NOT_PARSED; |
| 787 delete m_pParser; |
| 788 m_pParser = NULL; |
| 789 if (m_bReleaseMembers) { |
| 743 FX_POSITION pos = m_ObjectList.GetHeadPosition(); | 790 FX_POSITION pos = m_ObjectList.GetHeadPosition(); |
| 744 while (pos) { | 791 while (pos) { |
| 745 delete (CPDF_PageObject*)m_ObjectList.GetNext(pos); | 792 delete (CPDF_PageObject*)m_ObjectList.GetNext(pos); |
| 746 } | 793 } |
| 747 } | 794 } |
| 748 void CPDF_PageObjects::ContinueParse(IFX_Pause* pPause) | 795 m_ObjectList.RemoveAll(); |
| 749 { | 796 } |
| 750 if (m_pParser == NULL) { | 797 CPDF_Page::CPDF_Page() { |
| 751 return; | 798 m_pPageRender = NULL; |
| 752 } | 799 } |
| 753 m_pParser->Continue(pPause); | 800 void CPDF_Page::Load(CPDF_Document* pDocument, |
| 754 if (m_pParser->GetStatus() == CPDF_ContentParser::Done) { | 801 CPDF_Dictionary* pPageDict, |
| 755 m_ParseState = CONTENT_PARSED; | 802 FX_BOOL bPageCache) { |
| 756 delete m_pParser; | 803 m_pDocument = (CPDF_Document*)pDocument; |
| 757 m_pParser = NULL; | 804 m_pFormDict = pPageDict; |
| 758 } | 805 if (bPageCache) { |
| 759 } | 806 m_pPageRender = |
| 760 FX_POSITION CPDF_PageObjects::InsertObject(FX_POSITION posInsertAfter, CPDF_Page
Object* pNewObject) | 807 CPDF_ModuleMgr::Get()->GetRenderModule()->CreatePageCache(this); |
| 761 { | 808 } |
| 762 if (!posInsertAfter) { | 809 if (pPageDict == NULL) { |
| 763 return m_ObjectList.AddHead(pNewObject); | 810 m_PageWidth = m_PageHeight = 100 * 1.0f; |
| 764 } | 811 m_pPageResources = m_pResources = NULL; |
| 765 return m_ObjectList.InsertAfter(posInsertAfter, pNewObject); | 812 return; |
| 766 } | 813 } |
| 767 int CPDF_PageObjects::GetObjectIndex(CPDF_PageObject* pObj) const | 814 CPDF_Object* pageAttr = GetPageAttr(FX_BSTRC("Resources")); |
| 768 { | 815 m_pResources = pageAttr ? pageAttr->GetDict() : NULL; |
| 769 int index = 0; | 816 m_pPageResources = m_pResources; |
| 770 FX_POSITION pos = m_ObjectList.GetHeadPosition(); | 817 CPDF_Object* pRotate = GetPageAttr(FX_BSTRC("Rotate")); |
| 771 while (pos) { | 818 int rotate = 0; |
| 772 CPDF_PageObject* pThisObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); | 819 if (pRotate) { |
| 773 if (pThisObj == pObj) { | 820 rotate = pRotate->GetInteger() / 90 % 4; |
| 774 return index; | 821 } |
| 775 } | 822 if (rotate < 0) { |
| 776 index ++; | 823 rotate += 4; |
| 777 } | 824 } |
| 778 return -1; | 825 CPDF_Array *pMediaBox, *pCropBox; |
| 779 } | 826 pMediaBox = (CPDF_Array*)GetPageAttr(FX_BSTRC("MediaBox")); |
| 780 CPDF_PageObject* CPDF_PageObjects::GetObjectByIndex(int index) const | 827 CFX_FloatRect mediabox; |
| 781 { | 828 if (pMediaBox) { |
| 782 FX_POSITION pos = m_ObjectList.FindIndex(index); | 829 mediabox = pMediaBox->GetRect(); |
| 783 if (pos == NULL) { | 830 mediabox.Normalize(); |
| 784 return NULL; | 831 } |
| 785 } | 832 if (mediabox.IsEmpty()) { |
| 786 return (CPDF_PageObject*)m_ObjectList.GetAt(pos); | 833 mediabox = CFX_FloatRect(0, 0, 612, 792); |
| 787 } | 834 } |
| 788 void CPDF_PageObjects::Transform(const CFX_AffineMatrix& matrix) | 835 pCropBox = (CPDF_Array*)GetPageAttr(FX_BSTRC("CropBox")); |
| 789 { | 836 if (pCropBox) { |
| 790 FX_POSITION pos = m_ObjectList.GetHeadPosition(); | 837 m_BBox = pCropBox->GetRect(); |
| 791 while (pos) { | 838 m_BBox.Normalize(); |
| 792 CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); | 839 } |
| 793 pObj->Transform(matrix); | 840 if (m_BBox.IsEmpty()) { |
| 794 } | 841 m_BBox = mediabox; |
| 795 } | 842 } else { |
| 796 CFX_FloatRect CPDF_PageObjects::CalcBoundingBox() const | 843 m_BBox.Intersect(mediabox); |
| 797 { | 844 } |
| 798 if (m_ObjectList.GetCount() == 0) { | 845 if (rotate % 2) { |
| 799 return CFX_FloatRect(0, 0, 0, 0); | 846 m_PageHeight = m_BBox.right - m_BBox.left; |
| 800 } | 847 m_PageWidth = m_BBox.top - m_BBox.bottom; |
| 801 FX_FLOAT left, right, top, bottom; | 848 } else { |
| 802 left = bottom = 1000000 * 1.0f; | 849 m_PageWidth = m_BBox.right - m_BBox.left; |
| 803 right = top = -1000000 * 1.0f; | 850 m_PageHeight = m_BBox.top - m_BBox.bottom; |
| 804 FX_POSITION pos = m_ObjectList.GetHeadPosition(); | 851 } |
| 805 while (pos) { | 852 switch (rotate) { |
| 806 CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); | 853 case 0: |
| 807 if (left > pObj->m_Left) { | 854 m_PageMatrix.Set(1.0f, 0, 0, 1.0f, -m_BBox.left, -m_BBox.bottom); |
| 808 left = pObj->m_Left; | 855 break; |
| 809 } | 856 case 1: |
| 810 if (right < pObj->m_Right) { | 857 m_PageMatrix.Set(0, -1.0f, 1.0f, 0, -m_BBox.bottom, m_BBox.right); |
| 811 right = pObj->m_Right; | 858 break; |
| 812 } | 859 case 2: |
| 813 if (top < pObj->m_Top) { | 860 m_PageMatrix.Set(-1.0f, 0, 0, -1.0f, m_BBox.right, m_BBox.top); |
| 814 top = pObj->m_Top; | 861 break; |
| 815 } | 862 case 3: |
| 816 if (bottom > pObj->m_Bottom) { | 863 m_PageMatrix.Set(0, 1.0f, -1.0f, 0, m_BBox.top, -m_BBox.left); |
| 817 bottom = pObj->m_Bottom; | 864 break; |
| 818 } | 865 } |
| 819 } | 866 m_Transparency = PDFTRANS_ISOLATED; |
| 820 return CFX_FloatRect(left, bottom, right, top); | 867 LoadTransInfo(); |
| 821 } | 868 } |
| 822 void CPDF_PageObjects::LoadTransInfo() | 869 void CPDF_Page::StartParse(CPDF_ParseOptions* pOptions, FX_BOOL bReParse) { |
| 823 { | 870 if (bReParse) { |
| 824 if (m_pFormDict == NULL) { | 871 ClearCacheObjects(); |
| 825 return; | 872 } |
| 826 } | 873 if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) { |
| 827 CPDF_Dictionary* pGroup = m_pFormDict->GetDict(FX_BSTRC("Group")); | 874 return; |
| 828 if (pGroup == NULL) { | 875 } |
| 829 return; | 876 m_pParser = new CPDF_ContentParser; |
| 830 } | 877 m_pParser->Start(this, pOptions); |
| 831 if (pGroup->GetString(FX_BSTRC("S")) != FX_BSTRC("Transparency")) { | 878 m_ParseState = CONTENT_PARSING; |
| 832 return; | 879 } |
| 833 } | 880 void CPDF_Page::ParseContent(CPDF_ParseOptions* pOptions, FX_BOOL bReParse) { |
| 834 m_Transparency |= PDFTRANS_GROUP; | 881 StartParse(pOptions, bReParse); |
| 835 if (pGroup->GetInteger(FX_BSTRC("I"))) { | 882 ContinueParse(NULL); |
| 836 m_Transparency |= PDFTRANS_ISOLATED; | 883 } |
| 837 } | 884 CPDF_Page::~CPDF_Page() { |
| 838 if (pGroup->GetInteger(FX_BSTRC("K"))) { | 885 if (m_pPageRender) { |
| 839 m_Transparency |= PDFTRANS_KNOCKOUT; | 886 IPDF_RenderModule* pModule = CPDF_ModuleMgr::Get()->GetRenderModule(); |
| 840 } | 887 pModule->DestroyPageCache(m_pPageRender); |
| 841 } | 888 } |
| 842 void CPDF_PageObjects::ClearCacheObjects() | 889 } |
| 843 { | 890 CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict, |
| 844 m_ParseState = CONTENT_NOT_PARSED; | 891 const CFX_ByteStringC& name) { |
| 845 delete m_pParser; | 892 int level = 0; |
| 846 m_pParser = NULL; | 893 while (1) { |
| 847 if (m_bReleaseMembers) { | 894 CPDF_Object* pObj = pPageDict->GetElementValue(name); |
| 848 FX_POSITION pos = m_ObjectList.GetHeadPosition(); | 895 if (pObj) { |
| 849 while (pos) { | 896 return pObj; |
| 850 delete (CPDF_PageObject*)m_ObjectList.GetNext(pos); | 897 } |
| 851 } | 898 CPDF_Dictionary* pParent = pPageDict->GetDict(FX_BSTRC("Parent")); |
| 852 } | 899 if (!pParent || pParent == pPageDict) { |
| 853 m_ObjectList.RemoveAll(); | 900 return NULL; |
| 854 } | 901 } |
| 855 CPDF_Page::CPDF_Page() | 902 pPageDict = pParent; |
| 856 { | 903 level++; |
| 857 m_pPageRender = NULL; | 904 if (level == 1000) { |
| 858 } | 905 return NULL; |
| 859 void CPDF_Page::Load(CPDF_Document* pDocument, CPDF_Dictionary* pPageDict, FX_BO
OL bPageCache) | 906 } |
| 860 { | 907 } |
| 861 m_pDocument = (CPDF_Document*)pDocument; | 908 } |
| 862 m_pFormDict = pPageDict; | 909 CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteStringC& name) const { |
| 863 if (bPageCache) { | 910 return FPDFAPI_GetPageAttr(m_pFormDict, name); |
| 864 m_pPageRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreatePageCach
e(this); | 911 } |
| 865 } | 912 CPDF_Form::CPDF_Form(CPDF_Document* pDoc, |
| 866 if (pPageDict == NULL) { | 913 CPDF_Dictionary* pPageResources, |
| 867 m_PageWidth = m_PageHeight = 100 * 1.0f; | 914 CPDF_Stream* pFormStream, |
| 868 m_pPageResources = m_pResources = NULL; | 915 CPDF_Dictionary* pParentResources) { |
| 869 return; | 916 m_pDocument = pDoc; |
| 870 } | 917 m_pFormStream = pFormStream; |
| 871 CPDF_Object* pageAttr = GetPageAttr(FX_BSTRC("Resources")); | 918 m_pFormDict = pFormStream ? pFormStream->GetDict() : NULL; |
| 872 m_pResources = pageAttr ? pageAttr->GetDict() : NULL; | 919 m_pResources = m_pFormDict->GetDict(FX_BSTRC("Resources")); |
| 873 m_pPageResources = m_pResources; | 920 m_pPageResources = pPageResources; |
| 874 CPDF_Object* pRotate = GetPageAttr(FX_BSTRC("Rotate")); | 921 if (m_pResources == NULL) { |
| 875 int rotate = 0; | 922 m_pResources = pParentResources; |
| 876 if (pRotate) { | 923 } |
| 877 rotate = pRotate->GetInteger() / 90 % 4; | 924 if (m_pResources == NULL) { |
| 878 } | 925 m_pResources = pPageResources; |
| 879 if (rotate < 0) { | 926 } |
| 880 rotate += 4; | 927 m_Transparency = 0; |
| 881 } | 928 LoadTransInfo(); |
| 882 CPDF_Array* pMediaBox, *pCropBox; | 929 } |
| 883 pMediaBox = (CPDF_Array*)GetPageAttr(FX_BSTRC("MediaBox")); | 930 CPDF_Form::~CPDF_Form() {} |
| 884 CFX_FloatRect mediabox; | 931 void CPDF_Form::StartParse(CPDF_AllStates* pGraphicStates, |
| 885 if (pMediaBox) { | 932 CFX_AffineMatrix* pParentMatrix, |
| 886 mediabox = pMediaBox->GetRect(); | 933 CPDF_Type3Char* pType3Char, |
| 887 mediabox.Normalize(); | 934 CPDF_ParseOptions* pOptions, |
| 888 } | 935 int level) { |
| 889 if (mediabox.IsEmpty()) { | 936 if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) { |
| 890 mediabox = CFX_FloatRect(0, 0, 612, 792); | 937 return; |
| 891 } | 938 } |
| 892 pCropBox = (CPDF_Array*)GetPageAttr(FX_BSTRC("CropBox")); | 939 m_pParser = new CPDF_ContentParser; |
| 893 if (pCropBox) { | 940 m_pParser->Start(this, pGraphicStates, pParentMatrix, pType3Char, pOptions, |
| 894 m_BBox = pCropBox->GetRect(); | 941 level); |
| 895 m_BBox.Normalize(); | 942 m_ParseState = CONTENT_PARSING; |
| 896 } | 943 } |
| 897 if (m_BBox.IsEmpty()) { | 944 void CPDF_Form::ParseContent(CPDF_AllStates* pGraphicStates, |
| 898 m_BBox = mediabox; | 945 CFX_AffineMatrix* pParentMatrix, |
| 899 } else { | 946 CPDF_Type3Char* pType3Char, |
| 900 m_BBox.Intersect(mediabox); | 947 CPDF_ParseOptions* pOptions, |
| 901 } | 948 int level) { |
| 902 if (rotate % 2) { | 949 StartParse(pGraphicStates, pParentMatrix, pType3Char, pOptions, level); |
| 903 m_PageHeight = m_BBox.right - m_BBox.left; | 950 ContinueParse(NULL); |
| 904 m_PageWidth = m_BBox.top - m_BBox.bottom; | 951 } |
| 905 } else { | 952 CPDF_Form* CPDF_Form::Clone() const { |
| 906 m_PageWidth = m_BBox.right - m_BBox.left; | 953 CPDF_Form* pClone = |
| 907 m_PageHeight = m_BBox.top - m_BBox.bottom; | 954 new CPDF_Form(m_pDocument, m_pPageResources, m_pFormStream, m_pResources); |
| 908 } | 955 FX_POSITION pos = m_ObjectList.GetHeadPosition(); |
| 909 switch (rotate) { | 956 while (pos) { |
| 910 case 0: | 957 CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); |
| 911 m_PageMatrix.Set(1.0f, 0, 0, 1.0f, -m_BBox.left, -m_BBox.bottom); | 958 pClone->m_ObjectList.AddTail(pObj->Clone()); |
| 912 break; | 959 } |
| 913 case 1: | 960 return pClone; |
| 914 m_PageMatrix.Set(0, -1.0f, 1.0f, 0, -m_BBox.bottom, m_BBox.right); | 961 } |
| 915 break; | 962 void CPDF_Page::GetDisplayMatrix(CFX_AffineMatrix& matrix, |
| 916 case 2: | 963 int xPos, |
| 917 m_PageMatrix.Set(-1.0f, 0, 0, -1.0f, m_BBox.right, m_BBox.top); | 964 int yPos, |
| 918 break; | 965 int xSize, |
| 919 case 3: | 966 int ySize, |
| 920 m_PageMatrix.Set(0, 1.0f, -1.0f, 0, m_BBox.top, -m_BBox.left); | 967 int iRotate) const { |
| 921 break; | 968 if (m_PageWidth == 0 || m_PageHeight == 0) { |
| 922 } | 969 return; |
| 923 m_Transparency = PDFTRANS_ISOLATED; | 970 } |
| 924 LoadTransInfo(); | 971 CFX_AffineMatrix display_matrix; |
| 925 } | 972 int x0, y0, x1, y1, x2, y2; |
| 926 void CPDF_Page::StartParse(CPDF_ParseOptions* pOptions, FX_BOOL bReParse) | 973 iRotate %= 4; |
| 927 { | 974 switch (iRotate) { |
| 928 if (bReParse) { | 975 case 0: |
| 929 ClearCacheObjects(); | 976 x0 = xPos; |
| 930 } | 977 y0 = yPos + ySize; |
| 931 if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) { | 978 x1 = xPos; |
| 932 return; | 979 y1 = yPos; |
| 933 } | 980 x2 = xPos + xSize; |
| 934 m_pParser = new CPDF_ContentParser; | 981 y2 = yPos + ySize; |
| 935 m_pParser->Start(this, pOptions); | 982 break; |
| 936 m_ParseState = CONTENT_PARSING; | 983 case 1: |
| 937 } | 984 x0 = xPos; |
| 938 void CPDF_Page::ParseContent(CPDF_ParseOptions* pOptions, FX_BOOL bReParse) | 985 y0 = yPos; |
| 939 { | 986 x1 = xPos + xSize; |
| 940 StartParse(pOptions, bReParse); | 987 y1 = yPos; |
| 941 ContinueParse(NULL); | 988 x2 = xPos; |
| 942 } | 989 y2 = yPos + ySize; |
| 943 CPDF_Page::~CPDF_Page() | 990 break; |
| 944 { | 991 case 2: |
| 945 if (m_pPageRender) { | 992 x0 = xPos + xSize; |
| 946 IPDF_RenderModule* pModule = CPDF_ModuleMgr::Get()->GetRenderModule(); | 993 y0 = yPos; |
| 947 pModule->DestroyPageCache(m_pPageRender); | 994 x1 = xPos + xSize; |
| 948 } | 995 y1 = yPos + ySize; |
| 949 } | 996 x2 = xPos; |
| 950 CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict, const CFX_ByteStrin
gC& name) | 997 y2 = yPos; |
| 951 { | 998 break; |
| 952 int level = 0; | 999 case 3: |
| 953 while (1) { | 1000 x0 = xPos + xSize; |
| 954 CPDF_Object* pObj = pPageDict->GetElementValue(name); | 1001 y0 = yPos + ySize; |
| 955 if (pObj) { | 1002 x1 = xPos; |
| 956 return pObj; | 1003 y1 = yPos + ySize; |
| 957 } | 1004 x2 = xPos + xSize; |
| 958 CPDF_Dictionary* pParent = pPageDict->GetDict(FX_BSTRC("Parent")); | 1005 y2 = yPos; |
| 959 if (!pParent || pParent == pPageDict) { | 1006 break; |
| 960 return NULL; | 1007 } |
| 961 } | 1008 display_matrix.Set(FXSYS_Div((FX_FLOAT)(x2 - x0), m_PageWidth), |
| 962 pPageDict = pParent; | 1009 FXSYS_Div((FX_FLOAT)(y2 - y0), m_PageWidth), |
| 963 level ++; | 1010 FXSYS_Div((FX_FLOAT)(x1 - x0), m_PageHeight), |
| 964 if (level == 1000) { | 1011 FXSYS_Div((FX_FLOAT)(y1 - y0), m_PageHeight), (FX_FLOAT)x0, |
| 965 return NULL; | 1012 (FX_FLOAT)y0); |
| 966 } | 1013 matrix = m_PageMatrix; |
| 967 } | 1014 matrix.Concat(display_matrix); |
| 968 } | 1015 } |
| 969 CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteStringC& name) const | 1016 CPDF_ParseOptions::CPDF_ParseOptions() { |
| 970 { | 1017 m_bTextOnly = FALSE; |
| 971 return FPDFAPI_GetPageAttr(m_pFormDict, name); | 1018 m_bMarkedContent = TRUE; |
| 972 } | 1019 m_bSeparateForm = TRUE; |
| 973 CPDF_Form::CPDF_Form(CPDF_Document* pDoc, CPDF_Dictionary* pPageResources, CPDF_
Stream* pFormStream, CPDF_Dictionary* pParentResources) | 1020 m_bDecodeInlineImage = FALSE; |
| 974 { | 1021 } |
| 975 m_pDocument = pDoc; | |
| 976 m_pFormStream = pFormStream; | |
| 977 m_pFormDict = pFormStream ? pFormStream->GetDict() : NULL; | |
| 978 m_pResources = m_pFormDict->GetDict(FX_BSTRC("Resources")); | |
| 979 m_pPageResources = pPageResources; | |
| 980 if (m_pResources == NULL) { | |
| 981 m_pResources = pParentResources; | |
| 982 } | |
| 983 if (m_pResources == NULL) { | |
| 984 m_pResources = pPageResources; | |
| 985 } | |
| 986 m_Transparency = 0; | |
| 987 LoadTransInfo(); | |
| 988 } | |
| 989 CPDF_Form::~CPDF_Form() | |
| 990 { | |
| 991 } | |
| 992 void CPDF_Form::StartParse(CPDF_AllStates* pGraphicStates, CFX_AffineMatrix* pPa
rentMatrix, | |
| 993 CPDF_Type3Char* pType3Char, CPDF_ParseOptions* pOptio
ns, int level) | |
| 994 { | |
| 995 if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) { | |
| 996 return; | |
| 997 } | |
| 998 m_pParser = new CPDF_ContentParser; | |
| 999 m_pParser->Start(this, pGraphicStates, pParentMatrix, pType3Char, pOptions,
level); | |
| 1000 m_ParseState = CONTENT_PARSING; | |
| 1001 } | |
| 1002 void CPDF_Form::ParseContent(CPDF_AllStates* pGraphicStates, CFX_AffineMatrix* p
ParentMatrix, | |
| 1003 CPDF_Type3Char* pType3Char, CPDF_ParseOptions* pOpt
ions, int level) | |
| 1004 { | |
| 1005 StartParse(pGraphicStates, pParentMatrix, pType3Char, pOptions, level); | |
| 1006 ContinueParse(NULL); | |
| 1007 } | |
| 1008 CPDF_Form* CPDF_Form::Clone() const | |
| 1009 { | |
| 1010 CPDF_Form* pClone = new CPDF_Form(m_pDocument, m_pPageResources, m_pFormStre
am, m_pResources); | |
| 1011 FX_POSITION pos = m_ObjectList.GetHeadPosition(); | |
| 1012 while (pos) { | |
| 1013 CPDF_PageObject* pObj = (CPDF_PageObject*)m_ObjectList.GetNext(pos); | |
| 1014 pClone->m_ObjectList.AddTail(pObj->Clone()); | |
| 1015 } | |
| 1016 return pClone; | |
| 1017 } | |
| 1018 void CPDF_Page::GetDisplayMatrix(CFX_AffineMatrix& matrix, int xPos, int yPos, | |
| 1019 int xSize, int ySize, int iRotate) const | |
| 1020 { | |
| 1021 if (m_PageWidth == 0 || m_PageHeight == 0) { | |
| 1022 return; | |
| 1023 } | |
| 1024 CFX_AffineMatrix display_matrix; | |
| 1025 int x0, y0, x1, y1, x2, y2; | |
| 1026 iRotate %= 4; | |
| 1027 switch (iRotate) { | |
| 1028 case 0: | |
| 1029 x0 = xPos; | |
| 1030 y0 = yPos + ySize; | |
| 1031 x1 = xPos; | |
| 1032 y1 = yPos; | |
| 1033 x2 = xPos + xSize; | |
| 1034 y2 = yPos + ySize; | |
| 1035 break; | |
| 1036 case 1: | |
| 1037 x0 = xPos; | |
| 1038 y0 = yPos; | |
| 1039 x1 = xPos + xSize; | |
| 1040 y1 = yPos; | |
| 1041 x2 = xPos; | |
| 1042 y2 = yPos + ySize; | |
| 1043 break; | |
| 1044 case 2: | |
| 1045 x0 = xPos + xSize; | |
| 1046 y0 = yPos; | |
| 1047 x1 = xPos + xSize; | |
| 1048 y1 = yPos + ySize; | |
| 1049 x2 = xPos; | |
| 1050 y2 = yPos; | |
| 1051 break; | |
| 1052 case 3: | |
| 1053 x0 = xPos + xSize; | |
| 1054 y0 = yPos + ySize; | |
| 1055 x1 = xPos; | |
| 1056 y1 = yPos + ySize; | |
| 1057 x2 = xPos + xSize; | |
| 1058 y2 = yPos; | |
| 1059 break; | |
| 1060 } | |
| 1061 display_matrix.Set(FXSYS_Div((FX_FLOAT)(x2 - x0), m_PageWidth), | |
| 1062 FXSYS_Div((FX_FLOAT)(y2 - y0), m_PageWidth), | |
| 1063 FXSYS_Div((FX_FLOAT)(x1 - x0), m_PageHeight), | |
| 1064 FXSYS_Div((FX_FLOAT)(y1 - y0), m_PageHeight), | |
| 1065 (FX_FLOAT)x0, (FX_FLOAT)y0); | |
| 1066 matrix = m_PageMatrix; | |
| 1067 matrix.Concat(display_matrix); | |
| 1068 } | |
| 1069 CPDF_ParseOptions::CPDF_ParseOptions() | |
| 1070 { | |
| 1071 m_bTextOnly = FALSE; | |
| 1072 m_bMarkedContent = TRUE; | |
| 1073 m_bSeparateForm = TRUE; | |
| 1074 m_bDecodeInlineImage = FALSE; | |
| 1075 } | |
| OLD | NEW |