• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param.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