1// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#ifndef CORE_SRC_FPDFAPI_FPDF_PAGE_PAGEINT_H_
8#define CORE_SRC_FPDFAPI_FPDF_PAGE_PAGEINT_H_
9
10#include <map>
11#include <memory>
12#include <vector>
13
14#include "core/include/fpdfapi/fpdf_page.h"
15#include "core/include/fpdfapi/fpdf_pageobj.h"
16
17class CPDF_AllStates;
18class CPDF_ParseOptions;
19
20#define PARSE_STEP_LIMIT 100
21
22class CPDF_StreamParser {
23 public:
24  enum SyntaxType { EndOfData, Number, Keyword, Name, Others };
25
26  CPDF_StreamParser(const uint8_t* pData, FX_DWORD dwSize);
27  ~CPDF_StreamParser();
28
29  CPDF_Stream* ReadInlineStream(CPDF_Document* pDoc,
30                                CPDF_Dictionary* pDict,
31                                CPDF_Object* pCSObj,
32                                FX_BOOL bDecode);
33  SyntaxType ParseNextElement();
34  uint8_t* GetWordBuf() { return m_WordBuffer; }
35  FX_DWORD GetWordSize() const { return m_WordSize; }
36  CPDF_Object* GetObject() {
37    CPDF_Object* pObj = m_pLastObj;
38    m_pLastObj = NULL;
39    return pObj;
40  }
41  FX_DWORD GetPos() const { return m_Pos; }
42  void SetPos(FX_DWORD pos) { m_Pos = pos; }
43  CPDF_Object* ReadNextObject(FX_BOOL bAllowNestedArray = FALSE,
44                              FX_BOOL bInArray = FALSE);
45  void SkipPathObject();
46
47 protected:
48  friend class fpdf_page_parser_old_ReadHexString_Test;
49
50  void GetNextWord(FX_BOOL& bIsNumber);
51  CFX_ByteString ReadString();
52  CFX_ByteString ReadHexString();
53  const uint8_t* m_pBuf;
54
55  // Length in bytes of m_pBuf.
56  FX_DWORD m_Size;
57
58  // Current byte position within m_pBuf.
59  FX_DWORD m_Pos;
60
61  uint8_t m_WordBuffer[256];
62  FX_DWORD m_WordSize;
63  CPDF_Object* m_pLastObj;
64
65 private:
66  bool PositionIsInBounds() const;
67};
68
69#define PARAM_BUF_SIZE 16
70struct ContentParam {
71  int m_Type;
72  union {
73    struct {
74      FX_BOOL m_bInteger;
75      union {
76        int m_Integer;
77        FX_FLOAT m_Float;
78      };
79    } m_Number;
80    CPDF_Object* m_pObject;
81    struct {
82      int m_Len;
83      char m_Buffer[32];
84    } m_Name;
85  };
86};
87#define _FPDF_MAX_FORM_LEVEL_ 30
88#define _FPDF_MAX_TYPE3_FORM_LEVEL_ 4
89#define _FPDF_MAX_OBJECT_STACK_SIZE_ 512
90class CPDF_StreamContentParser {
91 public:
92  CPDF_StreamContentParser(CPDF_Document* pDoc,
93                           CPDF_Dictionary* pPageResources,
94                           CPDF_Dictionary* pParentResources,
95                           CFX_Matrix* pmtContentToUser,
96                           CPDF_PageObjects* pObjList,
97                           CPDF_Dictionary* pResources,
98                           CFX_FloatRect* pBBox,
99                           CPDF_ParseOptions* pOptions,
100                           CPDF_AllStates* pAllStates,
101                           int level);
102  ~CPDF_StreamContentParser();
103
104  CPDF_PageObjects* GetObjectList() const { return m_pObjectList; }
105  CPDF_AllStates* GetCurStates() const { return m_pCurStates.get(); }
106  FX_BOOL IsColored() const { return m_bColored; }
107  const FX_FLOAT* GetType3Data() const { return m_Type3Data; }
108
109  void AddNumberParam(const FX_CHAR* str, int len);
110  void AddObjectParam(CPDF_Object* pObj);
111  void AddNameParam(const FX_CHAR* name, int size);
112  int GetNextParamPos();
113  void ClearAllParams();
114  CPDF_Object* GetObject(FX_DWORD index);
115  CFX_ByteString GetString(FX_DWORD index);
116  FX_FLOAT GetNumber(FX_DWORD index);
117  FX_FLOAT GetNumber16(FX_DWORD index);
118  int GetInteger(FX_DWORD index) { return (int32_t)(GetNumber(index)); }
119  FX_BOOL OnOperator(const FX_CHAR* op);
120  void BigCaseCaller(int index);
121  FX_DWORD GetParsePos() { return m_pSyntax->GetPos(); }
122  void AddTextObject(CFX_ByteString* pText,
123                     FX_FLOAT fInitKerning,
124                     FX_FLOAT* pKerning,
125                     int count);
126
127  void ConvertUserSpace(FX_FLOAT& x, FX_FLOAT& y);
128  void ConvertTextSpace(FX_FLOAT& x, FX_FLOAT& y);
129  void OnChangeTextMatrix();
130  FX_DWORD Parse(const uint8_t* pData, FX_DWORD dwSize, FX_DWORD max_cost);
131  void ParsePathObject();
132  void AddPathPoint(FX_FLOAT x, FX_FLOAT y, int flag);
133  void AddPathRect(FX_FLOAT x, FX_FLOAT y, FX_FLOAT w, FX_FLOAT h);
134  void AddPathObject(int FillType, FX_BOOL bStroke);
135  CPDF_ImageObject* AddImage(CPDF_Stream* pStream,
136                             CPDF_Image* pImage,
137                             FX_BOOL bInline);
138  void AddDuplicateImage();
139  void AddForm(CPDF_Stream*);
140  void SetGraphicStates(CPDF_PageObject* pObj,
141                        FX_BOOL bColor,
142                        FX_BOOL bText,
143                        FX_BOOL bGraph);
144  void SaveStates(CPDF_AllStates*);
145  void RestoreStates(CPDF_AllStates*);
146  CPDF_Font* FindFont(const CFX_ByteString& name);
147  CPDF_ColorSpace* FindColorSpace(const CFX_ByteString& name);
148  CPDF_Pattern* FindPattern(const CFX_ByteString& name, FX_BOOL bShading);
149  CPDF_Object* FindResourceObj(const CFX_ByteStringC& type,
150                               const CFX_ByteString& name);
151
152 protected:
153  struct OpCode {
154    FX_DWORD m_OpId;
155    void (CPDF_StreamContentParser::*m_OpHandler)();
156  };
157  static const OpCode g_OpCodes[];
158
159  void Handle_CloseFillStrokePath();
160  void Handle_FillStrokePath();
161  void Handle_CloseEOFillStrokePath();
162  void Handle_EOFillStrokePath();
163  void Handle_BeginMarkedContent_Dictionary();
164  void Handle_BeginImage();
165  void Handle_BeginMarkedContent();
166  void Handle_BeginText();
167  void Handle_BeginSectionUndefined();
168  void Handle_CurveTo_123();
169  void Handle_ConcatMatrix();
170  void Handle_SetColorSpace_Fill();
171  void Handle_SetColorSpace_Stroke();
172  void Handle_SetDash();
173  void Handle_SetCharWidth();
174  void Handle_SetCachedDevice();
175  void Handle_ExecuteXObject();
176  void Handle_MarkPlace_Dictionary();
177  void Handle_EndImage();
178  void Handle_EndMarkedContent();
179  void Handle_EndText();
180  void Handle_EndSectionUndefined();
181  void Handle_FillPath();
182  void Handle_FillPathOld();
183  void Handle_EOFillPath();
184  void Handle_SetGray_Fill();
185  void Handle_SetGray_Stroke();
186  void Handle_SetExtendGraphState();
187  void Handle_ClosePath();
188  void Handle_SetFlat();
189  void Handle_BeginImageData();
190  void Handle_SetLineJoin();
191  void Handle_SetLineCap();
192  void Handle_SetCMYKColor_Fill();
193  void Handle_SetCMYKColor_Stroke();
194  void Handle_LineTo();
195  void Handle_MoveTo();
196  void Handle_SetMiterLimit();
197  void Handle_MarkPlace();
198  void Handle_EndPath();
199  void Handle_SaveGraphState();
200  void Handle_RestoreGraphState();
201  void Handle_Rectangle();
202  void Handle_SetRGBColor_Fill();
203  void Handle_SetRGBColor_Stroke();
204  void Handle_SetRenderIntent();
205  void Handle_CloseStrokePath();
206  void Handle_StrokePath();
207  void Handle_SetColor_Fill();
208  void Handle_SetColor_Stroke();
209  void Handle_SetColorPS_Fill();
210  void Handle_SetColorPS_Stroke();
211  void Handle_ShadeFill();
212  void Handle_SetCharSpace();
213  void Handle_MoveTextPoint();
214  void Handle_MoveTextPoint_SetLeading();
215  void Handle_SetFont();
216  void Handle_ShowText();
217  void Handle_ShowText_Positioning();
218  void Handle_SetTextLeading();
219  void Handle_SetTextMatrix();
220  void Handle_SetTextRenderMode();
221  void Handle_SetTextRise();
222  void Handle_SetWordSpace();
223  void Handle_SetHorzScale();
224  void Handle_MoveToNextLine();
225  void Handle_CurveTo_23();
226  void Handle_SetLineWidth();
227  void Handle_Clip();
228  void Handle_EOClip();
229  void Handle_CurveTo_13();
230  void Handle_NextLineShowText();
231  void Handle_NextLineShowText_Space();
232  void Handle_Invalid();
233
234  CPDF_Document* const m_pDocument;
235  CPDF_Dictionary* m_pPageResources;
236  CPDF_Dictionary* m_pParentResources;
237  CPDF_Dictionary* m_pResources;
238  CPDF_PageObjects* m_pObjectList;
239  int m_Level;
240  CFX_Matrix m_mtContentToUser;
241  CFX_FloatRect m_BBox;
242  CPDF_ParseOptions m_Options;
243  ContentParam m_ParamBuf1[PARAM_BUF_SIZE];
244  FX_DWORD m_ParamStartPos;
245  FX_DWORD m_ParamCount;
246  CPDF_StreamParser* m_pSyntax;
247  std::unique_ptr<CPDF_AllStates> m_pCurStates;
248  CPDF_ContentMark m_CurContentMark;
249  CFX_ArrayTemplate<CPDF_TextObject*> m_ClipTextList;
250  CPDF_TextObject* m_pLastTextObject;
251  FX_FLOAT m_DefFontSize;
252  int m_CompatCount;
253  FX_PATHPOINT* m_pPathPoints;
254  int m_PathPointCount;
255  int m_PathAllocSize;
256  FX_FLOAT m_PathStartX;
257  FX_FLOAT m_PathStartY;
258  FX_FLOAT m_PathCurrentX;
259  FX_FLOAT m_PathCurrentY;
260  int m_PathClipType;
261  CFX_ByteString m_LastImageName;
262  CPDF_Image* m_pLastImage;
263  CFX_BinaryBuf m_LastImageDict;
264  CFX_BinaryBuf m_LastImageData;
265  CPDF_Dictionary* m_pLastImageDict;
266  CPDF_Dictionary* m_pLastCloneImageDict;
267  FX_BOOL m_bReleaseLastDict;
268  FX_BOOL m_bSameLastDict;
269  FX_BOOL m_bColored;
270  FX_FLOAT m_Type3Data[6];
271  FX_BOOL m_bResourceMissing;
272  std::vector<std::unique_ptr<CPDF_AllStates>> m_StateStack;
273};
274class CPDF_ContentParser {
275 public:
276  enum ParseStatus { Ready, ToBeContinued, Done };
277
278  CPDF_ContentParser();
279  ~CPDF_ContentParser();
280
281  ParseStatus GetStatus() const { return m_Status; }
282  void Start(CPDF_Page* pPage, CPDF_ParseOptions* pOptions);
283  void Start(CPDF_Form* pForm,
284             CPDF_AllStates* pGraphicStates,
285             CFX_Matrix* pParentMatrix,
286             CPDF_Type3Char* pType3Char,
287             CPDF_ParseOptions* pOptions,
288             int level);
289  void Continue(IFX_Pause* pPause);
290
291 private:
292  enum InternalStage {
293    STAGE_GETCONTENT = 1,
294    STAGE_PARSE,
295    STAGE_CHECKCLIP,
296  };
297
298  ParseStatus m_Status;
299  InternalStage m_InternalStage;
300  CPDF_PageObjects* m_pObjects;
301  FX_BOOL m_bForm;
302  CPDF_ParseOptions m_Options;
303  CPDF_Type3Char* m_pType3Char;
304  FX_DWORD m_nStreams;
305  std::unique_ptr<CPDF_StreamAcc> m_pSingleStream;
306  std::vector<std::unique_ptr<CPDF_StreamAcc>> m_StreamArray;
307  uint8_t* m_pData;
308  FX_DWORD m_Size;
309  FX_DWORD m_CurrentOffset;
310  std::unique_ptr<CPDF_StreamContentParser> m_pParser;
311};
312class CPDF_AllStates : public CPDF_GraphicStates {
313 public:
314  CPDF_AllStates();
315  ~CPDF_AllStates();
316  void Copy(const CPDF_AllStates& src);
317  void ProcessExtGS(CPDF_Dictionary* pGS, CPDF_StreamContentParser* pParser);
318  void SetLineDash(CPDF_Array*, FX_FLOAT, FX_FLOAT scale);
319  CFX_Matrix m_TextMatrix, m_CTM, m_ParentMatrix;
320  FX_FLOAT m_TextX, m_TextY, m_TextLineX, m_TextLineY;
321  FX_FLOAT m_TextLeading, m_TextRise, m_TextHorzScale;
322};
323
324class CPDF_DocPageData {
325 public:
326  explicit CPDF_DocPageData(CPDF_Document* pPDFDoc);
327  ~CPDF_DocPageData();
328
329  void Clear(FX_BOOL bRelease = FALSE);
330  CPDF_Font* GetFont(CPDF_Dictionary* pFontDict, FX_BOOL findOnly);
331  CPDF_Font* GetStandardFont(const CFX_ByteStringC& fontName,
332                             CPDF_FontEncoding* pEncoding);
333  void ReleaseFont(CPDF_Dictionary* pFontDict);
334  CPDF_ColorSpace* GetColorSpace(CPDF_Object* pCSObj,
335                                 const CPDF_Dictionary* pResources);
336  CPDF_ColorSpace* GetCopiedColorSpace(CPDF_Object* pCSObj);
337  void ReleaseColorSpace(CPDF_Object* pColorSpace);
338  CPDF_Pattern* GetPattern(CPDF_Object* pPatternObj,
339                           FX_BOOL bShading,
340                           const CFX_Matrix* matrix);
341  void ReleasePattern(CPDF_Object* pPatternObj);
342  CPDF_Image* GetImage(CPDF_Object* pImageStream);
343  void ReleaseImage(CPDF_Object* pImageStream);
344  CPDF_IccProfile* GetIccProfile(CPDF_Stream* pIccProfileStream);
345  void ReleaseIccProfile(CPDF_IccProfile* pIccProfile);
346  CPDF_StreamAcc* GetFontFileStreamAcc(CPDF_Stream* pFontStream);
347  void ReleaseFontFileStreamAcc(CPDF_Stream* pFontStream,
348                                FX_BOOL bForce = FALSE);
349  FX_BOOL IsForceClear() const { return m_bForceClear; }
350  CPDF_CountedColorSpace* FindColorSpacePtr(CPDF_Object* pCSObj) const;
351  CPDF_CountedPattern* FindPatternPtr(CPDF_Object* pPatternObj) const;
352
353 private:
354  using CPDF_CountedFont = CPDF_CountedObject<CPDF_Font>;
355  using CPDF_CountedIccProfile = CPDF_CountedObject<CPDF_IccProfile>;
356  using CPDF_CountedImage = CPDF_CountedObject<CPDF_Image>;
357  using CPDF_CountedStreamAcc = CPDF_CountedObject<CPDF_StreamAcc>;
358
359  using CPDF_ColorSpaceMap = std::map<CPDF_Object*, CPDF_CountedColorSpace*>;
360  using CPDF_FontFileMap = std::map<CPDF_Stream*, CPDF_CountedStreamAcc*>;
361  using CPDF_FontMap = std::map<CPDF_Dictionary*, CPDF_CountedFont*>;
362  using CPDF_IccProfileMap = std::map<CPDF_Stream*, CPDF_CountedIccProfile*>;
363  using CPDF_ImageMap = std::map<FX_DWORD, CPDF_CountedImage*>;
364  using CPDF_PatternMap = std::map<CPDF_Object*, CPDF_CountedPattern*>;
365
366  CPDF_Document* const m_pPDFDoc;
367  FX_BOOL m_bForceClear;
368  std::map<CFX_ByteString, CPDF_Stream*> m_HashProfileMap;
369  CPDF_ColorSpaceMap m_ColorSpaceMap;
370  CPDF_FontFileMap m_FontFileMap;
371  CPDF_FontMap m_FontMap;
372  CPDF_IccProfileMap m_IccProfileMap;
373  CPDF_ImageMap m_ImageMap;
374  CPDF_PatternMap m_PatternMap;
375};
376
377class CPDF_Function {
378 public:
379  static CPDF_Function* Load(CPDF_Object* pFuncObj);
380  virtual ~CPDF_Function();
381  FX_BOOL Call(FX_FLOAT* inputs,
382               int ninputs,
383               FX_FLOAT* results,
384               int& nresults) const;
385  int CountInputs() { return m_nInputs; }
386  int CountOutputs() { return m_nOutputs; }
387
388 protected:
389  CPDF_Function();
390  int m_nInputs, m_nOutputs;
391  FX_FLOAT* m_pDomains;
392  FX_FLOAT* m_pRanges;
393  FX_BOOL Init(CPDF_Object* pObj);
394  virtual FX_BOOL v_Init(CPDF_Object* pObj) = 0;
395  virtual FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const = 0;
396};
397class CPDF_IccProfile {
398 public:
399  CPDF_IccProfile(const uint8_t* pData, FX_DWORD dwSize);
400  ~CPDF_IccProfile();
401  int32_t GetComponents() const { return m_nSrcComponents; }
402  FX_BOOL m_bsRGB;
403  void* m_pTransform;
404
405 private:
406  int32_t m_nSrcComponents;
407};
408
409class CPDF_DeviceCS : public CPDF_ColorSpace {
410 public:
411  CPDF_DeviceCS(CPDF_Document* pDoc, int family);
412
413  FX_BOOL GetRGB(FX_FLOAT* pBuf,
414                 FX_FLOAT& R,
415                 FX_FLOAT& G,
416                 FX_FLOAT& B) const override;
417  FX_BOOL SetRGB(FX_FLOAT* pBuf,
418                 FX_FLOAT R,
419                 FX_FLOAT G,
420                 FX_FLOAT B) const override;
421  FX_BOOL v_GetCMYK(FX_FLOAT* pBuf,
422                    FX_FLOAT& c,
423                    FX_FLOAT& m,
424                    FX_FLOAT& y,
425                    FX_FLOAT& k) const override;
426  FX_BOOL v_SetCMYK(FX_FLOAT* pBuf,
427                    FX_FLOAT c,
428                    FX_FLOAT m,
429                    FX_FLOAT y,
430                    FX_FLOAT k) const override;
431  void TranslateImageLine(uint8_t* pDestBuf,
432                          const uint8_t* pSrcBuf,
433                          int pixels,
434                          int image_width,
435                          int image_height,
436                          FX_BOOL bTransMask = FALSE) const override;
437};
438
439class CPDF_PatternCS : public CPDF_ColorSpace {
440 public:
441  explicit CPDF_PatternCS(CPDF_Document* pDoc)
442      : CPDF_ColorSpace(pDoc, PDFCS_PATTERN, 1),
443        m_pBaseCS(nullptr),
444        m_pCountedBaseCS(nullptr) {}
445  ~CPDF_PatternCS() override;
446  FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
447  FX_BOOL GetRGB(FX_FLOAT* pBuf,
448                 FX_FLOAT& R,
449                 FX_FLOAT& G,
450                 FX_FLOAT& B) const override;
451  CPDF_ColorSpace* GetBaseCS() const override;
452
453 private:
454  CPDF_ColorSpace* m_pBaseCS;
455  CPDF_CountedColorSpace* m_pCountedBaseCS;
456};
457
458void PDF_ReplaceAbbr(CPDF_Object* pObj);
459
460#endif  // CORE_SRC_FPDFAPI_FPDF_PAGE_PAGEINT_H_
461