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