| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| 6 | |
| 7 #include "core/src/fpdfapi/fpdf_page/pageint.h" | |
| 8 | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "core/include/fpdfapi/cpdf_array.h" | |
| 12 #include "core/include/fpdfapi/cpdf_dictionary.h" | |
| 13 #include "core/include/fpdfapi/cpdf_document.h" | |
| 14 #include "core/include/fpdfapi/cpdf_name.h" | |
| 15 #include "core/include/fpdfapi/cpdf_number.h" | |
| 16 #include "core/include/fpdfapi/cpdf_reference.h" | |
| 17 #include "core/include/fpdfapi/fpdf_module.h" | |
| 18 #include "core/include/fpdfapi/fpdf_page.h" | |
| 19 #include "core/include/fpdfapi/fpdf_parser_decode.h" | |
| 20 #include "core/include/fpdfapi/fpdf_serial.h" | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 const char kPathOperatorSubpath = 'm'; | |
| 25 const char kPathOperatorLine = 'l'; | |
| 26 const char kPathOperatorCubicBezier1 = 'c'; | |
| 27 const char kPathOperatorCubicBezier2 = 'v'; | |
| 28 const char kPathOperatorCubicBezier3 = 'y'; | |
| 29 const char kPathOperatorClosePath = 'h'; | |
| 30 const char kPathOperatorRectangle[] = "re"; | |
| 31 | |
| 32 struct _FX_BSTR { | |
| 33 const FX_CHAR* m_Ptr; | |
| 34 int m_Size; | |
| 35 }; | |
| 36 #define _FX_BSTRC(str) \ | |
| 37 { str, sizeof(str) - 1 } | |
| 38 | |
| 39 struct PDF_AbbrPairs { | |
| 40 _FX_BSTR full_name; | |
| 41 _FX_BSTR abbr; | |
| 42 }; | |
| 43 | |
| 44 const PDF_AbbrPairs PDF_InlineKeyAbbr[] = { | |
| 45 {_FX_BSTRC("BitsPerComponent"), _FX_BSTRC("BPC")}, | |
| 46 {_FX_BSTRC("ColorSpace"), _FX_BSTRC("CS")}, | |
| 47 {_FX_BSTRC("Decode"), _FX_BSTRC("D")}, | |
| 48 {_FX_BSTRC("DecodeParms"), _FX_BSTRC("DP")}, | |
| 49 {_FX_BSTRC("Filter"), _FX_BSTRC("F")}, | |
| 50 {_FX_BSTRC("Height"), _FX_BSTRC("H")}, | |
| 51 {_FX_BSTRC("ImageMask"), _FX_BSTRC("IM")}, | |
| 52 {_FX_BSTRC("Interpolate"), _FX_BSTRC("I")}, | |
| 53 {_FX_BSTRC("Width"), _FX_BSTRC("W")}, | |
| 54 }; | |
| 55 | |
| 56 const PDF_AbbrPairs PDF_InlineValueAbbr[] = { | |
| 57 {_FX_BSTRC("DeviceGray"), _FX_BSTRC("G")}, | |
| 58 {_FX_BSTRC("DeviceRGB"), _FX_BSTRC("RGB")}, | |
| 59 {_FX_BSTRC("DeviceCMYK"), _FX_BSTRC("CMYK")}, | |
| 60 {_FX_BSTRC("Indexed"), _FX_BSTRC("I")}, | |
| 61 {_FX_BSTRC("ASCIIHexDecode"), _FX_BSTRC("AHx")}, | |
| 62 {_FX_BSTRC("ASCII85Decode"), _FX_BSTRC("A85")}, | |
| 63 {_FX_BSTRC("LZWDecode"), _FX_BSTRC("LZW")}, | |
| 64 {_FX_BSTRC("FlateDecode"), _FX_BSTRC("Fl")}, | |
| 65 {_FX_BSTRC("RunLengthDecode"), _FX_BSTRC("RL")}, | |
| 66 {_FX_BSTRC("CCITTFaxDecode"), _FX_BSTRC("CCF")}, | |
| 67 {_FX_BSTRC("DCTDecode"), _FX_BSTRC("DCT")}, | |
| 68 }; | |
| 69 | |
| 70 struct AbbrReplacementOp { | |
| 71 bool is_replace_key; | |
| 72 CFX_ByteString key; | |
| 73 CFX_ByteStringC replacement; | |
| 74 }; | |
| 75 | |
| 76 class CPDF_StreamParserAutoClearer { | |
| 77 public: | |
| 78 CPDF_StreamParserAutoClearer(CPDF_StreamParser** scoped_variable, | |
| 79 CPDF_StreamParser* new_parser) | |
| 80 : scoped_variable_(scoped_variable) { | |
| 81 *scoped_variable_ = new_parser; | |
| 82 } | |
| 83 ~CPDF_StreamParserAutoClearer() { *scoped_variable_ = NULL; } | |
| 84 | |
| 85 private: | |
| 86 CPDF_StreamParser** scoped_variable_; | |
| 87 }; | |
| 88 | |
| 89 CFX_ByteStringC PDF_FindFullName(const PDF_AbbrPairs* table, | |
| 90 size_t count, | |
| 91 const CFX_ByteStringC& abbr) { | |
| 92 for (size_t i = 0; i < count; ++i) { | |
| 93 if (abbr.GetLength() != table[i].abbr.m_Size) | |
| 94 continue; | |
| 95 if (memcmp(abbr.GetPtr(), table[i].abbr.m_Ptr, abbr.GetLength())) | |
| 96 continue; | |
| 97 return CFX_ByteStringC(table[i].full_name.m_Ptr, table[i].full_name.m_Size); | |
| 98 } | |
| 99 return CFX_ByteStringC(); | |
| 100 } | |
| 101 | |
| 102 } // namespace | |
| 103 | |
| 104 bool IsPathOperator(const uint8_t* buf, size_t len) { | |
| 105 if (len == 1) { | |
| 106 uint8_t op = buf[0]; | |
| 107 if (op == kPathOperatorSubpath || op == kPathOperatorLine || | |
| 108 op == kPathOperatorCubicBezier1 || op == kPathOperatorCubicBezier2 || | |
| 109 op == kPathOperatorCubicBezier3) { | |
| 110 return true; | |
| 111 } | |
| 112 } else if (len == 2) { | |
| 113 if (buf[0] == kPathOperatorRectangle[0] && | |
| 114 buf[1] == kPathOperatorRectangle[1]) { | |
| 115 return true; | |
| 116 } | |
| 117 } | |
| 118 return false; | |
| 119 } | |
| 120 | |
| 121 CPDF_StreamContentParser::CPDF_StreamContentParser( | |
| 122 CPDF_Document* pDocument, | |
| 123 CPDF_Dictionary* pPageResources, | |
| 124 CPDF_Dictionary* pParentResources, | |
| 125 CFX_Matrix* pmtContentToUser, | |
| 126 CPDF_PageObjectHolder* pObjHolder, | |
| 127 CPDF_Dictionary* pResources, | |
| 128 CFX_FloatRect* pBBox, | |
| 129 CPDF_ParseOptions* pOptions, | |
| 130 CPDF_AllStates* pStates, | |
| 131 int level) | |
| 132 : m_pDocument(pDocument), | |
| 133 m_pPageResources(pPageResources), | |
| 134 m_pParentResources(pParentResources), | |
| 135 m_pResources(pResources), | |
| 136 m_pObjectHolder(pObjHolder), | |
| 137 m_Level(level), | |
| 138 m_ParamStartPos(0), | |
| 139 m_ParamCount(0), | |
| 140 m_pCurStates(new CPDF_AllStates), | |
| 141 m_pLastTextObject(nullptr), | |
| 142 m_DefFontSize(0), | |
| 143 m_pPathPoints(nullptr), | |
| 144 m_PathPointCount(0), | |
| 145 m_PathAllocSize(0), | |
| 146 m_PathCurrentX(0.0f), | |
| 147 m_PathCurrentY(0.0f), | |
| 148 m_PathClipType(0), | |
| 149 m_pLastImage(nullptr), | |
| 150 m_pLastImageDict(nullptr), | |
| 151 m_pLastCloneImageDict(nullptr), | |
| 152 m_bReleaseLastDict(TRUE), | |
| 153 m_bColored(FALSE), | |
| 154 m_bResourceMissing(FALSE) { | |
| 155 if (pmtContentToUser) { | |
| 156 m_mtContentToUser = *pmtContentToUser; | |
| 157 } | |
| 158 if (pOptions) { | |
| 159 m_Options = *pOptions; | |
| 160 } | |
| 161 if (!m_pResources) { | |
| 162 m_pResources = m_pParentResources; | |
| 163 } | |
| 164 if (!m_pResources) { | |
| 165 m_pResources = m_pPageResources; | |
| 166 } | |
| 167 if (pBBox) { | |
| 168 m_BBox = *pBBox; | |
| 169 } | |
| 170 if (pStates) { | |
| 171 m_pCurStates->Copy(*pStates); | |
| 172 } else { | |
| 173 m_pCurStates->m_GeneralState.New(); | |
| 174 m_pCurStates->m_GraphState.New(); | |
| 175 m_pCurStates->m_TextState.New(); | |
| 176 m_pCurStates->m_ColorState.New(); | |
| 177 } | |
| 178 for (size_t i = 0; i < FX_ArraySize(m_Type3Data); ++i) { | |
| 179 m_Type3Data[i] = 0.0; | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 CPDF_StreamContentParser::~CPDF_StreamContentParser() { | |
| 184 ClearAllParams(); | |
| 185 FX_Free(m_pPathPoints); | |
| 186 if (m_pLastImageDict) { | |
| 187 m_pLastImageDict->Release(); | |
| 188 } | |
| 189 if (m_pLastCloneImageDict) { | |
| 190 m_pLastCloneImageDict->Release(); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 int CPDF_StreamContentParser::GetNextParamPos() { | |
| 195 if (m_ParamCount == PARAM_BUF_SIZE) { | |
| 196 m_ParamStartPos++; | |
| 197 if (m_ParamStartPos == PARAM_BUF_SIZE) { | |
| 198 m_ParamStartPos = 0; | |
| 199 } | |
| 200 if (m_ParamBuf[m_ParamStartPos].m_Type == 0) { | |
| 201 if (CPDF_Object* pObject = m_ParamBuf[m_ParamStartPos].m_pObject) | |
| 202 pObject->Release(); | |
| 203 } | |
| 204 return m_ParamStartPos; | |
| 205 } | |
| 206 int index = m_ParamStartPos + m_ParamCount; | |
| 207 if (index >= PARAM_BUF_SIZE) { | |
| 208 index -= PARAM_BUF_SIZE; | |
| 209 } | |
| 210 m_ParamCount++; | |
| 211 return index; | |
| 212 } | |
| 213 | |
| 214 void CPDF_StreamContentParser::AddNameParam(const FX_CHAR* name, int len) { | |
| 215 int index = GetNextParamPos(); | |
| 216 if (len > 32) { | |
| 217 m_ParamBuf[index].m_Type = ContentParam::OBJECT; | |
| 218 m_ParamBuf[index].m_pObject = | |
| 219 new CPDF_Name(PDF_NameDecode(CFX_ByteStringC(name, len))); | |
| 220 } else { | |
| 221 m_ParamBuf[index].m_Type = ContentParam::NAME; | |
| 222 if (!FXSYS_memchr(name, '#', len)) { | |
| 223 FXSYS_memcpy(m_ParamBuf[index].m_Name.m_Buffer, name, len); | |
| 224 m_ParamBuf[index].m_Name.m_Len = len; | |
| 225 } else { | |
| 226 CFX_ByteString str = PDF_NameDecode(CFX_ByteStringC(name, len)); | |
| 227 FXSYS_memcpy(m_ParamBuf[index].m_Name.m_Buffer, str.c_str(), | |
| 228 str.GetLength()); | |
| 229 m_ParamBuf[index].m_Name.m_Len = str.GetLength(); | |
| 230 } | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 void CPDF_StreamContentParser::AddNumberParam(const FX_CHAR* str, int len) { | |
| 235 int index = GetNextParamPos(); | |
| 236 m_ParamBuf[index].m_Type = ContentParam::NUMBER; | |
| 237 FX_atonum(CFX_ByteStringC(str, len), m_ParamBuf[index].m_Number.m_bInteger, | |
| 238 &m_ParamBuf[index].m_Number.m_Integer); | |
| 239 } | |
| 240 void CPDF_StreamContentParser::AddObjectParam(CPDF_Object* pObj) { | |
| 241 int index = GetNextParamPos(); | |
| 242 m_ParamBuf[index].m_Type = ContentParam::OBJECT; | |
| 243 m_ParamBuf[index].m_pObject = pObj; | |
| 244 } | |
| 245 void CPDF_StreamContentParser::ClearAllParams() { | |
| 246 FX_DWORD index = m_ParamStartPos; | |
| 247 for (FX_DWORD i = 0; i < m_ParamCount; i++) { | |
| 248 if (m_ParamBuf[index].m_Type == 0) { | |
| 249 if (CPDF_Object* pObject = m_ParamBuf[index].m_pObject) | |
| 250 pObject->Release(); | |
| 251 } | |
| 252 index++; | |
| 253 if (index == PARAM_BUF_SIZE) { | |
| 254 index = 0; | |
| 255 } | |
| 256 } | |
| 257 m_ParamStartPos = 0; | |
| 258 m_ParamCount = 0; | |
| 259 } | |
| 260 | |
| 261 CPDF_Object* CPDF_StreamContentParser::GetObject(FX_DWORD index) { | |
| 262 if (index >= m_ParamCount) { | |
| 263 return NULL; | |
| 264 } | |
| 265 int real_index = m_ParamStartPos + m_ParamCount - index - 1; | |
| 266 if (real_index >= PARAM_BUF_SIZE) { | |
| 267 real_index -= PARAM_BUF_SIZE; | |
| 268 } | |
| 269 ContentParam& param = m_ParamBuf[real_index]; | |
| 270 if (param.m_Type == ContentParam::NUMBER) { | |
| 271 CPDF_Number* pNumber = param.m_Number.m_bInteger | |
| 272 ? new CPDF_Number(param.m_Number.m_Integer) | |
| 273 : new CPDF_Number(param.m_Number.m_Float); | |
| 274 | |
| 275 param.m_Type = ContentParam::OBJECT; | |
| 276 param.m_pObject = pNumber; | |
| 277 return pNumber; | |
| 278 } | |
| 279 if (param.m_Type == ContentParam::NAME) { | |
| 280 CPDF_Name* pName = new CPDF_Name( | |
| 281 CFX_ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len)); | |
| 282 param.m_Type = ContentParam::OBJECT; | |
| 283 param.m_pObject = pName; | |
| 284 return pName; | |
| 285 } | |
| 286 if (param.m_Type == ContentParam::OBJECT) { | |
| 287 return param.m_pObject; | |
| 288 } | |
| 289 ASSERT(FALSE); | |
| 290 return NULL; | |
| 291 } | |
| 292 | |
| 293 CFX_ByteString CPDF_StreamContentParser::GetString(FX_DWORD index) { | |
| 294 if (index >= m_ParamCount) { | |
| 295 return CFX_ByteString(); | |
| 296 } | |
| 297 int real_index = m_ParamStartPos + m_ParamCount - index - 1; | |
| 298 if (real_index >= PARAM_BUF_SIZE) { | |
| 299 real_index -= PARAM_BUF_SIZE; | |
| 300 } | |
| 301 ContentParam& param = m_ParamBuf[real_index]; | |
| 302 if (param.m_Type == ContentParam::NAME) { | |
| 303 return CFX_ByteString(param.m_Name.m_Buffer, param.m_Name.m_Len); | |
| 304 } | |
| 305 if (param.m_Type == 0 && param.m_pObject) { | |
| 306 return param.m_pObject->GetString(); | |
| 307 } | |
| 308 return CFX_ByteString(); | |
| 309 } | |
| 310 | |
| 311 FX_FLOAT CPDF_StreamContentParser::GetNumber(FX_DWORD index) { | |
| 312 if (index >= m_ParamCount) { | |
| 313 return 0; | |
| 314 } | |
| 315 int real_index = m_ParamStartPos + m_ParamCount - index - 1; | |
| 316 if (real_index >= PARAM_BUF_SIZE) { | |
| 317 real_index -= PARAM_BUF_SIZE; | |
| 318 } | |
| 319 ContentParam& param = m_ParamBuf[real_index]; | |
| 320 if (param.m_Type == ContentParam::NUMBER) { | |
| 321 return param.m_Number.m_bInteger ? (FX_FLOAT)param.m_Number.m_Integer | |
| 322 : param.m_Number.m_Float; | |
| 323 } | |
| 324 if (param.m_Type == 0 && param.m_pObject) { | |
| 325 return param.m_pObject->GetNumber(); | |
| 326 } | |
| 327 return 0; | |
| 328 } | |
| 329 | |
| 330 FX_FLOAT CPDF_StreamContentParser::GetNumber16(FX_DWORD index) { | |
| 331 return GetNumber(index); | |
| 332 } | |
| 333 | |
| 334 void CPDF_StreamContentParser::SetGraphicStates(CPDF_PageObject* pObj, | |
| 335 FX_BOOL bColor, | |
| 336 FX_BOOL bText, | |
| 337 FX_BOOL bGraph) { | |
| 338 pObj->m_GeneralState = m_pCurStates->m_GeneralState; | |
| 339 pObj->m_ClipPath = m_pCurStates->m_ClipPath; | |
| 340 pObj->m_ContentMark = m_CurContentMark; | |
| 341 if (bColor) { | |
| 342 pObj->m_ColorState = m_pCurStates->m_ColorState; | |
| 343 } | |
| 344 if (bGraph) { | |
| 345 pObj->m_GraphState = m_pCurStates->m_GraphState; | |
| 346 } | |
| 347 if (bText) { | |
| 348 pObj->m_TextState = m_pCurStates->m_TextState; | |
| 349 } | |
| 350 } | |
| 351 | |
| 352 // static | |
| 353 CPDF_StreamContentParser::OpCodes | |
| 354 CPDF_StreamContentParser::InitializeOpCodes() { | |
| 355 return OpCodes({ | |
| 356 {FXBSTR_ID('"', 0, 0, 0), | |
| 357 &CPDF_StreamContentParser::Handle_NextLineShowText_Space}, | |
| 358 {FXBSTR_ID('\'', 0, 0, 0), | |
| 359 &CPDF_StreamContentParser::Handle_NextLineShowText}, | |
| 360 {FXBSTR_ID('B', 0, 0, 0), | |
| 361 &CPDF_StreamContentParser::Handle_FillStrokePath}, | |
| 362 {FXBSTR_ID('B', '*', 0, 0), | |
| 363 &CPDF_StreamContentParser::Handle_EOFillStrokePath}, | |
| 364 {FXBSTR_ID('B', 'D', 'C', 0), | |
| 365 &CPDF_StreamContentParser::Handle_BeginMarkedContent_Dictionary}, | |
| 366 {FXBSTR_ID('B', 'I', 0, 0), &CPDF_StreamContentParser::Handle_BeginImage}, | |
| 367 {FXBSTR_ID('B', 'M', 'C', 0), | |
| 368 &CPDF_StreamContentParser::Handle_BeginMarkedContent}, | |
| 369 {FXBSTR_ID('B', 'T', 0, 0), &CPDF_StreamContentParser::Handle_BeginText}, | |
| 370 {FXBSTR_ID('C', 'S', 0, 0), | |
| 371 &CPDF_StreamContentParser::Handle_SetColorSpace_Stroke}, | |
| 372 {FXBSTR_ID('D', 'P', 0, 0), | |
| 373 &CPDF_StreamContentParser::Handle_MarkPlace_Dictionary}, | |
| 374 {FXBSTR_ID('D', 'o', 0, 0), | |
| 375 &CPDF_StreamContentParser::Handle_ExecuteXObject}, | |
| 376 {FXBSTR_ID('E', 'I', 0, 0), &CPDF_StreamContentParser::Handle_EndImage}, | |
| 377 {FXBSTR_ID('E', 'M', 'C', 0), | |
| 378 &CPDF_StreamContentParser::Handle_EndMarkedContent}, | |
| 379 {FXBSTR_ID('E', 'T', 0, 0), &CPDF_StreamContentParser::Handle_EndText}, | |
| 380 {FXBSTR_ID('F', 0, 0, 0), &CPDF_StreamContentParser::Handle_FillPathOld}, | |
| 381 {FXBSTR_ID('G', 0, 0, 0), | |
| 382 &CPDF_StreamContentParser::Handle_SetGray_Stroke}, | |
| 383 {FXBSTR_ID('I', 'D', 0, 0), | |
| 384 &CPDF_StreamContentParser::Handle_BeginImageData}, | |
| 385 {FXBSTR_ID('J', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetLineCap}, | |
| 386 {FXBSTR_ID('K', 0, 0, 0), | |
| 387 &CPDF_StreamContentParser::Handle_SetCMYKColor_Stroke}, | |
| 388 {FXBSTR_ID('M', 0, 0, 0), | |
| 389 &CPDF_StreamContentParser::Handle_SetMiterLimit}, | |
| 390 {FXBSTR_ID('M', 'P', 0, 0), &CPDF_StreamContentParser::Handle_MarkPlace}, | |
| 391 {FXBSTR_ID('Q', 0, 0, 0), | |
| 392 &CPDF_StreamContentParser::Handle_RestoreGraphState}, | |
| 393 {FXBSTR_ID('R', 'G', 0, 0), | |
| 394 &CPDF_StreamContentParser::Handle_SetRGBColor_Stroke}, | |
| 395 {FXBSTR_ID('S', 0, 0, 0), &CPDF_StreamContentParser::Handle_StrokePath}, | |
| 396 {FXBSTR_ID('S', 'C', 0, 0), | |
| 397 &CPDF_StreamContentParser::Handle_SetColor_Stroke}, | |
| 398 {FXBSTR_ID('S', 'C', 'N', 0), | |
| 399 &CPDF_StreamContentParser::Handle_SetColorPS_Stroke}, | |
| 400 {FXBSTR_ID('T', '*', 0, 0), | |
| 401 &CPDF_StreamContentParser::Handle_MoveToNextLine}, | |
| 402 {FXBSTR_ID('T', 'D', 0, 0), | |
| 403 &CPDF_StreamContentParser::Handle_MoveTextPoint_SetLeading}, | |
| 404 {FXBSTR_ID('T', 'J', 0, 0), | |
| 405 &CPDF_StreamContentParser::Handle_ShowText_Positioning}, | |
| 406 {FXBSTR_ID('T', 'L', 0, 0), | |
| 407 &CPDF_StreamContentParser::Handle_SetTextLeading}, | |
| 408 {FXBSTR_ID('T', 'c', 0, 0), | |
| 409 &CPDF_StreamContentParser::Handle_SetCharSpace}, | |
| 410 {FXBSTR_ID('T', 'd', 0, 0), | |
| 411 &CPDF_StreamContentParser::Handle_MoveTextPoint}, | |
| 412 {FXBSTR_ID('T', 'f', 0, 0), &CPDF_StreamContentParser::Handle_SetFont}, | |
| 413 {FXBSTR_ID('T', 'j', 0, 0), &CPDF_StreamContentParser::Handle_ShowText}, | |
| 414 {FXBSTR_ID('T', 'm', 0, 0), | |
| 415 &CPDF_StreamContentParser::Handle_SetTextMatrix}, | |
| 416 {FXBSTR_ID('T', 'r', 0, 0), | |
| 417 &CPDF_StreamContentParser::Handle_SetTextRenderMode}, | |
| 418 {FXBSTR_ID('T', 's', 0, 0), | |
| 419 &CPDF_StreamContentParser::Handle_SetTextRise}, | |
| 420 {FXBSTR_ID('T', 'w', 0, 0), | |
| 421 &CPDF_StreamContentParser::Handle_SetWordSpace}, | |
| 422 {FXBSTR_ID('T', 'z', 0, 0), | |
| 423 &CPDF_StreamContentParser::Handle_SetHorzScale}, | |
| 424 {FXBSTR_ID('W', 0, 0, 0), &CPDF_StreamContentParser::Handle_Clip}, | |
| 425 {FXBSTR_ID('W', '*', 0, 0), &CPDF_StreamContentParser::Handle_EOClip}, | |
| 426 {FXBSTR_ID('b', 0, 0, 0), | |
| 427 &CPDF_StreamContentParser::Handle_CloseFillStrokePath}, | |
| 428 {FXBSTR_ID('b', '*', 0, 0), | |
| 429 &CPDF_StreamContentParser::Handle_CloseEOFillStrokePath}, | |
| 430 {FXBSTR_ID('c', 0, 0, 0), &CPDF_StreamContentParser::Handle_CurveTo_123}, | |
| 431 {FXBSTR_ID('c', 'm', 0, 0), | |
| 432 &CPDF_StreamContentParser::Handle_ConcatMatrix}, | |
| 433 {FXBSTR_ID('c', 's', 0, 0), | |
| 434 &CPDF_StreamContentParser::Handle_SetColorSpace_Fill}, | |
| 435 {FXBSTR_ID('d', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetDash}, | |
| 436 {FXBSTR_ID('d', '0', 0, 0), | |
| 437 &CPDF_StreamContentParser::Handle_SetCharWidth}, | |
| 438 {FXBSTR_ID('d', '1', 0, 0), | |
| 439 &CPDF_StreamContentParser::Handle_SetCachedDevice}, | |
| 440 {FXBSTR_ID('f', 0, 0, 0), &CPDF_StreamContentParser::Handle_FillPath}, | |
| 441 {FXBSTR_ID('f', '*', 0, 0), &CPDF_StreamContentParser::Handle_EOFillPath}, | |
| 442 {FXBSTR_ID('g', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetGray_Fill}, | |
| 443 {FXBSTR_ID('g', 's', 0, 0), | |
| 444 &CPDF_StreamContentParser::Handle_SetExtendGraphState}, | |
| 445 {FXBSTR_ID('h', 0, 0, 0), &CPDF_StreamContentParser::Handle_ClosePath}, | |
| 446 {FXBSTR_ID('i', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetFlat}, | |
| 447 {FXBSTR_ID('j', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetLineJoin}, | |
| 448 {FXBSTR_ID('k', 0, 0, 0), | |
| 449 &CPDF_StreamContentParser::Handle_SetCMYKColor_Fill}, | |
| 450 {FXBSTR_ID('l', 0, 0, 0), &CPDF_StreamContentParser::Handle_LineTo}, | |
| 451 {FXBSTR_ID('m', 0, 0, 0), &CPDF_StreamContentParser::Handle_MoveTo}, | |
| 452 {FXBSTR_ID('n', 0, 0, 0), &CPDF_StreamContentParser::Handle_EndPath}, | |
| 453 {FXBSTR_ID('q', 0, 0, 0), | |
| 454 &CPDF_StreamContentParser::Handle_SaveGraphState}, | |
| 455 {FXBSTR_ID('r', 'e', 0, 0), &CPDF_StreamContentParser::Handle_Rectangle}, | |
| 456 {FXBSTR_ID('r', 'g', 0, 0), | |
| 457 &CPDF_StreamContentParser::Handle_SetRGBColor_Fill}, | |
| 458 {FXBSTR_ID('r', 'i', 0, 0), | |
| 459 &CPDF_StreamContentParser::Handle_SetRenderIntent}, | |
| 460 {FXBSTR_ID('s', 0, 0, 0), | |
| 461 &CPDF_StreamContentParser::Handle_CloseStrokePath}, | |
| 462 {FXBSTR_ID('s', 'c', 0, 0), | |
| 463 &CPDF_StreamContentParser::Handle_SetColor_Fill}, | |
| 464 {FXBSTR_ID('s', 'c', 'n', 0), | |
| 465 &CPDF_StreamContentParser::Handle_SetColorPS_Fill}, | |
| 466 {FXBSTR_ID('s', 'h', 0, 0), &CPDF_StreamContentParser::Handle_ShadeFill}, | |
| 467 {FXBSTR_ID('v', 0, 0, 0), &CPDF_StreamContentParser::Handle_CurveTo_23}, | |
| 468 {FXBSTR_ID('w', 0, 0, 0), &CPDF_StreamContentParser::Handle_SetLineWidth}, | |
| 469 {FXBSTR_ID('y', 0, 0, 0), &CPDF_StreamContentParser::Handle_CurveTo_13}, | |
| 470 }); | |
| 471 } | |
| 472 | |
| 473 void CPDF_StreamContentParser::OnOperator(const FX_CHAR* op) { | |
| 474 int i = 0; | |
| 475 FX_DWORD opid = 0; | |
| 476 while (i < 4 && op[i]) { | |
| 477 opid = (opid << 8) + op[i]; | |
| 478 i++; | |
| 479 } | |
| 480 while (i < 4) { | |
| 481 opid <<= 8; | |
| 482 i++; | |
| 483 } | |
| 484 | |
| 485 static const OpCodes s_OpCodes = InitializeOpCodes(); | |
| 486 | |
| 487 auto it = s_OpCodes.find(opid); | |
| 488 if (it != s_OpCodes.end()) | |
| 489 (this->*it->second)(); | |
| 490 } | |
| 491 | |
| 492 void CPDF_StreamContentParser::Handle_CloseFillStrokePath() { | |
| 493 if (m_Options.m_bTextOnly) { | |
| 494 return; | |
| 495 } | |
| 496 Handle_ClosePath(); | |
| 497 AddPathObject(FXFILL_WINDING, TRUE); | |
| 498 } | |
| 499 | |
| 500 void CPDF_StreamContentParser::Handle_FillStrokePath() { | |
| 501 if (m_Options.m_bTextOnly) { | |
| 502 return; | |
| 503 } | |
| 504 AddPathObject(FXFILL_WINDING, TRUE); | |
| 505 } | |
| 506 | |
| 507 void CPDF_StreamContentParser::Handle_CloseEOFillStrokePath() { | |
| 508 if (m_Options.m_bTextOnly) { | |
| 509 return; | |
| 510 } | |
| 511 AddPathPoint(m_PathStartX, m_PathStartY, FXPT_LINETO | FXPT_CLOSEFIGURE); | |
| 512 AddPathObject(FXFILL_ALTERNATE, TRUE); | |
| 513 } | |
| 514 | |
| 515 void CPDF_StreamContentParser::Handle_EOFillStrokePath() { | |
| 516 if (m_Options.m_bTextOnly) { | |
| 517 return; | |
| 518 } | |
| 519 AddPathObject(FXFILL_ALTERNATE, TRUE); | |
| 520 } | |
| 521 | |
| 522 void CPDF_StreamContentParser::Handle_BeginMarkedContent_Dictionary() { | |
| 523 if (!m_Options.m_bMarkedContent) { | |
| 524 return; | |
| 525 } | |
| 526 CFX_ByteString tag = GetString(1); | |
| 527 CPDF_Object* pProperty = GetObject(0); | |
| 528 if (!pProperty) { | |
| 529 return; | |
| 530 } | |
| 531 FX_BOOL bDirect = TRUE; | |
| 532 if (pProperty->IsName()) { | |
| 533 pProperty = FindResourceObj("Properties", pProperty->GetString()); | |
| 534 if (!pProperty) | |
| 535 return; | |
| 536 bDirect = FALSE; | |
| 537 } | |
| 538 if (CPDF_Dictionary* pDict = pProperty->AsDictionary()) { | |
| 539 m_CurContentMark.GetModify()->AddMark(tag, pDict, bDirect); | |
| 540 } | |
| 541 } | |
| 542 | |
| 543 void CPDF_StreamContentParser::Handle_BeginImage() { | |
| 544 FX_FILESIZE savePos = m_pSyntax->GetPos(); | |
| 545 CPDF_Dictionary* pDict = new CPDF_Dictionary; | |
| 546 while (1) { | |
| 547 CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement(); | |
| 548 if (type == CPDF_StreamParser::Keyword) { | |
| 549 CFX_ByteString bsKeyword(m_pSyntax->GetWordBuf(), | |
| 550 m_pSyntax->GetWordSize()); | |
| 551 if (bsKeyword != "ID") { | |
| 552 m_pSyntax->SetPos(savePos); | |
| 553 pDict->Release(); | |
| 554 return; | |
| 555 } | |
| 556 } | |
| 557 if (type != CPDF_StreamParser::Name) { | |
| 558 break; | |
| 559 } | |
| 560 CFX_ByteString key((const FX_CHAR*)m_pSyntax->GetWordBuf() + 1, | |
| 561 m_pSyntax->GetWordSize() - 1); | |
| 562 std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pObj( | |
| 563 m_pSyntax->ReadNextObject()); | |
| 564 if (!key.IsEmpty()) { | |
| 565 FX_DWORD dwObjNum = pObj ? pObj->GetObjNum() : 0; | |
| 566 if (dwObjNum) | |
| 567 pDict->SetAtReference(key, m_pDocument, dwObjNum); | |
| 568 else | |
| 569 pDict->SetAt(key, pObj.release()); | |
| 570 } | |
| 571 } | |
| 572 PDF_ReplaceAbbr(pDict); | |
| 573 CPDF_Object* pCSObj = NULL; | |
| 574 if (pDict->KeyExist("ColorSpace")) { | |
| 575 pCSObj = pDict->GetElementValue("ColorSpace"); | |
| 576 if (pCSObj->IsName()) { | |
| 577 CFX_ByteString name = pCSObj->GetString(); | |
| 578 if (name != "DeviceRGB" && name != "DeviceGray" && name != "DeviceCMYK") { | |
| 579 pCSObj = FindResourceObj("ColorSpace", name); | |
| 580 if (pCSObj && !pCSObj->GetObjNum()) { | |
| 581 pCSObj = pCSObj->Clone(); | |
| 582 pDict->SetAt("ColorSpace", pCSObj); | |
| 583 } | |
| 584 } | |
| 585 } | |
| 586 } | |
| 587 CPDF_Stream* pStream = m_pSyntax->ReadInlineStream( | |
| 588 m_pDocument, pDict, pCSObj, m_Options.m_bDecodeInlineImage); | |
| 589 while (1) { | |
| 590 CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement(); | |
| 591 if (type == CPDF_StreamParser::EndOfData) { | |
| 592 break; | |
| 593 } | |
| 594 if (type != CPDF_StreamParser::Keyword) { | |
| 595 continue; | |
| 596 } | |
| 597 if (m_pSyntax->GetWordSize() == 2 && m_pSyntax->GetWordBuf()[0] == 'E' && | |
| 598 m_pSyntax->GetWordBuf()[1] == 'I') { | |
| 599 break; | |
| 600 } | |
| 601 } | |
| 602 if (m_Options.m_bTextOnly) { | |
| 603 if (pStream) { | |
| 604 pStream->Release(); | |
| 605 } else { | |
| 606 pDict->Release(); | |
| 607 } | |
| 608 return; | |
| 609 } | |
| 610 pDict->SetAtName("Subtype", "Image"); | |
| 611 CPDF_ImageObject* pImgObj = AddImage(pStream, NULL, TRUE); | |
| 612 if (!pImgObj) { | |
| 613 if (pStream) { | |
| 614 pStream->Release(); | |
| 615 } else { | |
| 616 pDict->Release(); | |
| 617 } | |
| 618 } | |
| 619 } | |
| 620 | |
| 621 void CPDF_StreamContentParser::Handle_BeginMarkedContent() { | |
| 622 if (!m_Options.m_bMarkedContent) { | |
| 623 return; | |
| 624 } | |
| 625 CFX_ByteString tag = GetString(0); | |
| 626 m_CurContentMark.GetModify()->AddMark(tag, NULL, FALSE); | |
| 627 } | |
| 628 | |
| 629 void CPDF_StreamContentParser::Handle_BeginText() { | |
| 630 m_pCurStates->m_TextMatrix.Set(1.0f, 0, 0, 1.0f, 0, 0); | |
| 631 OnChangeTextMatrix(); | |
| 632 m_pCurStates->m_TextX = 0; | |
| 633 m_pCurStates->m_TextY = 0; | |
| 634 m_pCurStates->m_TextLineX = 0; | |
| 635 m_pCurStates->m_TextLineY = 0; | |
| 636 } | |
| 637 | |
| 638 void CPDF_StreamContentParser::Handle_CurveTo_123() { | |
| 639 if (m_Options.m_bTextOnly) { | |
| 640 return; | |
| 641 } | |
| 642 AddPathPoint(GetNumber(5), GetNumber(4), FXPT_BEZIERTO); | |
| 643 AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO); | |
| 644 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO); | |
| 645 } | |
| 646 | |
| 647 void CPDF_StreamContentParser::Handle_ConcatMatrix() { | |
| 648 FX_FLOAT a2 = GetNumber16(5), b2 = GetNumber16(4), c2 = GetNumber16(3), | |
| 649 d2 = GetNumber16(2); | |
| 650 FX_FLOAT e2 = GetNumber(1), f2 = GetNumber(0); | |
| 651 CFX_Matrix new_matrix(a2, b2, c2, d2, e2, f2); | |
| 652 new_matrix.Concat(m_pCurStates->m_CTM); | |
| 653 m_pCurStates->m_CTM = new_matrix; | |
| 654 OnChangeTextMatrix(); | |
| 655 } | |
| 656 | |
| 657 void CPDF_StreamContentParser::Handle_SetColorSpace_Fill() { | |
| 658 if (m_Options.m_bTextOnly) { | |
| 659 return; | |
| 660 } | |
| 661 CFX_ByteString csname = GetString(0); | |
| 662 CPDF_ColorSpace* pCS = FindColorSpace(csname); | |
| 663 if (!pCS) { | |
| 664 return; | |
| 665 } | |
| 666 m_pCurStates->m_ColorState.GetModify()->m_FillColor.SetColorSpace(pCS); | |
| 667 } | |
| 668 | |
| 669 void CPDF_StreamContentParser::Handle_SetColorSpace_Stroke() { | |
| 670 if (m_Options.m_bTextOnly) { | |
| 671 return; | |
| 672 } | |
| 673 CFX_ByteString csname = GetString(0); | |
| 674 CPDF_ColorSpace* pCS = FindColorSpace(csname); | |
| 675 if (!pCS) { | |
| 676 return; | |
| 677 } | |
| 678 m_pCurStates->m_ColorState.GetModify()->m_StrokeColor.SetColorSpace(pCS); | |
| 679 } | |
| 680 | |
| 681 void CPDF_StreamContentParser::Handle_SetDash() { | |
| 682 if (m_Options.m_bTextOnly) { | |
| 683 return; | |
| 684 } | |
| 685 CPDF_Array* pArray = GetObject(1) ? GetObject(1)->GetArray() : NULL; | |
| 686 if (!pArray) { | |
| 687 return; | |
| 688 } | |
| 689 m_pCurStates->SetLineDash(pArray, GetNumber(0), 1.0f); | |
| 690 } | |
| 691 | |
| 692 void CPDF_StreamContentParser::Handle_SetCharWidth() { | |
| 693 m_Type3Data[0] = GetNumber(1); | |
| 694 m_Type3Data[1] = GetNumber(0); | |
| 695 m_bColored = TRUE; | |
| 696 } | |
| 697 | |
| 698 void CPDF_StreamContentParser::Handle_SetCachedDevice() { | |
| 699 for (int i = 0; i < 6; i++) { | |
| 700 m_Type3Data[i] = GetNumber(5 - i); | |
| 701 } | |
| 702 m_bColored = FALSE; | |
| 703 } | |
| 704 | |
| 705 void CPDF_StreamContentParser::Handle_ExecuteXObject() { | |
| 706 CFX_ByteString name = GetString(0); | |
| 707 if (name == m_LastImageName && m_pLastImage && m_pLastImage->GetStream() && | |
| 708 m_pLastImage->GetStream()->GetObjNum()) { | |
| 709 AddImage(nullptr, m_pLastImage, FALSE); | |
| 710 return; | |
| 711 } | |
| 712 | |
| 713 if (m_Options.m_bTextOnly) { | |
| 714 if (!m_pResources) | |
| 715 return; | |
| 716 | |
| 717 CPDF_Dictionary* pList = m_pResources->GetDictBy("XObject"); | |
| 718 if (!pList && m_pPageResources && m_pResources != m_pPageResources) | |
| 719 pList = m_pPageResources->GetDictBy("XObject"); | |
| 720 if (!pList) | |
| 721 return; | |
| 722 CPDF_Reference* pRes = ToReference(pList->GetElement(name)); | |
| 723 if (!pRes) | |
| 724 return; | |
| 725 | |
| 726 FX_BOOL bForm; | |
| 727 if (m_pDocument->IsFormStream(pRes->GetRefObjNum(), bForm) && !bForm) | |
| 728 return; | |
| 729 } | |
| 730 | |
| 731 CPDF_Stream* pXObject = ToStream(FindResourceObj("XObject", name)); | |
| 732 if (!pXObject) { | |
| 733 m_bResourceMissing = TRUE; | |
| 734 return; | |
| 735 } | |
| 736 | |
| 737 CFX_ByteStringC type = pXObject->GetDict() | |
| 738 ? pXObject->GetDict()->GetConstStringBy("Subtype") | |
| 739 : CFX_ByteStringC(); | |
| 740 if (type == "Image") { | |
| 741 if (m_Options.m_bTextOnly) { | |
| 742 return; | |
| 743 } | |
| 744 CPDF_ImageObject* pObj = AddImage(pXObject, NULL, FALSE); | |
| 745 m_LastImageName = name; | |
| 746 m_pLastImage = pObj->m_pImage; | |
| 747 if (!m_pObjectHolder->HasImageMask()) | |
| 748 m_pObjectHolder->SetHasImageMask(m_pLastImage->IsMask()); | |
| 749 } else if (type == "Form") { | |
| 750 AddForm(pXObject); | |
| 751 } else { | |
| 752 return; | |
| 753 } | |
| 754 } | |
| 755 | |
| 756 void CPDF_StreamContentParser::AddForm(CPDF_Stream* pStream) { | |
| 757 if (!m_Options.m_bSeparateForm) { | |
| 758 CPDF_Dictionary* pResources = pStream->GetDict()->GetDictBy("Resources"); | |
| 759 CFX_Matrix form_matrix = pStream->GetDict()->GetMatrixBy("Matrix"); | |
| 760 form_matrix.Concat(m_pCurStates->m_CTM); | |
| 761 CPDF_Array* pBBox = pStream->GetDict()->GetArrayBy("BBox"); | |
| 762 CFX_FloatRect form_bbox; | |
| 763 CPDF_Path ClipPath; | |
| 764 if (pBBox) { | |
| 765 form_bbox = pStream->GetDict()->GetRectBy("BBox"); | |
| 766 ClipPath.New(); | |
| 767 ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right, | |
| 768 form_bbox.top); | |
| 769 ClipPath.Transform(&form_matrix); | |
| 770 form_bbox.Transform(&form_matrix); | |
| 771 } | |
| 772 CPDF_StreamContentParser parser(m_pDocument, m_pPageResources, m_pResources, | |
| 773 &m_mtContentToUser, m_pObjectHolder, | |
| 774 pResources, &form_bbox, &m_Options, | |
| 775 m_pCurStates.get(), m_Level + 1); | |
| 776 parser.m_pCurStates->m_CTM = form_matrix; | |
| 777 if (ClipPath.NotNull()) { | |
| 778 parser.m_pCurStates->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING, | |
| 779 TRUE); | |
| 780 } | |
| 781 CPDF_StreamAcc stream; | |
| 782 stream.LoadAllData(pStream, FALSE); | |
| 783 if (stream.GetSize() == 0) { | |
| 784 return; | |
| 785 } | |
| 786 parser.Parse(stream.GetData(), stream.GetSize(), 0); | |
| 787 return; | |
| 788 } | |
| 789 std::unique_ptr<CPDF_FormObject> pFormObj(new CPDF_FormObject); | |
| 790 pFormObj->m_pForm = | |
| 791 new CPDF_Form(m_pDocument, m_pPageResources, pStream, m_pResources); | |
| 792 pFormObj->m_FormMatrix = m_pCurStates->m_CTM; | |
| 793 pFormObj->m_FormMatrix.Concat(m_mtContentToUser); | |
| 794 CPDF_AllStates status; | |
| 795 status.m_GeneralState = m_pCurStates->m_GeneralState; | |
| 796 status.m_GraphState = m_pCurStates->m_GraphState; | |
| 797 status.m_ColorState = m_pCurStates->m_ColorState; | |
| 798 status.m_TextState = m_pCurStates->m_TextState; | |
| 799 pFormObj->m_pForm->ParseContent(&status, NULL, NULL, &m_Options, m_Level + 1); | |
| 800 if (!m_pObjectHolder->BackgroundAlphaNeeded() && | |
| 801 pFormObj->m_pForm->BackgroundAlphaNeeded()) { | |
| 802 m_pObjectHolder->SetBackgroundAlphaNeeded(TRUE); | |
| 803 } | |
| 804 pFormObj->CalcBoundingBox(); | |
| 805 SetGraphicStates(pFormObj.get(), TRUE, TRUE, TRUE); | |
| 806 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pFormObj)); | |
| 807 } | |
| 808 | |
| 809 CPDF_ImageObject* CPDF_StreamContentParser::AddImage(CPDF_Stream* pStream, | |
| 810 CPDF_Image* pImage, | |
| 811 FX_BOOL bInline) { | |
| 812 if (!pStream && !pImage) { | |
| 813 return NULL; | |
| 814 } | |
| 815 CFX_Matrix ImageMatrix; | |
| 816 ImageMatrix.Copy(m_pCurStates->m_CTM); | |
| 817 ImageMatrix.Concat(m_mtContentToUser); | |
| 818 | |
| 819 std::unique_ptr<CPDF_ImageObject> pImageObj(new CPDF_ImageObject); | |
| 820 if (pImage) { | |
| 821 pImageObj->m_pImage = | |
| 822 m_pDocument->GetPageData()->GetImage(pImage->GetStream()); | |
| 823 } else if (pStream->GetObjNum()) { | |
| 824 pImageObj->m_pImage = m_pDocument->LoadImageF(pStream); | |
| 825 } else { | |
| 826 pImageObj->m_pImage = new CPDF_Image(m_pDocument); | |
| 827 pImageObj->m_pImage->LoadImageF(pStream, bInline); | |
| 828 } | |
| 829 SetGraphicStates(pImageObj.get(), pImageObj->m_pImage->IsMask(), FALSE, | |
| 830 FALSE); | |
| 831 pImageObj->m_Matrix = ImageMatrix; | |
| 832 pImageObj->CalcBoundingBox(); | |
| 833 CPDF_ImageObject* pRet = pImageObj.get(); | |
| 834 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pImageObj)); | |
| 835 return pRet; | |
| 836 } | |
| 837 | |
| 838 void CPDF_StreamContentParser::Handle_MarkPlace_Dictionary() {} | |
| 839 | |
| 840 void CPDF_StreamContentParser::Handle_EndImage() {} | |
| 841 | |
| 842 void CPDF_StreamContentParser::Handle_EndMarkedContent() { | |
| 843 if (!m_Options.m_bMarkedContent) { | |
| 844 return; | |
| 845 } | |
| 846 if (m_CurContentMark.IsNull()) { | |
| 847 return; | |
| 848 } | |
| 849 int count = m_CurContentMark.GetObject()->CountItems(); | |
| 850 if (count == 1) { | |
| 851 m_CurContentMark.SetNull(); | |
| 852 return; | |
| 853 } | |
| 854 m_CurContentMark.GetModify()->DeleteLastMark(); | |
| 855 } | |
| 856 | |
| 857 void CPDF_StreamContentParser::Handle_EndText() { | |
| 858 int count = m_ClipTextList.GetSize(); | |
| 859 if (count == 0) { | |
| 860 return; | |
| 861 } | |
| 862 if (m_pCurStates->m_TextState.GetObject()->m_TextMode < 4) { | |
| 863 for (int i = 0; i < count; i++) { | |
| 864 delete m_ClipTextList.GetAt(i); | |
| 865 } | |
| 866 } else { | |
| 867 m_pCurStates->m_ClipPath.AppendTexts(m_ClipTextList.GetData(), count); | |
| 868 } | |
| 869 m_ClipTextList.RemoveAll(); | |
| 870 } | |
| 871 | |
| 872 void CPDF_StreamContentParser::Handle_FillPath() { | |
| 873 if (m_Options.m_bTextOnly) { | |
| 874 return; | |
| 875 } | |
| 876 AddPathObject(FXFILL_WINDING, FALSE); | |
| 877 } | |
| 878 | |
| 879 void CPDF_StreamContentParser::Handle_FillPathOld() { | |
| 880 if (m_Options.m_bTextOnly) { | |
| 881 return; | |
| 882 } | |
| 883 AddPathObject(FXFILL_WINDING, FALSE); | |
| 884 } | |
| 885 | |
| 886 void CPDF_StreamContentParser::Handle_EOFillPath() { | |
| 887 if (m_Options.m_bTextOnly) { | |
| 888 return; | |
| 889 } | |
| 890 AddPathObject(FXFILL_ALTERNATE, FALSE); | |
| 891 } | |
| 892 | |
| 893 void CPDF_StreamContentParser::Handle_SetGray_Fill() { | |
| 894 FX_FLOAT value = GetNumber(0); | |
| 895 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); | |
| 896 m_pCurStates->m_ColorState.SetFillColor(pCS, &value, 1); | |
| 897 } | |
| 898 | |
| 899 void CPDF_StreamContentParser::Handle_SetGray_Stroke() { | |
| 900 FX_FLOAT value = GetNumber(0); | |
| 901 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); | |
| 902 m_pCurStates->m_ColorState.SetStrokeColor(pCS, &value, 1); | |
| 903 } | |
| 904 | |
| 905 void CPDF_StreamContentParser::Handle_SetExtendGraphState() { | |
| 906 CFX_ByteString name = GetString(0); | |
| 907 CPDF_Dictionary* pGS = ToDictionary(FindResourceObj("ExtGState", name)); | |
| 908 if (!pGS) { | |
| 909 m_bResourceMissing = TRUE; | |
| 910 return; | |
| 911 } | |
| 912 m_pCurStates->ProcessExtGS(pGS, this); | |
| 913 } | |
| 914 | |
| 915 void CPDF_StreamContentParser::Handle_ClosePath() { | |
| 916 if (m_Options.m_bTextOnly) { | |
| 917 return; | |
| 918 } | |
| 919 if (m_PathPointCount == 0) { | |
| 920 return; | |
| 921 } | |
| 922 if (m_PathStartX != m_PathCurrentX || m_PathStartY != m_PathCurrentY) { | |
| 923 AddPathPoint(m_PathStartX, m_PathStartY, FXPT_LINETO | FXPT_CLOSEFIGURE); | |
| 924 } else if (m_pPathPoints[m_PathPointCount - 1].m_Flag != FXPT_MOVETO) { | |
| 925 m_pPathPoints[m_PathPointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; | |
| 926 } | |
| 927 } | |
| 928 | |
| 929 void CPDF_StreamContentParser::Handle_SetFlat() { | |
| 930 m_pCurStates->m_GeneralState.GetModify()->m_Flatness = GetNumber(0); | |
| 931 } | |
| 932 | |
| 933 void CPDF_StreamContentParser::Handle_BeginImageData() {} | |
| 934 | |
| 935 void CPDF_StreamContentParser::Handle_SetLineJoin() { | |
| 936 m_pCurStates->m_GraphState.GetModify()->m_LineJoin = | |
| 937 (CFX_GraphStateData::LineJoin)GetInteger(0); | |
| 938 } | |
| 939 | |
| 940 void CPDF_StreamContentParser::Handle_SetLineCap() { | |
| 941 m_pCurStates->m_GraphState.GetModify()->m_LineCap = | |
| 942 (CFX_GraphStateData::LineCap)GetInteger(0); | |
| 943 } | |
| 944 | |
| 945 void CPDF_StreamContentParser::Handle_SetCMYKColor_Fill() { | |
| 946 if (m_ParamCount != 4) | |
| 947 return; | |
| 948 | |
| 949 FX_FLOAT values[4]; | |
| 950 for (int i = 0; i < 4; i++) { | |
| 951 values[i] = GetNumber(3 - i); | |
| 952 } | |
| 953 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); | |
| 954 m_pCurStates->m_ColorState.SetFillColor(pCS, values, 4); | |
| 955 } | |
| 956 | |
| 957 void CPDF_StreamContentParser::Handle_SetCMYKColor_Stroke() { | |
| 958 if (m_ParamCount != 4) | |
| 959 return; | |
| 960 | |
| 961 FX_FLOAT values[4]; | |
| 962 for (int i = 0; i < 4; i++) { | |
| 963 values[i] = GetNumber(3 - i); | |
| 964 } | |
| 965 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); | |
| 966 m_pCurStates->m_ColorState.SetStrokeColor(pCS, values, 4); | |
| 967 } | |
| 968 | |
| 969 void CPDF_StreamContentParser::Handle_LineTo() { | |
| 970 if (m_ParamCount != 2) | |
| 971 return; | |
| 972 | |
| 973 if (m_Options.m_bTextOnly) { | |
| 974 return; | |
| 975 } | |
| 976 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_LINETO); | |
| 977 } | |
| 978 | |
| 979 void CPDF_StreamContentParser::Handle_MoveTo() { | |
| 980 if (m_ParamCount != 2) | |
| 981 return; | |
| 982 | |
| 983 if (m_Options.m_bTextOnly) { | |
| 984 m_pSyntax->SkipPathObject(); | |
| 985 return; | |
| 986 } | |
| 987 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_MOVETO); | |
| 988 ParsePathObject(); | |
| 989 } | |
| 990 | |
| 991 void CPDF_StreamContentParser::Handle_SetMiterLimit() { | |
| 992 m_pCurStates->m_GraphState.GetModify()->m_MiterLimit = GetNumber(0); | |
| 993 } | |
| 994 | |
| 995 void CPDF_StreamContentParser::Handle_MarkPlace() {} | |
| 996 | |
| 997 void CPDF_StreamContentParser::Handle_EndPath() { | |
| 998 if (m_Options.m_bTextOnly) { | |
| 999 return; | |
| 1000 } | |
| 1001 AddPathObject(0, FALSE); | |
| 1002 } | |
| 1003 | |
| 1004 void CPDF_StreamContentParser::Handle_SaveGraphState() { | |
| 1005 std::unique_ptr<CPDF_AllStates> pStates(new CPDF_AllStates); | |
| 1006 pStates->Copy(*m_pCurStates); | |
| 1007 m_StateStack.push_back(std::move(pStates)); | |
| 1008 } | |
| 1009 | |
| 1010 void CPDF_StreamContentParser::Handle_RestoreGraphState() { | |
| 1011 if (m_StateStack.empty()) | |
| 1012 return; | |
| 1013 std::unique_ptr<CPDF_AllStates> pStates = std::move(m_StateStack.back()); | |
| 1014 m_StateStack.pop_back(); | |
| 1015 m_pCurStates->Copy(*pStates); | |
| 1016 } | |
| 1017 | |
| 1018 void CPDF_StreamContentParser::Handle_Rectangle() { | |
| 1019 if (m_Options.m_bTextOnly) { | |
| 1020 return; | |
| 1021 } | |
| 1022 FX_FLOAT x = GetNumber(3), y = GetNumber(2); | |
| 1023 FX_FLOAT w = GetNumber(1), h = GetNumber(0); | |
| 1024 AddPathRect(x, y, w, h); | |
| 1025 } | |
| 1026 | |
| 1027 void CPDF_StreamContentParser::AddPathRect(FX_FLOAT x, | |
| 1028 FX_FLOAT y, | |
| 1029 FX_FLOAT w, | |
| 1030 FX_FLOAT h) { | |
| 1031 AddPathPoint(x, y, FXPT_MOVETO); | |
| 1032 AddPathPoint(x + w, y, FXPT_LINETO); | |
| 1033 AddPathPoint(x + w, y + h, FXPT_LINETO); | |
| 1034 AddPathPoint(x, y + h, FXPT_LINETO); | |
| 1035 AddPathPoint(x, y, FXPT_LINETO | FXPT_CLOSEFIGURE); | |
| 1036 } | |
| 1037 | |
| 1038 void CPDF_StreamContentParser::Handle_SetRGBColor_Fill() { | |
| 1039 if (m_ParamCount != 3) | |
| 1040 return; | |
| 1041 | |
| 1042 FX_FLOAT values[3]; | |
| 1043 for (int i = 0; i < 3; i++) { | |
| 1044 values[i] = GetNumber(2 - i); | |
| 1045 } | |
| 1046 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); | |
| 1047 m_pCurStates->m_ColorState.SetFillColor(pCS, values, 3); | |
| 1048 } | |
| 1049 | |
| 1050 void CPDF_StreamContentParser::Handle_SetRGBColor_Stroke() { | |
| 1051 if (m_ParamCount != 3) | |
| 1052 return; | |
| 1053 | |
| 1054 FX_FLOAT values[3]; | |
| 1055 for (int i = 0; i < 3; i++) { | |
| 1056 values[i] = GetNumber(2 - i); | |
| 1057 } | |
| 1058 CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); | |
| 1059 m_pCurStates->m_ColorState.SetStrokeColor(pCS, values, 3); | |
| 1060 } | |
| 1061 | |
| 1062 void CPDF_StreamContentParser::Handle_SetRenderIntent() {} | |
| 1063 | |
| 1064 void CPDF_StreamContentParser::Handle_CloseStrokePath() { | |
| 1065 if (m_Options.m_bTextOnly) { | |
| 1066 return; | |
| 1067 } | |
| 1068 Handle_ClosePath(); | |
| 1069 AddPathObject(0, TRUE); | |
| 1070 } | |
| 1071 | |
| 1072 void CPDF_StreamContentParser::Handle_StrokePath() { | |
| 1073 if (m_Options.m_bTextOnly) { | |
| 1074 return; | |
| 1075 } | |
| 1076 AddPathObject(0, TRUE); | |
| 1077 } | |
| 1078 | |
| 1079 void CPDF_StreamContentParser::Handle_SetColor_Fill() { | |
| 1080 if (m_Options.m_bTextOnly) { | |
| 1081 return; | |
| 1082 } | |
| 1083 FX_FLOAT values[4]; | |
| 1084 int nargs = m_ParamCount; | |
| 1085 if (nargs > 4) { | |
| 1086 nargs = 4; | |
| 1087 } | |
| 1088 for (int i = 0; i < nargs; i++) { | |
| 1089 values[i] = GetNumber(nargs - i - 1); | |
| 1090 } | |
| 1091 m_pCurStates->m_ColorState.SetFillColor(NULL, values, nargs); | |
| 1092 } | |
| 1093 | |
| 1094 void CPDF_StreamContentParser::Handle_SetColor_Stroke() { | |
| 1095 if (m_Options.m_bTextOnly) { | |
| 1096 return; | |
| 1097 } | |
| 1098 FX_FLOAT values[4]; | |
| 1099 int nargs = m_ParamCount; | |
| 1100 if (nargs > 4) { | |
| 1101 nargs = 4; | |
| 1102 } | |
| 1103 for (int i = 0; i < nargs; i++) { | |
| 1104 values[i] = GetNumber(nargs - i - 1); | |
| 1105 } | |
| 1106 m_pCurStates->m_ColorState.SetStrokeColor(NULL, values, nargs); | |
| 1107 } | |
| 1108 | |
| 1109 void CPDF_StreamContentParser::Handle_SetColorPS_Fill() { | |
| 1110 if (m_Options.m_bTextOnly) { | |
| 1111 return; | |
| 1112 } | |
| 1113 CPDF_Object* pLastParam = GetObject(0); | |
| 1114 if (!pLastParam) { | |
| 1115 return; | |
| 1116 } | |
| 1117 int nargs = m_ParamCount; | |
| 1118 int nvalues = nargs; | |
| 1119 if (pLastParam->IsName()) { | |
| 1120 nvalues--; | |
| 1121 } | |
| 1122 FX_FLOAT* values = NULL; | |
| 1123 if (nvalues) { | |
| 1124 values = FX_Alloc(FX_FLOAT, nvalues); | |
| 1125 for (int i = 0; i < nvalues; i++) { | |
| 1126 values[i] = GetNumber(nargs - i - 1); | |
| 1127 } | |
| 1128 } | |
| 1129 if (nvalues != nargs) { | |
| 1130 CPDF_Pattern* pPattern = FindPattern(GetString(0), FALSE); | |
| 1131 if (pPattern) { | |
| 1132 m_pCurStates->m_ColorState.SetFillPattern(pPattern, values, nvalues); | |
| 1133 } | |
| 1134 } else { | |
| 1135 m_pCurStates->m_ColorState.SetFillColor(NULL, values, nvalues); | |
| 1136 } | |
| 1137 FX_Free(values); | |
| 1138 } | |
| 1139 | |
| 1140 void CPDF_StreamContentParser::Handle_SetColorPS_Stroke() { | |
| 1141 if (m_Options.m_bTextOnly) { | |
| 1142 return; | |
| 1143 } | |
| 1144 CPDF_Object* pLastParam = GetObject(0); | |
| 1145 if (!pLastParam) { | |
| 1146 return; | |
| 1147 } | |
| 1148 int nargs = m_ParamCount; | |
| 1149 int nvalues = nargs; | |
| 1150 if (pLastParam->IsName()) | |
| 1151 nvalues--; | |
| 1152 | |
| 1153 FX_FLOAT* values = NULL; | |
| 1154 if (nvalues) { | |
| 1155 values = FX_Alloc(FX_FLOAT, nvalues); | |
| 1156 for (int i = 0; i < nvalues; i++) { | |
| 1157 values[i] = GetNumber(nargs - i - 1); | |
| 1158 } | |
| 1159 } | |
| 1160 if (nvalues != nargs) { | |
| 1161 CPDF_Pattern* pPattern = FindPattern(GetString(0), FALSE); | |
| 1162 if (pPattern) { | |
| 1163 m_pCurStates->m_ColorState.SetStrokePattern(pPattern, values, nvalues); | |
| 1164 } | |
| 1165 } else { | |
| 1166 m_pCurStates->m_ColorState.SetStrokeColor(NULL, values, nvalues); | |
| 1167 } | |
| 1168 FX_Free(values); | |
| 1169 } | |
| 1170 | |
| 1171 CFX_FloatRect GetShadingBBox(CPDF_Stream* pStream, | |
| 1172 ShadingType type, | |
| 1173 const CFX_Matrix* pMatrix, | |
| 1174 CPDF_Function** pFuncs, | |
| 1175 int nFuncs, | |
| 1176 CPDF_ColorSpace* pCS); | |
| 1177 | |
| 1178 void CPDF_StreamContentParser::Handle_ShadeFill() { | |
| 1179 if (m_Options.m_bTextOnly) { | |
| 1180 return; | |
| 1181 } | |
| 1182 CPDF_Pattern* pPattern = FindPattern(GetString(0), TRUE); | |
| 1183 if (!pPattern) { | |
| 1184 return; | |
| 1185 } | |
| 1186 if (pPattern->m_PatternType != CPDF_Pattern::SHADING) { | |
| 1187 return; | |
| 1188 } | |
| 1189 CPDF_ShadingPattern* pShading = static_cast<CPDF_ShadingPattern*>(pPattern); | |
| 1190 if (!pShading->m_bShadingObj) { | |
| 1191 return; | |
| 1192 } | |
| 1193 if (!pShading->Load()) { | |
| 1194 return; | |
| 1195 } | |
| 1196 std::unique_ptr<CPDF_ShadingObject> pObj(new CPDF_ShadingObject); | |
| 1197 pObj->m_pShading = pShading; | |
| 1198 SetGraphicStates(pObj.get(), FALSE, FALSE, FALSE); | |
| 1199 pObj->m_Matrix = m_pCurStates->m_CTM; | |
| 1200 pObj->m_Matrix.Concat(m_mtContentToUser); | |
| 1201 CFX_FloatRect bbox; | |
| 1202 if (!pObj->m_ClipPath.IsNull()) { | |
| 1203 bbox = pObj->m_ClipPath.GetClipBox(); | |
| 1204 } else { | |
| 1205 bbox = m_BBox; | |
| 1206 } | |
| 1207 if (pShading->IsMeshShading()) { | |
| 1208 bbox.Intersect(GetShadingBBox(ToStream(pShading->m_pShadingObj), | |
| 1209 pShading->m_ShadingType, &pObj->m_Matrix, | |
| 1210 pShading->m_pFunctions, pShading->m_nFuncs, | |
| 1211 pShading->m_pCS)); | |
| 1212 } | |
| 1213 pObj->m_Left = bbox.left; | |
| 1214 pObj->m_Right = bbox.right; | |
| 1215 pObj->m_Top = bbox.top; | |
| 1216 pObj->m_Bottom = bbox.bottom; | |
| 1217 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pObj)); | |
| 1218 } | |
| 1219 | |
| 1220 void CPDF_StreamContentParser::Handle_SetCharSpace() { | |
| 1221 m_pCurStates->m_TextState.GetModify()->m_CharSpace = GetNumber(0); | |
| 1222 } | |
| 1223 | |
| 1224 void CPDF_StreamContentParser::Handle_MoveTextPoint() { | |
| 1225 m_pCurStates->m_TextLineX += GetNumber(1); | |
| 1226 m_pCurStates->m_TextLineY += GetNumber(0); | |
| 1227 m_pCurStates->m_TextX = m_pCurStates->m_TextLineX; | |
| 1228 m_pCurStates->m_TextY = m_pCurStates->m_TextLineY; | |
| 1229 } | |
| 1230 | |
| 1231 void CPDF_StreamContentParser::Handle_MoveTextPoint_SetLeading() { | |
| 1232 Handle_MoveTextPoint(); | |
| 1233 m_pCurStates->m_TextLeading = -GetNumber(0); | |
| 1234 } | |
| 1235 | |
| 1236 void CPDF_StreamContentParser::Handle_SetFont() { | |
| 1237 FX_FLOAT fs = GetNumber(0); | |
| 1238 if (fs == 0) { | |
| 1239 fs = m_DefFontSize; | |
| 1240 } | |
| 1241 m_pCurStates->m_TextState.GetModify()->m_FontSize = fs; | |
| 1242 CPDF_Font* pFont = FindFont(GetString(1)); | |
| 1243 if (pFont) { | |
| 1244 m_pCurStates->m_TextState.SetFont(pFont); | |
| 1245 } | |
| 1246 } | |
| 1247 | |
| 1248 CPDF_Object* CPDF_StreamContentParser::FindResourceObj( | |
| 1249 const CFX_ByteStringC& type, | |
| 1250 const CFX_ByteString& name) { | |
| 1251 if (!m_pResources) { | |
| 1252 return NULL; | |
| 1253 } | |
| 1254 if (m_pResources == m_pPageResources) { | |
| 1255 CPDF_Dictionary* pList = m_pResources->GetDictBy(type); | |
| 1256 if (!pList) { | |
| 1257 return NULL; | |
| 1258 } | |
| 1259 CPDF_Object* pRes = pList->GetElementValue(name); | |
| 1260 return pRes; | |
| 1261 } | |
| 1262 CPDF_Dictionary* pList = m_pResources->GetDictBy(type); | |
| 1263 if (!pList) { | |
| 1264 if (!m_pPageResources) { | |
| 1265 return NULL; | |
| 1266 } | |
| 1267 CPDF_Dictionary* pList = m_pPageResources->GetDictBy(type); | |
| 1268 if (!pList) { | |
| 1269 return NULL; | |
| 1270 } | |
| 1271 CPDF_Object* pRes = pList->GetElementValue(name); | |
| 1272 return pRes; | |
| 1273 } | |
| 1274 CPDF_Object* pRes = pList->GetElementValue(name); | |
| 1275 return pRes; | |
| 1276 } | |
| 1277 | |
| 1278 CPDF_Font* CPDF_StreamContentParser::FindFont(const CFX_ByteString& name) { | |
| 1279 CPDF_Dictionary* pFontDict = ToDictionary(FindResourceObj("Font", name)); | |
| 1280 if (!pFontDict) { | |
| 1281 m_bResourceMissing = TRUE; | |
| 1282 return CPDF_Font::GetStockFont(m_pDocument, "Helvetica"); | |
| 1283 } | |
| 1284 | |
| 1285 CPDF_Font* pFont = m_pDocument->LoadFont(pFontDict); | |
| 1286 if (pFont && pFont->IsType3Font()) { | |
| 1287 pFont->AsType3Font()->SetPageResources(m_pResources); | |
| 1288 pFont->AsType3Font()->CheckType3FontMetrics(); | |
| 1289 } | |
| 1290 return pFont; | |
| 1291 } | |
| 1292 | |
| 1293 CPDF_ColorSpace* CPDF_StreamContentParser::FindColorSpace( | |
| 1294 const CFX_ByteString& name) { | |
| 1295 if (name == "Pattern") { | |
| 1296 return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN); | |
| 1297 } | |
| 1298 if (name == "DeviceGray" || name == "DeviceCMYK" || name == "DeviceRGB") { | |
| 1299 CFX_ByteString defname = "Default"; | |
| 1300 defname += name.Mid(7); | |
| 1301 CPDF_Object* pDefObj = FindResourceObj("ColorSpace", defname); | |
| 1302 if (!pDefObj) { | |
| 1303 if (name == "DeviceGray") { | |
| 1304 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); | |
| 1305 } | |
| 1306 if (name == "DeviceRGB") { | |
| 1307 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); | |
| 1308 } | |
| 1309 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); | |
| 1310 } | |
| 1311 return m_pDocument->LoadColorSpace(pDefObj); | |
| 1312 } | |
| 1313 CPDF_Object* pCSObj = FindResourceObj("ColorSpace", name); | |
| 1314 if (!pCSObj) { | |
| 1315 m_bResourceMissing = TRUE; | |
| 1316 return NULL; | |
| 1317 } | |
| 1318 return m_pDocument->LoadColorSpace(pCSObj); | |
| 1319 } | |
| 1320 | |
| 1321 CPDF_Pattern* CPDF_StreamContentParser::FindPattern(const CFX_ByteString& name, | |
| 1322 FX_BOOL bShading) { | |
| 1323 CPDF_Object* pPattern = | |
| 1324 FindResourceObj(bShading ? "Shading" : "Pattern", name); | |
| 1325 if (!pPattern || (!pPattern->IsDictionary() && !pPattern->IsStream())) { | |
| 1326 m_bResourceMissing = TRUE; | |
| 1327 return NULL; | |
| 1328 } | |
| 1329 return m_pDocument->LoadPattern(pPattern, bShading, | |
| 1330 &m_pCurStates->m_ParentMatrix); | |
| 1331 } | |
| 1332 | |
| 1333 void CPDF_StreamContentParser::ConvertTextSpace(FX_FLOAT& x, FX_FLOAT& y) { | |
| 1334 m_pCurStates->m_TextMatrix.Transform(x, y, x, y); | |
| 1335 ConvertUserSpace(x, y); | |
| 1336 } | |
| 1337 | |
| 1338 void CPDF_StreamContentParser::ConvertUserSpace(FX_FLOAT& x, FX_FLOAT& y) { | |
| 1339 m_pCurStates->m_CTM.Transform(x, y, x, y); | |
| 1340 m_mtContentToUser.Transform(x, y, x, y); | |
| 1341 } | |
| 1342 | |
| 1343 void CPDF_StreamContentParser::AddTextObject(CFX_ByteString* pStrs, | |
| 1344 FX_FLOAT fInitKerning, | |
| 1345 FX_FLOAT* pKerning, | |
| 1346 int nsegs) { | |
| 1347 CPDF_Font* pFont = m_pCurStates->m_TextState.GetFont(); | |
| 1348 if (!pFont) { | |
| 1349 return; | |
| 1350 } | |
| 1351 if (fInitKerning != 0) { | |
| 1352 if (!pFont->IsVertWriting()) { | |
| 1353 m_pCurStates->m_TextX -= | |
| 1354 (fInitKerning * m_pCurStates->m_TextState.GetFontSize()) / 1000; | |
| 1355 } else { | |
| 1356 m_pCurStates->m_TextY -= | |
| 1357 (fInitKerning * m_pCurStates->m_TextState.GetFontSize()) / 1000; | |
| 1358 } | |
| 1359 } | |
| 1360 if (nsegs == 0) { | |
| 1361 return; | |
| 1362 } | |
| 1363 int textmode; | |
| 1364 if (pFont->IsType3Font()) { | |
| 1365 textmode = 0; | |
| 1366 } else { | |
| 1367 textmode = m_pCurStates->m_TextState.GetObject()->m_TextMode; | |
| 1368 } | |
| 1369 { | |
| 1370 std::unique_ptr<CPDF_TextObject> pText(new CPDF_TextObject); | |
| 1371 m_pLastTextObject = pText.get(); | |
| 1372 SetGraphicStates(m_pLastTextObject, TRUE, TRUE, TRUE); | |
| 1373 if (textmode && textmode != 3 && textmode != 4 && textmode != 7) { | |
| 1374 FX_FLOAT* pCTM = pText->m_TextState.GetModify()->m_CTM; | |
| 1375 pCTM[0] = m_pCurStates->m_CTM.a; | |
| 1376 pCTM[1] = m_pCurStates->m_CTM.c; | |
| 1377 pCTM[2] = m_pCurStates->m_CTM.b; | |
| 1378 pCTM[3] = m_pCurStates->m_CTM.d; | |
| 1379 } | |
| 1380 pText->SetSegments(pStrs, pKerning, nsegs); | |
| 1381 pText->m_PosX = m_pCurStates->m_TextX; | |
| 1382 pText->m_PosY = m_pCurStates->m_TextY + m_pCurStates->m_TextRise; | |
| 1383 ConvertTextSpace(pText->m_PosX, pText->m_PosY); | |
| 1384 FX_FLOAT x_advance; | |
| 1385 FX_FLOAT y_advance; | |
| 1386 pText->CalcPositionData(&x_advance, &y_advance, | |
| 1387 m_pCurStates->m_TextHorzScale, m_Level); | |
| 1388 m_pCurStates->m_TextX += x_advance; | |
| 1389 m_pCurStates->m_TextY += y_advance; | |
| 1390 if (textmode > 3) | |
| 1391 m_ClipTextList.Add(pText->Clone()); | |
| 1392 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pText)); | |
| 1393 } | |
| 1394 if (pKerning && pKerning[nsegs - 1] != 0) { | |
| 1395 if (!pFont->IsVertWriting()) { | |
| 1396 m_pCurStates->m_TextX -= | |
| 1397 (pKerning[nsegs - 1] * m_pCurStates->m_TextState.GetFontSize()) / | |
| 1398 1000; | |
| 1399 } else { | |
| 1400 m_pCurStates->m_TextY -= | |
| 1401 (pKerning[nsegs - 1] * m_pCurStates->m_TextState.GetFontSize()) / | |
| 1402 1000; | |
| 1403 } | |
| 1404 } | |
| 1405 } | |
| 1406 | |
| 1407 void CPDF_StreamContentParser::Handle_ShowText() { | |
| 1408 CFX_ByteString str = GetString(0); | |
| 1409 if (str.IsEmpty()) { | |
| 1410 return; | |
| 1411 } | |
| 1412 AddTextObject(&str, 0, NULL, 1); | |
| 1413 } | |
| 1414 | |
| 1415 void CPDF_StreamContentParser::Handle_ShowText_Positioning() { | |
| 1416 CPDF_Array* pArray = GetObject(0) ? GetObject(0)->GetArray() : NULL; | |
| 1417 if (!pArray) { | |
| 1418 return; | |
| 1419 } | |
| 1420 int n = pArray->GetCount(); | |
| 1421 int nsegs = 0; | |
| 1422 for (int i = 0; i < n; i++) { | |
| 1423 if (pArray->GetElementValue(i)->IsString()) | |
| 1424 nsegs++; | |
| 1425 } | |
| 1426 if (nsegs == 0) { | |
| 1427 for (int i = 0; i < n; i++) { | |
| 1428 m_pCurStates->m_TextX -= | |
| 1429 (pArray->GetNumberAt(i) * m_pCurStates->m_TextState.GetFontSize()) / | |
| 1430 1000; | |
| 1431 } | |
| 1432 return; | |
| 1433 } | |
| 1434 CFX_ByteString* pStrs = new CFX_ByteString[nsegs]; | |
| 1435 FX_FLOAT* pKerning = FX_Alloc(FX_FLOAT, nsegs); | |
| 1436 int iSegment = 0; | |
| 1437 FX_FLOAT fInitKerning = 0; | |
| 1438 for (int i = 0; i < n; i++) { | |
| 1439 CPDF_Object* pObj = pArray->GetElementValue(i); | |
| 1440 if (pObj->IsString()) { | |
| 1441 CFX_ByteString str = pObj->GetString(); | |
| 1442 if (str.IsEmpty()) { | |
| 1443 continue; | |
| 1444 } | |
| 1445 pStrs[iSegment] = str; | |
| 1446 pKerning[iSegment++] = 0; | |
| 1447 } else { | |
| 1448 FX_FLOAT num = pObj ? pObj->GetNumber() : 0; | |
| 1449 if (iSegment == 0) { | |
| 1450 fInitKerning += num; | |
| 1451 } else { | |
| 1452 pKerning[iSegment - 1] += num; | |
| 1453 } | |
| 1454 } | |
| 1455 } | |
| 1456 AddTextObject(pStrs, fInitKerning, pKerning, iSegment); | |
| 1457 delete[] pStrs; | |
| 1458 FX_Free(pKerning); | |
| 1459 } | |
| 1460 | |
| 1461 void CPDF_StreamContentParser::Handle_SetTextLeading() { | |
| 1462 m_pCurStates->m_TextLeading = GetNumber(0); | |
| 1463 } | |
| 1464 | |
| 1465 void CPDF_StreamContentParser::Handle_SetTextMatrix() { | |
| 1466 m_pCurStates->m_TextMatrix.Set(GetNumber16(5), GetNumber16(4), GetNumber16(3), | |
| 1467 GetNumber16(2), GetNumber(1), GetNumber(0)); | |
| 1468 OnChangeTextMatrix(); | |
| 1469 m_pCurStates->m_TextX = 0; | |
| 1470 m_pCurStates->m_TextY = 0; | |
| 1471 m_pCurStates->m_TextLineX = 0; | |
| 1472 m_pCurStates->m_TextLineY = 0; | |
| 1473 } | |
| 1474 | |
| 1475 void CPDF_StreamContentParser::OnChangeTextMatrix() { | |
| 1476 CFX_Matrix text_matrix(m_pCurStates->m_TextHorzScale, 0.0f, 0.0f, 1.0f, 0.0f, | |
| 1477 0.0f); | |
| 1478 text_matrix.Concat(m_pCurStates->m_TextMatrix); | |
| 1479 text_matrix.Concat(m_pCurStates->m_CTM); | |
| 1480 text_matrix.Concat(m_mtContentToUser); | |
| 1481 FX_FLOAT* pTextMatrix = m_pCurStates->m_TextState.GetModify()->m_Matrix; | |
| 1482 pTextMatrix[0] = text_matrix.a; | |
| 1483 pTextMatrix[1] = text_matrix.c; | |
| 1484 pTextMatrix[2] = text_matrix.b; | |
| 1485 pTextMatrix[3] = text_matrix.d; | |
| 1486 } | |
| 1487 | |
| 1488 void CPDF_StreamContentParser::Handle_SetTextRenderMode() { | |
| 1489 int mode = GetInteger(0); | |
| 1490 if (mode < 0 || mode > 7) { | |
| 1491 return; | |
| 1492 } | |
| 1493 m_pCurStates->m_TextState.GetModify()->m_TextMode = mode; | |
| 1494 } | |
| 1495 | |
| 1496 void CPDF_StreamContentParser::Handle_SetTextRise() { | |
| 1497 m_pCurStates->m_TextRise = GetNumber(0); | |
| 1498 } | |
| 1499 | |
| 1500 void CPDF_StreamContentParser::Handle_SetWordSpace() { | |
| 1501 m_pCurStates->m_TextState.GetModify()->m_WordSpace = GetNumber(0); | |
| 1502 } | |
| 1503 | |
| 1504 void CPDF_StreamContentParser::Handle_SetHorzScale() { | |
| 1505 if (m_ParamCount != 1) { | |
| 1506 return; | |
| 1507 } | |
| 1508 m_pCurStates->m_TextHorzScale = GetNumber(0) / 100; | |
| 1509 OnChangeTextMatrix(); | |
| 1510 } | |
| 1511 | |
| 1512 void CPDF_StreamContentParser::Handle_MoveToNextLine() { | |
| 1513 m_pCurStates->m_TextLineY -= m_pCurStates->m_TextLeading; | |
| 1514 m_pCurStates->m_TextX = m_pCurStates->m_TextLineX; | |
| 1515 m_pCurStates->m_TextY = m_pCurStates->m_TextLineY; | |
| 1516 } | |
| 1517 | |
| 1518 void CPDF_StreamContentParser::Handle_CurveTo_23() { | |
| 1519 if (m_Options.m_bTextOnly) { | |
| 1520 return; | |
| 1521 } | |
| 1522 AddPathPoint(m_PathCurrentX, m_PathCurrentY, FXPT_BEZIERTO); | |
| 1523 AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO); | |
| 1524 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO); | |
| 1525 } | |
| 1526 | |
| 1527 void CPDF_StreamContentParser::Handle_SetLineWidth() { | |
| 1528 FX_FLOAT width = GetNumber(0); | |
| 1529 m_pCurStates->m_GraphState.GetModify()->m_LineWidth = width; | |
| 1530 } | |
| 1531 | |
| 1532 void CPDF_StreamContentParser::Handle_Clip() { | |
| 1533 m_PathClipType = FXFILL_WINDING; | |
| 1534 } | |
| 1535 | |
| 1536 void CPDF_StreamContentParser::Handle_EOClip() { | |
| 1537 m_PathClipType = FXFILL_ALTERNATE; | |
| 1538 } | |
| 1539 | |
| 1540 void CPDF_StreamContentParser::Handle_CurveTo_13() { | |
| 1541 if (m_Options.m_bTextOnly) { | |
| 1542 return; | |
| 1543 } | |
| 1544 AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO); | |
| 1545 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO); | |
| 1546 AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO); | |
| 1547 } | |
| 1548 | |
| 1549 void CPDF_StreamContentParser::Handle_NextLineShowText() { | |
| 1550 Handle_MoveToNextLine(); | |
| 1551 Handle_ShowText(); | |
| 1552 } | |
| 1553 | |
| 1554 void CPDF_StreamContentParser::Handle_NextLineShowText_Space() { | |
| 1555 m_pCurStates->m_TextState.GetModify()->m_WordSpace = GetNumber(2); | |
| 1556 m_pCurStates->m_TextState.GetModify()->m_CharSpace = GetNumber(1); | |
| 1557 Handle_NextLineShowText(); | |
| 1558 } | |
| 1559 | |
| 1560 void CPDF_StreamContentParser::Handle_Invalid() {} | |
| 1561 | |
| 1562 void CPDF_StreamContentParser::AddPathPoint(FX_FLOAT x, FX_FLOAT y, int flag) { | |
| 1563 m_PathCurrentX = x; | |
| 1564 m_PathCurrentY = y; | |
| 1565 if (flag == FXPT_MOVETO) { | |
| 1566 m_PathStartX = x; | |
| 1567 m_PathStartY = y; | |
| 1568 if (m_PathPointCount && | |
| 1569 m_pPathPoints[m_PathPointCount - 1].m_Flag == FXPT_MOVETO) { | |
| 1570 m_pPathPoints[m_PathPointCount - 1].m_PointX = x; | |
| 1571 m_pPathPoints[m_PathPointCount - 1].m_PointY = y; | |
| 1572 return; | |
| 1573 } | |
| 1574 } else if (m_PathPointCount == 0) { | |
| 1575 return; | |
| 1576 } | |
| 1577 m_PathPointCount++; | |
| 1578 if (m_PathPointCount > m_PathAllocSize) { | |
| 1579 int newsize = m_PathPointCount + 256; | |
| 1580 FX_PATHPOINT* pNewPoints = FX_Alloc(FX_PATHPOINT, newsize); | |
| 1581 if (m_PathAllocSize) { | |
| 1582 FXSYS_memcpy(pNewPoints, m_pPathPoints, | |
| 1583 m_PathAllocSize * sizeof(FX_PATHPOINT)); | |
| 1584 FX_Free(m_pPathPoints); | |
| 1585 } | |
| 1586 m_pPathPoints = pNewPoints; | |
| 1587 m_PathAllocSize = newsize; | |
| 1588 } | |
| 1589 m_pPathPoints[m_PathPointCount - 1].m_Flag = flag; | |
| 1590 m_pPathPoints[m_PathPointCount - 1].m_PointX = x; | |
| 1591 m_pPathPoints[m_PathPointCount - 1].m_PointY = y; | |
| 1592 } | |
| 1593 | |
| 1594 void CPDF_StreamContentParser::AddPathObject(int FillType, FX_BOOL bStroke) { | |
| 1595 int PathPointCount = m_PathPointCount, PathClipType = m_PathClipType; | |
| 1596 m_PathPointCount = 0; | |
| 1597 m_PathClipType = 0; | |
| 1598 if (PathPointCount <= 1) { | |
| 1599 if (PathPointCount && PathClipType) { | |
| 1600 CPDF_Path path; | |
| 1601 path.New()->AppendRect(0, 0, 0, 0); | |
| 1602 m_pCurStates->m_ClipPath.AppendPath(path, FXFILL_WINDING, TRUE); | |
| 1603 } | |
| 1604 return; | |
| 1605 } | |
| 1606 if (PathPointCount && | |
| 1607 m_pPathPoints[PathPointCount - 1].m_Flag == FXPT_MOVETO) { | |
| 1608 PathPointCount--; | |
| 1609 } | |
| 1610 CPDF_Path Path; | |
| 1611 CFX_PathData* pPathData = Path.New(); | |
| 1612 pPathData->SetPointCount(PathPointCount); | |
| 1613 FXSYS_memcpy(pPathData->GetPoints(), m_pPathPoints, | |
| 1614 sizeof(FX_PATHPOINT) * PathPointCount); | |
| 1615 CFX_Matrix matrix = m_pCurStates->m_CTM; | |
| 1616 matrix.Concat(m_mtContentToUser); | |
| 1617 if (bStroke || FillType) { | |
| 1618 std::unique_ptr<CPDF_PathObject> pPathObj(new CPDF_PathObject); | |
| 1619 pPathObj->m_bStroke = bStroke; | |
| 1620 pPathObj->m_FillType = FillType; | |
| 1621 pPathObj->m_Path = Path; | |
| 1622 pPathObj->m_Matrix = matrix; | |
| 1623 SetGraphicStates(pPathObj.get(), TRUE, FALSE, TRUE); | |
| 1624 pPathObj->CalcBoundingBox(); | |
| 1625 m_pObjectHolder->GetPageObjectList()->push_back(std::move(pPathObj)); | |
| 1626 } | |
| 1627 if (PathClipType) { | |
| 1628 if (!matrix.IsIdentity()) { | |
| 1629 Path.Transform(&matrix); | |
| 1630 matrix.SetIdentity(); | |
| 1631 } | |
| 1632 m_pCurStates->m_ClipPath.AppendPath(Path, PathClipType, TRUE); | |
| 1633 } | |
| 1634 } | |
| 1635 | |
| 1636 FX_DWORD CPDF_StreamContentParser::Parse(const uint8_t* pData, | |
| 1637 FX_DWORD dwSize, | |
| 1638 FX_DWORD max_cost) { | |
| 1639 if (m_Level > _FPDF_MAX_FORM_LEVEL_) { | |
| 1640 return dwSize; | |
| 1641 } | |
| 1642 FX_DWORD InitObjCount = m_pObjectHolder->GetPageObjectList()->size(); | |
| 1643 CPDF_StreamParser syntax(pData, dwSize); | |
| 1644 CPDF_StreamParserAutoClearer auto_clearer(&m_pSyntax, &syntax); | |
| 1645 while (1) { | |
| 1646 FX_DWORD cost = m_pObjectHolder->GetPageObjectList()->size() - InitObjCount; | |
| 1647 if (max_cost && cost >= max_cost) { | |
| 1648 break; | |
| 1649 } | |
| 1650 switch (syntax.ParseNextElement()) { | |
| 1651 case CPDF_StreamParser::EndOfData: | |
| 1652 return m_pSyntax->GetPos(); | |
| 1653 case CPDF_StreamParser::Keyword: | |
| 1654 OnOperator((char*)syntax.GetWordBuf()); | |
| 1655 ClearAllParams(); | |
| 1656 break; | |
| 1657 case CPDF_StreamParser::Number: | |
| 1658 AddNumberParam((char*)syntax.GetWordBuf(), syntax.GetWordSize()); | |
| 1659 break; | |
| 1660 case CPDF_StreamParser::Name: | |
| 1661 AddNameParam((const FX_CHAR*)syntax.GetWordBuf() + 1, | |
| 1662 syntax.GetWordSize() - 1); | |
| 1663 break; | |
| 1664 default: | |
| 1665 AddObjectParam(syntax.GetObject()); | |
| 1666 } | |
| 1667 } | |
| 1668 return m_pSyntax->GetPos(); | |
| 1669 } | |
| 1670 | |
| 1671 void CPDF_StreamContentParser::ParsePathObject() { | |
| 1672 FX_FLOAT params[6] = {}; | |
| 1673 int nParams = 0; | |
| 1674 int last_pos = m_pSyntax->GetPos(); | |
| 1675 while (1) { | |
| 1676 CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement(); | |
| 1677 FX_BOOL bProcessed = TRUE; | |
| 1678 switch (type) { | |
| 1679 case CPDF_StreamParser::EndOfData: | |
| 1680 return; | |
| 1681 case CPDF_StreamParser::Keyword: { | |
| 1682 int len = m_pSyntax->GetWordSize(); | |
| 1683 if (len == 1) { | |
| 1684 switch (m_pSyntax->GetWordBuf()[0]) { | |
| 1685 case kPathOperatorSubpath: | |
| 1686 AddPathPoint(params[0], params[1], FXPT_MOVETO); | |
| 1687 nParams = 0; | |
| 1688 break; | |
| 1689 case kPathOperatorLine: | |
| 1690 AddPathPoint(params[0], params[1], FXPT_LINETO); | |
| 1691 nParams = 0; | |
| 1692 break; | |
| 1693 case kPathOperatorCubicBezier1: | |
| 1694 AddPathPoint(params[0], params[1], FXPT_BEZIERTO); | |
| 1695 AddPathPoint(params[2], params[3], FXPT_BEZIERTO); | |
| 1696 AddPathPoint(params[4], params[5], FXPT_BEZIERTO); | |
| 1697 nParams = 0; | |
| 1698 break; | |
| 1699 case kPathOperatorCubicBezier2: | |
| 1700 AddPathPoint(m_PathCurrentX, m_PathCurrentY, FXPT_BEZIERTO); | |
| 1701 AddPathPoint(params[0], params[1], FXPT_BEZIERTO); | |
| 1702 AddPathPoint(params[2], params[3], FXPT_BEZIERTO); | |
| 1703 nParams = 0; | |
| 1704 break; | |
| 1705 case kPathOperatorCubicBezier3: | |
| 1706 AddPathPoint(params[0], params[1], FXPT_BEZIERTO); | |
| 1707 AddPathPoint(params[2], params[3], FXPT_BEZIERTO); | |
| 1708 AddPathPoint(params[2], params[3], FXPT_BEZIERTO); | |
| 1709 nParams = 0; | |
| 1710 break; | |
| 1711 case kPathOperatorClosePath: | |
| 1712 Handle_ClosePath(); | |
| 1713 nParams = 0; | |
| 1714 break; | |
| 1715 default: | |
| 1716 bProcessed = FALSE; | |
| 1717 break; | |
| 1718 } | |
| 1719 } else if (len == 2) { | |
| 1720 if (m_pSyntax->GetWordBuf()[0] == kPathOperatorRectangle[0] && | |
| 1721 m_pSyntax->GetWordBuf()[1] == kPathOperatorRectangle[1]) { | |
| 1722 AddPathRect(params[0], params[1], params[2], params[3]); | |
| 1723 nParams = 0; | |
| 1724 } else { | |
| 1725 bProcessed = FALSE; | |
| 1726 } | |
| 1727 } else { | |
| 1728 bProcessed = FALSE; | |
| 1729 } | |
| 1730 if (bProcessed) { | |
| 1731 last_pos = m_pSyntax->GetPos(); | |
| 1732 } | |
| 1733 break; | |
| 1734 } | |
| 1735 case CPDF_StreamParser::Number: { | |
| 1736 if (nParams == 6) { | |
| 1737 break; | |
| 1738 } | |
| 1739 FX_BOOL bInteger; | |
| 1740 int value; | |
| 1741 FX_atonum( | |
| 1742 CFX_ByteStringC(m_pSyntax->GetWordBuf(), m_pSyntax->GetWordSize()), | |
| 1743 bInteger, &value); | |
| 1744 params[nParams++] = bInteger ? (FX_FLOAT)value : *(FX_FLOAT*)&value; | |
| 1745 break; | |
| 1746 } | |
| 1747 default: | |
| 1748 bProcessed = FALSE; | |
| 1749 } | |
| 1750 if (!bProcessed) { | |
| 1751 m_pSyntax->SetPos(last_pos); | |
| 1752 return; | |
| 1753 } | |
| 1754 } | |
| 1755 } | |
| 1756 | |
| 1757 void PDF_ReplaceAbbr(CPDF_Object* pObj) { | |
| 1758 switch (pObj->GetType()) { | |
| 1759 case CPDF_Object::DICTIONARY: { | |
| 1760 CPDF_Dictionary* pDict = pObj->AsDictionary(); | |
| 1761 std::vector<AbbrReplacementOp> replacements; | |
| 1762 for (const auto& it : *pDict) { | |
| 1763 CFX_ByteString key = it.first; | |
| 1764 CPDF_Object* value = it.second; | |
| 1765 CFX_ByteStringC fullname = PDF_FindFullName( | |
| 1766 PDF_InlineKeyAbbr, FX_ArraySize(PDF_InlineKeyAbbr), key); | |
| 1767 if (!fullname.IsEmpty()) { | |
| 1768 AbbrReplacementOp op; | |
| 1769 op.is_replace_key = true; | |
| 1770 op.key = key; | |
| 1771 op.replacement = fullname; | |
| 1772 replacements.push_back(op); | |
| 1773 key = fullname; | |
| 1774 } | |
| 1775 | |
| 1776 if (value->IsName()) { | |
| 1777 CFX_ByteString name = value->GetString(); | |
| 1778 fullname = PDF_FindFullName(PDF_InlineValueAbbr, | |
| 1779 FX_ArraySize(PDF_InlineValueAbbr), name); | |
| 1780 if (!fullname.IsEmpty()) { | |
| 1781 AbbrReplacementOp op; | |
| 1782 op.is_replace_key = false; | |
| 1783 op.key = key; | |
| 1784 op.replacement = fullname; | |
| 1785 replacements.push_back(op); | |
| 1786 } | |
| 1787 } else { | |
| 1788 PDF_ReplaceAbbr(value); | |
| 1789 } | |
| 1790 } | |
| 1791 for (const auto& op : replacements) { | |
| 1792 if (op.is_replace_key) | |
| 1793 pDict->ReplaceKey(op.key, op.replacement); | |
| 1794 else | |
| 1795 pDict->SetAtName(op.key, op.replacement); | |
| 1796 } | |
| 1797 break; | |
| 1798 } | |
| 1799 case CPDF_Object::ARRAY: { | |
| 1800 CPDF_Array* pArray = pObj->AsArray(); | |
| 1801 for (FX_DWORD i = 0; i < pArray->GetCount(); i++) { | |
| 1802 CPDF_Object* pElement = pArray->GetElement(i); | |
| 1803 if (pElement->IsName()) { | |
| 1804 CFX_ByteString name = pElement->GetString(); | |
| 1805 CFX_ByteStringC fullname = PDF_FindFullName( | |
| 1806 PDF_InlineValueAbbr, FX_ArraySize(PDF_InlineValueAbbr), name); | |
| 1807 if (!fullname.IsEmpty()) { | |
| 1808 pArray->SetAt(i, new CPDF_Name(fullname)); | |
| 1809 } | |
| 1810 } else { | |
| 1811 PDF_ReplaceAbbr(pElement); | |
| 1812 } | |
| 1813 } | |
| 1814 break; | |
| 1815 } | |
| 1816 default: | |
| 1817 break; | |
| 1818 } | |
| 1819 } | |
| OLD | NEW |