blob: 30c58745c61eeb4bcd53ebb37ecdfe12f133c791 [file] [log] [blame]
// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#ifndef CORE_FPDFAPI_FPDF_PAGE_PAGEINT_H_
#define CORE_FPDFAPI_FPDF_PAGE_PAGEINT_H_
#include <map>
#include <memory>
#include <unordered_map>
#include <set>
#include <vector>
#include "core/fpdfapi/fpdf_page/cpdf_contentmark.h"
#include "core/fpdfapi/fpdf_page/cpdf_countedobject.h"
#include "core/fpdfapi/fpdf_page/include/cpdf_pageobjectholder.h"
#include "core/fxge/include/fx_ge.h"
class CPDF_AllStates;
class CPDF_ColorSpace;
class CPDF_ExpIntFunc;
class CPDF_Font;
class CPDF_FontEncoding;
class CPDF_Form;
class CPDF_IccProfile;
class CPDF_Image;
class CPDF_ImageObject;
class CPDF_Page;
class CPDF_Pattern;
class CPDF_SampledFunc;
class CPDF_StitchFunc;
class CPDF_StreamAcc;
class CPDF_TextObject;
class CPDF_Type3Char;
#define PARSE_STEP_LIMIT 100
class CPDF_StreamParser {
public:
enum SyntaxType { EndOfData, Number, Keyword, Name, Others };
CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize);
~CPDF_StreamParser();
CPDF_Stream* ReadInlineStream(CPDF_Document* pDoc,
CPDF_Dictionary* pDict,
CPDF_Object* pCSObj);
SyntaxType ParseNextElement();
uint8_t* GetWordBuf() { return m_WordBuffer; }
uint32_t GetWordSize() const { return m_WordSize; }
CPDF_Object* GetObject() {
CPDF_Object* pObj = m_pLastObj;
m_pLastObj = nullptr;
return pObj;
}
uint32_t GetPos() const { return m_Pos; }
void SetPos(uint32_t pos) { m_Pos = pos; }
CPDF_Object* ReadNextObject(bool bAllowNestedArray, uint32_t dwInArrayLevel);
protected:
friend class fpdf_page_parser_old_ReadHexString_Test;
void GetNextWord(FX_BOOL& bIsNumber);
CFX_ByteString ReadString();
CFX_ByteString ReadHexString();
const uint8_t* m_pBuf;
// Length in bytes of m_pBuf.
uint32_t m_Size;
// Current byte position within m_pBuf.
uint32_t m_Pos;
uint8_t m_WordBuffer[256];
uint32_t m_WordSize;
CPDF_Object* m_pLastObj;
private:
bool PositionIsInBounds() const;
};
#define PARAM_BUF_SIZE 16
struct ContentParam {
enum Type { OBJECT = 0, NUMBER, NAME };
Type m_Type;
union {
struct {
bool m_bInteger;
union {
int m_Integer;
FX_FLOAT m_Float;
};
} m_Number;
CPDF_Object* m_pObject;
struct {
int m_Len;
char m_Buffer[32];
} m_Name;
};
};
#define _FPDF_MAX_FORM_LEVEL_ 30
#define _FPDF_MAX_TYPE3_FORM_LEVEL_ 4
class CPDF_StreamContentParser {
public:
CPDF_StreamContentParser(CPDF_Document* pDoc,
CPDF_Dictionary* pPageResources,
CPDF_Dictionary* pParentResources,
const CFX_Matrix* pmtContentToUser,
CPDF_PageObjectHolder* pObjectHolder,
CPDF_Dictionary* pResources,
CFX_FloatRect* pBBox,
CPDF_AllStates* pAllStates,
int level);
~CPDF_StreamContentParser();
CPDF_PageObjectHolder* GetPageObjectHolder() const { return m_pObjectHolder; }
CPDF_AllStates* GetCurStates() const { return m_pCurStates.get(); }
FX_BOOL IsColored() const { return m_bColored; }
const FX_FLOAT* GetType3Data() const { return m_Type3Data; }
void AddNumberParam(const FX_CHAR* str, int len);
void AddObjectParam(CPDF_Object* pObj);
void AddNameParam(const FX_CHAR* name, int size);
int GetNextParamPos();
void ClearAllParams();
CPDF_Object* GetObject(uint32_t index);
CFX_ByteString GetString(uint32_t index);
FX_FLOAT GetNumber(uint32_t index);
int GetInteger(uint32_t index) { return (int32_t)(GetNumber(index)); }
void OnOperator(const FX_CHAR* op);
void BigCaseCaller(int index);
uint32_t GetParsePos() { return m_pSyntax->GetPos(); }
void AddTextObject(CFX_ByteString* pText,
FX_FLOAT fInitKerning,
FX_FLOAT* pKerning,
int count);
void ConvertUserSpace(FX_FLOAT& x, FX_FLOAT& y);
void ConvertTextSpace(FX_FLOAT& x, FX_FLOAT& y);
void OnChangeTextMatrix();
uint32_t Parse(const uint8_t* pData, uint32_t dwSize, uint32_t max_cost);
void ParsePathObject();
void AddPathPoint(FX_FLOAT x, FX_FLOAT y, int flag);
void AddPathRect(FX_FLOAT x, FX_FLOAT y, FX_FLOAT w, FX_FLOAT h);
void AddPathObject(int FillType, FX_BOOL bStroke);
CPDF_ImageObject* AddImage(CPDF_Stream* pStream,
CPDF_Image* pImage,
bool bInline);
void AddDuplicateImage();
void AddForm(CPDF_Stream* pStream);
void SetGraphicStates(CPDF_PageObject* pObj,
FX_BOOL bColor,
FX_BOOL bText,
FX_BOOL bGraph);
void SaveStates(CPDF_AllStates* pState);
void RestoreStates(CPDF_AllStates* pState);
CPDF_Font* FindFont(const CFX_ByteString& name);
CPDF_ColorSpace* FindColorSpace(const CFX_ByteString& name);
CPDF_Pattern* FindPattern(const CFX_ByteString& name, bool bShading);
CPDF_Object* FindResourceObj(const CFX_ByteString& type,
const CFX_ByteString& name);
protected:
using OpCodes =
std::unordered_map<uint32_t, void (CPDF_StreamContentParser::*)()>;
static OpCodes InitializeOpCodes();
void Handle_CloseFillStrokePath();
void Handle_FillStrokePath();
void Handle_CloseEOFillStrokePath();
void Handle_EOFillStrokePath();
void Handle_BeginMarkedContent_Dictionary();
void Handle_BeginImage();
void Handle_BeginMarkedContent();
void Handle_BeginText();
void Handle_CurveTo_123();
void Handle_ConcatMatrix();
void Handle_SetColorSpace_Fill();
void Handle_SetColorSpace_Stroke();
void Handle_SetDash();
void Handle_SetCharWidth();
void Handle_SetCachedDevice();
void Handle_ExecuteXObject();
void Handle_MarkPlace_Dictionary();
void Handle_EndImage();
void Handle_EndMarkedContent();
void Handle_EndText();
void Handle_FillPath();
void Handle_FillPathOld();
void Handle_EOFillPath();
void Handle_SetGray_Fill();
void Handle_SetGray_Stroke();
void Handle_SetExtendGraphState();
void Handle_ClosePath();
void Handle_SetFlat();
void Handle_BeginImageData();
void Handle_SetLineJoin();
void Handle_SetLineCap();
void Handle_SetCMYKColor_Fill();
void Handle_SetCMYKColor_Stroke();
void Handle_LineTo();
void Handle_MoveTo();
void Handle_SetMiterLimit();
void Handle_MarkPlace();
void Handle_EndPath();
void Handle_SaveGraphState();
void Handle_RestoreGraphState();
void Handle_Rectangle();
void Handle_SetRGBColor_Fill();
void Handle_SetRGBColor_Stroke();
void Handle_SetRenderIntent();
void Handle_CloseStrokePath();
void Handle_StrokePath();
void Handle_SetColor_Fill();
void Handle_SetColor_Stroke();
void Handle_SetColorPS_Fill();
void Handle_SetColorPS_Stroke();
void Handle_ShadeFill();
void Handle_SetCharSpace();
void Handle_MoveTextPoint();
void Handle_MoveTextPoint_SetLeading();
void Handle_SetFont();
void Handle_ShowText();
void Handle_ShowText_Positioning();
void Handle_SetTextLeading();
void Handle_SetTextMatrix();
void Handle_SetTextRenderMode();
void Handle_SetTextRise();
void Handle_SetWordSpace();
void Handle_SetHorzScale();
void Handle_MoveToNextLine();
void Handle_CurveTo_23();
void Handle_SetLineWidth();
void Handle_Clip();
void Handle_EOClip();
void Handle_CurveTo_13();
void Handle_NextLineShowText();
void Handle_NextLineShowText_Space();
void Handle_Invalid();
CPDF_Document* const m_pDocument;
CPDF_Dictionary* m_pPageResources;
CPDF_Dictionary* m_pParentResources;
CPDF_Dictionary* m_pResources;
CPDF_PageObjectHolder* m_pObjectHolder;
int m_Level;
CFX_Matrix m_mtContentToUser;
CFX_FloatRect m_BBox;
ContentParam m_ParamBuf[PARAM_BUF_SIZE];
uint32_t m_ParamStartPos;
uint32_t m_ParamCount;
CPDF_StreamParser* m_pSyntax;
std::unique_ptr<CPDF_AllStates> m_pCurStates;
CPDF_ContentMark m_CurContentMark;
std::vector<std::unique_ptr<CPDF_TextObject>> m_ClipTextList;
CPDF_TextObject* m_pLastTextObject;
FX_FLOAT m_DefFontSize;
FX_PATHPOINT* m_pPathPoints;
int m_PathPointCount;
int m_PathAllocSize;
FX_FLOAT m_PathStartX;
FX_FLOAT m_PathStartY;
FX_FLOAT m_PathCurrentX;
FX_FLOAT m_PathCurrentY;
uint8_t m_PathClipType;
CFX_ByteString m_LastImageName;
CPDF_Image* m_pLastImage;
CFX_BinaryBuf m_LastImageDict;
CFX_BinaryBuf m_LastImageData;
CPDF_Dictionary* m_pLastImageDict;
CPDF_Dictionary* m_pLastCloneImageDict;
FX_BOOL m_bReleaseLastDict;
FX_BOOL m_bSameLastDict;
FX_BOOL m_bColored;
FX_FLOAT m_Type3Data[6];
FX_BOOL m_bResourceMissing;
std::vector<std::unique_ptr<CPDF_AllStates>> m_StateStack;
};
class CPDF_ContentParser {
public:
enum ParseStatus { Ready, ToBeContinued, Done };
CPDF_ContentParser();
~CPDF_ContentParser();
ParseStatus GetStatus() const { return m_Status; }
void Start(CPDF_Page* pPage);
void Start(CPDF_Form* pForm,
CPDF_AllStates* pGraphicStates,
const CFX_Matrix* pParentMatrix,
CPDF_Type3Char* pType3Char,
int level);
void Continue(IFX_Pause* pPause);
private:
enum InternalStage {
STAGE_GETCONTENT = 1,
STAGE_PARSE,
STAGE_CHECKCLIP,
};
ParseStatus m_Status;
InternalStage m_InternalStage;
CPDF_PageObjectHolder* m_pObjectHolder;
FX_BOOL m_bForm;
CPDF_Type3Char* m_pType3Char;
uint32_t m_nStreams;
std::unique_ptr<CPDF_StreamAcc> m_pSingleStream;
std::vector<std::unique_ptr<CPDF_StreamAcc>> m_StreamArray;
uint8_t* m_pData;
uint32_t m_Size;
uint32_t m_CurrentOffset;
std::unique_ptr<CPDF_StreamContentParser> m_pParser;
};
class CPDF_DocPageData {
public:
explicit CPDF_DocPageData(CPDF_Document* pPDFDoc);
~CPDF_DocPageData();
void Clear(FX_BOOL bRelease = FALSE);
CPDF_Font* GetFont(CPDF_Dictionary* pFontDict, FX_BOOL findOnly);
CPDF_Font* GetStandardFont(const CFX_ByteString& fontName,
CPDF_FontEncoding* pEncoding);
void ReleaseFont(const CPDF_Dictionary* pFontDict);
CPDF_ColorSpace* GetColorSpace(CPDF_Object* pCSObj,
const CPDF_Dictionary* pResources);
CPDF_ColorSpace* GetCopiedColorSpace(CPDF_Object* pCSObj);
void ReleaseColorSpace(const CPDF_Object* pColorSpace);
CPDF_Pattern* GetPattern(CPDF_Object* pPatternObj,
FX_BOOL bShading,
const CFX_Matrix& matrix);
void ReleasePattern(const CPDF_Object* pPatternObj);
CPDF_Image* GetImage(CPDF_Object* pImageStream);
void ReleaseImage(const CPDF_Object* pImageStream);
CPDF_IccProfile* GetIccProfile(CPDF_Stream* pIccProfileStream);
void ReleaseIccProfile(const CPDF_IccProfile* pIccProfile);
CPDF_StreamAcc* GetFontFileStreamAcc(CPDF_Stream* pFontStream);
void ReleaseFontFileStreamAcc(const CPDF_Stream* pFontStream);
FX_BOOL IsForceClear() const { return m_bForceClear; }
CPDF_CountedColorSpace* FindColorSpacePtr(CPDF_Object* pCSObj) const;
CPDF_CountedPattern* FindPatternPtr(CPDF_Object* pPatternObj) const;
private:
using CPDF_CountedFont = CPDF_CountedObject<CPDF_Font>;
using CPDF_CountedIccProfile = CPDF_CountedObject<CPDF_IccProfile>;
using CPDF_CountedImage = CPDF_CountedObject<CPDF_Image>;
using CPDF_CountedStreamAcc = CPDF_CountedObject<CPDF_StreamAcc>;
using CPDF_ColorSpaceMap =
std::map<const CPDF_Object*, CPDF_CountedColorSpace*>;
using CPDF_FontFileMap = std::map<const CPDF_Stream*, CPDF_CountedStreamAcc*>;
using CPDF_FontMap = std::map<const CPDF_Dictionary*, CPDF_CountedFont*>;
using CPDF_IccProfileMap =
std::map<const CPDF_Stream*, CPDF_CountedIccProfile*>;
using CPDF_ImageMap = std::map<uint32_t, CPDF_CountedImage*>;
using CPDF_PatternMap = std::map<const CPDF_Object*, CPDF_CountedPattern*>;
CPDF_ColorSpace* GetColorSpaceImpl(CPDF_Object* pCSObj,
const CPDF_Dictionary* pResources,
std::set<CPDF_Object*>* pVisited);
CPDF_Document* const m_pPDFDoc;
FX_BOOL m_bForceClear;
std::map<CFX_ByteString, CPDF_Stream*> m_HashProfileMap;
CPDF_ColorSpaceMap m_ColorSpaceMap;
CPDF_FontFileMap m_FontFileMap;
CPDF_FontMap m_FontMap;
CPDF_IccProfileMap m_IccProfileMap;
CPDF_ImageMap m_ImageMap;
CPDF_PatternMap m_PatternMap;
};
class CPDF_Function {
public:
enum class Type {
kTypeInvalid = -1,
kType0Sampled = 0,
kType2ExpotentialInterpolation = 2,
kType3Stitching = 3,
kType4PostScript = 4,
};
static std::unique_ptr<CPDF_Function> Load(CPDF_Object* pFuncObj);
static Type IntegerToFunctionType(int iType);
virtual ~CPDF_Function();
FX_BOOL Call(FX_FLOAT* inputs,
uint32_t ninputs,
FX_FLOAT* results,
int& nresults) const;
uint32_t CountInputs() const { return m_nInputs; }
uint32_t CountOutputs() const { return m_nOutputs; }
FX_FLOAT GetDomain(int i) const { return m_pDomains[i]; }
FX_FLOAT GetRange(int i) const { return m_pRanges[i]; }
const CPDF_SampledFunc* ToSampledFunc() const;
const CPDF_ExpIntFunc* ToExpIntFunc() const;
const CPDF_StitchFunc* ToStitchFunc() const;
protected:
explicit CPDF_Function(Type type);
FX_BOOL Init(CPDF_Object* pObj);
virtual FX_BOOL v_Init(CPDF_Object* pObj) = 0;
virtual FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const = 0;
uint32_t m_nInputs;
uint32_t m_nOutputs;
FX_FLOAT* m_pDomains;
FX_FLOAT* m_pRanges;
const Type m_Type;
};
class CPDF_ExpIntFunc : public CPDF_Function {
public:
CPDF_ExpIntFunc();
~CPDF_ExpIntFunc() override;
// CPDF_Function
FX_BOOL v_Init(CPDF_Object* pObj) override;
FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override;
uint32_t m_nOrigOutputs;
FX_FLOAT m_Exponent;
FX_FLOAT* m_pBeginValues;
FX_FLOAT* m_pEndValues;
};
class CPDF_SampledFunc : public CPDF_Function {
public:
struct SampleEncodeInfo {
FX_FLOAT encode_max;
FX_FLOAT encode_min;
uint32_t sizes;
};
struct SampleDecodeInfo {
FX_FLOAT decode_max;
FX_FLOAT decode_min;
};
CPDF_SampledFunc();
~CPDF_SampledFunc() override;
// CPDF_Function
FX_BOOL v_Init(CPDF_Object* pObj) override;
FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override;
const std::vector<SampleEncodeInfo>& GetEncodeInfo() const {
return m_EncodeInfo;
}
uint32_t GetBitsPerSample() const { return m_nBitsPerSample; }
const CPDF_StreamAcc* GetSampleStream() const {
return m_pSampleStream.get();
}
private:
std::vector<SampleEncodeInfo> m_EncodeInfo;
std::vector<SampleDecodeInfo> m_DecodeInfo;
uint32_t m_nBitsPerSample;
uint32_t m_SampleMax;
std::unique_ptr<CPDF_StreamAcc> m_pSampleStream;
};
class CPDF_StitchFunc : public CPDF_Function {
public:
CPDF_StitchFunc();
~CPDF_StitchFunc() override;
// CPDF_Function
FX_BOOL v_Init(CPDF_Object* pObj) override;
FX_BOOL v_Call(FX_FLOAT* inputs, FX_FLOAT* results) const override;
const std::vector<std::unique_ptr<CPDF_Function>>& GetSubFunctions() const {
return m_pSubFunctions;
}
FX_FLOAT GetBound(size_t i) const { return m_pBounds[i]; }
private:
std::vector<std::unique_ptr<CPDF_Function>> m_pSubFunctions;
FX_FLOAT* m_pBounds;
FX_FLOAT* m_pEncode;
static const uint32_t kRequiredNumInputs = 1;
};
class CPDF_IccProfile {
public:
CPDF_IccProfile(const uint8_t* pData, uint32_t dwSize);
~CPDF_IccProfile();
uint32_t GetComponents() const { return m_nSrcComponents; }
FX_BOOL m_bsRGB;
void* m_pTransform;
private:
uint32_t m_nSrcComponents;
};
class CPDF_DeviceCS : public CPDF_ColorSpace {
public:
CPDF_DeviceCS(CPDF_Document* pDoc, int family);
FX_BOOL GetRGB(FX_FLOAT* pBuf,
FX_FLOAT& R,
FX_FLOAT& G,
FX_FLOAT& B) const override;
FX_BOOL SetRGB(FX_FLOAT* pBuf,
FX_FLOAT R,
FX_FLOAT G,
FX_FLOAT B) const override;
FX_BOOL v_GetCMYK(FX_FLOAT* pBuf,
FX_FLOAT& c,
FX_FLOAT& m,
FX_FLOAT& y,
FX_FLOAT& k) const override;
FX_BOOL v_SetCMYK(FX_FLOAT* pBuf,
FX_FLOAT c,
FX_FLOAT m,
FX_FLOAT y,
FX_FLOAT k) const override;
void TranslateImageLine(uint8_t* pDestBuf,
const uint8_t* pSrcBuf,
int pixels,
int image_width,
int image_height,
FX_BOOL bTransMask = FALSE) const override;
};
class CPDF_PatternCS : public CPDF_ColorSpace {
public:
explicit CPDF_PatternCS(CPDF_Document* pDoc);
~CPDF_PatternCS() override;
FX_BOOL v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override;
FX_BOOL GetRGB(FX_FLOAT* pBuf,
FX_FLOAT& R,
FX_FLOAT& G,
FX_FLOAT& B) const override;
CPDF_ColorSpace* GetBaseCS() const override;
private:
CPDF_ColorSpace* m_pBaseCS;
CPDF_CountedColorSpace* m_pCountedBaseCS;
};
#define MAX_PATTERN_COLORCOMPS 16
struct PatternValue {
CPDF_Pattern* m_pPattern;
CPDF_CountedPattern* m_pCountedPattern;
int m_nComps;
FX_FLOAT m_Comps[MAX_PATTERN_COLORCOMPS];
};
CFX_ByteStringC PDF_FindKeyAbbreviationForTesting(const CFX_ByteStringC& abbr);
CFX_ByteStringC PDF_FindValueAbbreviationForTesting(
const CFX_ByteStringC& abbr);
void PDF_ReplaceAbbr(CPDF_Object* pObj);
bool IsPathOperator(const uint8_t* buf, size_t len);
#endif // CORE_FPDFAPI_FPDF_PAGE_PAGEINT_H_