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:
CPDF_StreamParserAutoClearer(CPDF_StreamParser ** scoped_variable,CPDF_StreamParser * new_parser)61 CPDF_StreamParserAutoClearer(CPDF_StreamParser** scoped_variable,
62 CPDF_StreamParser* new_parser)
63 : scoped_variable_(scoped_variable) {
64 *scoped_variable_ = new_parser;
65 }
~CPDF_StreamParserAutoClearer()66 ~CPDF_StreamParserAutoClearer() { *scoped_variable_ = nullptr; }
67
68 private:
69 CPDF_StreamParser** scoped_variable_;
70 };
71
GetShadingBBox(CPDF_ShadingPattern * pShading,const CFX_Matrix & matrix)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
FindFullName(const AbbrPair * table,size_t count,const CFX_ByteStringC & abbr)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
ReplaceAbbr(CPDF_Object * pObj)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
PDF_FindKeyAbbreviationForTesting(const CFX_ByteStringC & abbr)238 CFX_ByteStringC PDF_FindKeyAbbreviationForTesting(const CFX_ByteStringC& abbr) {
239 return FindFullName(InlineKeyAbbr, FX_ArraySize(InlineKeyAbbr), abbr);
240 }
241
PDF_FindValueAbbreviationForTesting(const CFX_ByteStringC & abbr)242 CFX_ByteStringC PDF_FindValueAbbreviationForTesting(
243 const CFX_ByteStringC& abbr) {
244 return FindFullName(InlineValueAbbr, FX_ArraySize(InlineValueAbbr), abbr);
245 }
246
CPDF_StreamContentParser(CPDF_Document * pDocument,CPDF_Dictionary * pPageResources,CPDF_Dictionary * pParentResources,const CFX_Matrix * pmtContentToUser,CPDF_PageObjectHolder * pObjHolder,CPDF_Dictionary * pResources,CFX_FloatRect * pBBox,CPDF_AllStates * pStates,int level)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
~CPDF_StreamContentParser()300 CPDF_StreamContentParser::~CPDF_StreamContentParser() {
301 ClearAllParams();
302 FX_Free(m_pPathPoints);
303 }
304
GetNextParamPos()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
AddNameParam(const CFX_ByteStringC & bsName)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
AddNumberParam(const CFX_ByteStringC & str)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
AddObjectParam(std::unique_ptr<CPDF_Object> pObj)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
ClearAllParams()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
GetObject(uint32_t index)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
GetString(uint32_t index)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
GetNumber(uint32_t index)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
SetGraphicStates(CPDF_PageObject * pObj,bool bColor,bool bText,bool bGraph)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
InitializeOpCodes()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
OnOperator(const CFX_ByteStringC & op)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
Handle_CloseFillStrokePath()584 void CPDF_StreamContentParser::Handle_CloseFillStrokePath() {
585 Handle_ClosePath();
586 AddPathObject(FXFILL_WINDING, true);
587 }
588
Handle_FillStrokePath()589 void CPDF_StreamContentParser::Handle_FillStrokePath() {
590 AddPathObject(FXFILL_WINDING, true);
591 }
592
Handle_CloseEOFillStrokePath()593 void CPDF_StreamContentParser::Handle_CloseEOFillStrokePath() {
594 AddPathPoint(m_PathStartX, m_PathStartY, FXPT_TYPE::LineTo, true);
595 AddPathObject(FXFILL_ALTERNATE, true);
596 }
597
Handle_EOFillStrokePath()598 void CPDF_StreamContentParser::Handle_EOFillStrokePath() {
599 AddPathObject(FXFILL_ALTERNATE, true);
600 }
601
Handle_BeginMarkedContent_Dictionary()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
Handle_BeginImage()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
Handle_BeginMarkedContent()676 void CPDF_StreamContentParser::Handle_BeginMarkedContent() {
677 m_CurContentMark.AddMark(GetString(0), nullptr, false);
678 }
679
Handle_BeginText()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
Handle_CurveTo_123()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
Handle_ConcatMatrix()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
Handle_SetColorSpace_Fill()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
Handle_SetColorSpace_Stroke()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
Handle_SetDash()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
Handle_SetCharWidth()725 void CPDF_StreamContentParser::Handle_SetCharWidth() {
726 m_Type3Data[0] = GetNumber(1);
727 m_Type3Data[1] = GetNumber(0);
728 m_bColored = true;
729 }
730
Handle_SetCachedDevice()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
Handle_ExecuteXObject()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
AddForm(CPDF_Stream * pStream)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
AddImage(std::unique_ptr<CPDF_Stream> pStream)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
AddImage(uint32_t streamObjNum)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
AddImage(CPDF_Image * pImage)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
AddImageObject(std::unique_ptr<CPDF_ImageObject> pImageObj)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
Handle_MarkPlace_Dictionary()835 void CPDF_StreamContentParser::Handle_MarkPlace_Dictionary() {}
836
Handle_EndImage()837 void CPDF_StreamContentParser::Handle_EndImage() {}
838
Handle_EndMarkedContent()839 void CPDF_StreamContentParser::Handle_EndMarkedContent() {
840 if (m_CurContentMark)
841 m_CurContentMark.DeleteLastMark();
842 }
843
Handle_EndText()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
Handle_FillPath()854 void CPDF_StreamContentParser::Handle_FillPath() {
855 AddPathObject(FXFILL_WINDING, false);
856 }
857
Handle_FillPathOld()858 void CPDF_StreamContentParser::Handle_FillPathOld() {
859 AddPathObject(FXFILL_WINDING, false);
860 }
861
Handle_EOFillPath()862 void CPDF_StreamContentParser::Handle_EOFillPath() {
863 AddPathObject(FXFILL_ALTERNATE, false);
864 }
865
Handle_SetGray_Fill()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
Handle_SetGray_Stroke()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
Handle_SetExtendGraphState()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
Handle_ClosePath()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
Handle_SetFlat()899 void CPDF_StreamContentParser::Handle_SetFlat() {
900 m_pCurStates->m_GeneralState.SetFlatness(GetNumber(0));
901 }
902
Handle_BeginImageData()903 void CPDF_StreamContentParser::Handle_BeginImageData() {}
904
Handle_SetLineJoin()905 void CPDF_StreamContentParser::Handle_SetLineJoin() {
906 m_pCurStates->m_GraphState.SetLineJoin(
907 static_cast<CFX_GraphStateData::LineJoin>(GetInteger(0)));
908 }
909
Handle_SetLineCap()910 void CPDF_StreamContentParser::Handle_SetLineCap() {
911 m_pCurStates->m_GraphState.SetLineCap(
912 static_cast<CFX_GraphStateData::LineCap>(GetInteger(0)));
913 }
914
Handle_SetCMYKColor_Fill()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
Handle_SetCMYKColor_Stroke()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
Handle_LineTo()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
Handle_MoveTo()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
Handle_SetMiterLimit()954 void CPDF_StreamContentParser::Handle_SetMiterLimit() {
955 m_pCurStates->m_GraphState.SetMiterLimit(GetNumber(0));
956 }
957
Handle_MarkPlace()958 void CPDF_StreamContentParser::Handle_MarkPlace() {}
959
Handle_EndPath()960 void CPDF_StreamContentParser::Handle_EndPath() {
961 AddPathObject(0, false);
962 }
963
Handle_SaveGraphState()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
Handle_RestoreGraphState()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
Handle_Rectangle()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
AddPathRect(FX_FLOAT x,FX_FLOAT y,FX_FLOAT w,FX_FLOAT h)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
Handle_SetRGBColor_Fill()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
Handle_SetRGBColor_Stroke()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
Handle_SetRenderIntent()1019 void CPDF_StreamContentParser::Handle_SetRenderIntent() {}
1020
Handle_CloseStrokePath()1021 void CPDF_StreamContentParser::Handle_CloseStrokePath() {
1022 Handle_ClosePath();
1023 AddPathObject(0, true);
1024 }
1025
Handle_StrokePath()1026 void CPDF_StreamContentParser::Handle_StrokePath() {
1027 AddPathObject(0, true);
1028 }
1029
Handle_SetColor_Fill()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
Handle_SetColor_Stroke()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
Handle_SetColorPS_Fill()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
Handle_SetColorPS_Stroke()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
Handle_ShadeFill()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
Handle_SetCharSpace()1137 void CPDF_StreamContentParser::Handle_SetCharSpace() {
1138 m_pCurStates->m_TextState.SetCharSpace(GetNumber(0));
1139 }
1140
Handle_MoveTextPoint()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
Handle_MoveTextPoint_SetLeading()1146 void CPDF_StreamContentParser::Handle_MoveTextPoint_SetLeading() {
1147 Handle_MoveTextPoint();
1148 m_pCurStates->m_TextLeading = -GetNumber(0);
1149 }
1150
Handle_SetFont()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
FindResourceObj(const CFX_ByteString & type,const CFX_ByteString & name)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
FindFont(const CFX_ByteString & name)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
FindColorSpace(const CFX_ByteString & name)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
FindPattern(const CFX_ByteString & name,bool bShading)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
AddTextObject(CFX_ByteString * pStrs,FX_FLOAT fInitKerning,FX_FLOAT * pKerning,int nsegs)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
Handle_ShowText()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
Handle_ShowText_Positioning()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
Handle_SetTextLeading()1352 void CPDF_StreamContentParser::Handle_SetTextLeading() {
1353 m_pCurStates->m_TextLeading = GetNumber(0);
1354 }
1355
Handle_SetTextMatrix()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
OnChangeTextMatrix()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
Handle_SetTextRenderMode()1378 void CPDF_StreamContentParser::Handle_SetTextRenderMode() {
1379 TextRenderingMode mode;
1380 if (SetTextRenderingModeFromInt(GetInteger(0), &mode))
1381 m_pCurStates->m_TextState.SetTextMode(mode);
1382 }
1383
Handle_SetTextRise()1384 void CPDF_StreamContentParser::Handle_SetTextRise() {
1385 m_pCurStates->m_TextRise = GetNumber(0);
1386 }
1387
Handle_SetWordSpace()1388 void CPDF_StreamContentParser::Handle_SetWordSpace() {
1389 m_pCurStates->m_TextState.SetWordSpace(GetNumber(0));
1390 }
1391
Handle_SetHorzScale()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
Handle_MoveToNextLine()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
Handle_CurveTo_23()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
Handle_SetLineWidth()1411 void CPDF_StreamContentParser::Handle_SetLineWidth() {
1412 m_pCurStates->m_GraphState.SetLineWidth(GetNumber(0));
1413 }
1414
Handle_Clip()1415 void CPDF_StreamContentParser::Handle_Clip() {
1416 m_PathClipType = FXFILL_WINDING;
1417 }
1418
Handle_EOClip()1419 void CPDF_StreamContentParser::Handle_EOClip() {
1420 m_PathClipType = FXFILL_ALTERNATE;
1421 }
1422
Handle_CurveTo_13()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
Handle_NextLineShowText()1429 void CPDF_StreamContentParser::Handle_NextLineShowText() {
1430 Handle_MoveToNextLine();
1431 Handle_ShowText();
1432 }
1433
Handle_NextLineShowText_Space()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
Handle_Invalid()1440 void CPDF_StreamContentParser::Handle_Invalid() {}
1441
AddPathPoint(FX_FLOAT x,FX_FLOAT y,FXPT_TYPE type,bool close)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
AddPathObject(int FillType,bool bStroke)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
Parse(const uint8_t * pData,uint32_t dwSize,uint32_t max_cost)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
ParsePathObject()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
ContentParam()1640 CPDF_StreamContentParser::ContentParam::ContentParam() {}
1641
~ContentParam()1642 CPDF_StreamContentParser::ContentParam::~ContentParam() {}
1643