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