// 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_INCLUDE_FPDFAPI_FPDF_PAGEOBJ_H_ #define CORE_INCLUDE_FPDFAPI_FPDF_PAGEOBJ_H_ #include "core/include/fxge/fx_ge.h" #include "fpdf_resource.h" class CPDF_ClipPath; class CPDF_ClipPathData; class CPDF_ColorState; class CPDF_ColorStateData; class CPDF_ContentMark; class CPDF_ContentMarkItem; class CPDF_FormObject; class CPDF_GeneralState; class CPDF_GeneralStateData; class CPDF_GraphicStates; class CPDF_GraphState; class CPDF_ImageObject; class CPDF_PageObject; class CPDF_Path; class CPDF_PathObject; class CPDF_ShadingObject; class CPDF_TextObject; class CPDF_TextState; class CPDF_TextStateData; class CPDF_TransferFunc; typedef CFX_PathData CPDF_PathData; class CPDF_Path : public CFX_CountRef<CFX_PathData> { public: int GetPointCount() { return m_pObject->m_PointCount; } int GetFlag(int index) { return m_pObject->m_pPoints[index].m_Flag; } FX_FLOAT GetPointX(int index) { return m_pObject->m_pPoints[index].m_PointX; } FX_FLOAT GetPointY(int index) { return m_pObject->m_pPoints[index].m_PointY; } FX_PATHPOINT* GetPoints() { return m_pObject->m_pPoints; } CFX_FloatRect GetBoundingBox() const { return m_pObject->GetBoundingBox(); } CFX_FloatRect GetBoundingBox(FX_FLOAT line_width, FX_FLOAT miter_limit) const { return m_pObject->GetBoundingBox(line_width, miter_limit); } void Transform(const CFX_Matrix* pMatrix) { GetModify()->Transform(pMatrix); } void Append(CPDF_Path src, const CFX_Matrix* pMatrix) { m_pObject->Append(src.m_pObject, pMatrix); } void AppendRect(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top) { m_pObject->AppendRect(left, bottom, right, top); } FX_BOOL IsRect() const { return m_pObject->IsRect(); } }; class CPDF_ClipPathData { public: CPDF_ClipPathData(); CPDF_ClipPathData(const CPDF_ClipPathData&); ~CPDF_ClipPathData(); void SetCount(int path_count, int text_count); public: int m_PathCount; CPDF_Path* m_pPathList; uint8_t* m_pTypeList; int m_TextCount; CPDF_TextObject** m_pTextList; }; class CPDF_ClipPath : public CFX_CountRef<CPDF_ClipPathData> { public: FX_DWORD GetPathCount() const { return m_pObject->m_PathCount; } CPDF_Path GetPath(int i) const { return m_pObject->m_pPathList[i]; } int GetClipType(int i) const { return m_pObject->m_pTypeList[i]; } FX_DWORD GetTextCount() const { return m_pObject->m_TextCount; } CPDF_TextObject* GetText(int i) const { return m_pObject->m_pTextList[i]; } CFX_FloatRect GetClipBox() const; void AppendPath(CPDF_Path path, int type, FX_BOOL bAutoMerge); void DeletePath(int layer_index); void AppendTexts(CPDF_TextObject** pTexts, int count); void Transform(const CFX_Matrix& matrix); }; class CPDF_ColorStateData { public: CPDF_ColorStateData() : m_FillRGB(0), m_StrokeRGB(0) {} CPDF_ColorStateData(const CPDF_ColorStateData& src); void Default(); CPDF_Color m_FillColor; FX_DWORD m_FillRGB; CPDF_Color m_StrokeColor; FX_DWORD m_StrokeRGB; }; class CPDF_ColorState : public CFX_CountRef<CPDF_ColorStateData> { public: CPDF_Color* GetFillColor() const { return m_pObject ? &m_pObject->m_FillColor : NULL; } CPDF_Color* GetStrokeColor() const { return m_pObject ? &m_pObject->m_StrokeColor : NULL; } void SetFillColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues); void SetStrokeColor(CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues); void SetFillPattern(CPDF_Pattern* pattern, FX_FLOAT* pValue, int nValues); void SetStrokePattern(CPDF_Pattern* pattern, FX_FLOAT* pValue, int nValues); private: void SetColor(CPDF_Color& color, FX_DWORD& rgb, CPDF_ColorSpace* pCS, FX_FLOAT* pValue, int nValues); }; typedef CFX_GraphStateData CPDF_GraphStateData; class CPDF_GraphState : public CFX_CountRef<CFX_GraphStateData> { public: }; class CPDF_TextStateData { public: CPDF_TextStateData(); CPDF_TextStateData(const CPDF_TextStateData& src); ~CPDF_TextStateData(); CPDF_Font* m_pFont; CPDF_Document* m_pDocument; FX_FLOAT m_FontSize; FX_FLOAT m_CharSpace; FX_FLOAT m_WordSpace; FX_FLOAT m_Matrix[4]; int m_TextMode; FX_FLOAT m_CTM[4]; }; class CPDF_TextState : public CFX_CountRef<CPDF_TextStateData> { public: CPDF_Font* GetFont() const { return m_pObject->m_pFont; } void SetFont(CPDF_Font* pFont); FX_FLOAT GetFontSize() const { return m_pObject->m_FontSize; } FX_FLOAT* GetMatrix() const { return m_pObject->m_Matrix; } FX_FLOAT GetFontSizeV() const; FX_FLOAT GetFontSizeH() const; FX_FLOAT GetBaselineAngle() const; FX_FLOAT GetShearAngle() const; }; class CPDF_GeneralStateData { public: CPDF_GeneralStateData(); CPDF_GeneralStateData(const CPDF_GeneralStateData& src); ~CPDF_GeneralStateData(); void SetBlendMode(const CFX_ByteStringC& blend_mode); char m_BlendMode[16]; int m_BlendType; CPDF_Object* m_pSoftMask; FX_FLOAT m_SMaskMatrix[6]; FX_FLOAT m_StrokeAlpha; FX_FLOAT m_FillAlpha; CPDF_Object* m_pTR; CPDF_TransferFunc* m_pTransferFunc; CFX_Matrix m_Matrix; int m_RenderIntent; FX_BOOL m_StrokeAdjust; FX_BOOL m_AlphaSource; FX_BOOL m_TextKnockout; FX_BOOL m_StrokeOP; FX_BOOL m_FillOP; int m_OPMode; CPDF_Object* m_pBG; CPDF_Object* m_pUCR; CPDF_Object* m_pHT; FX_FLOAT m_Flatness; FX_FLOAT m_Smoothness; }; class CPDF_GeneralState : public CFX_CountRef<CPDF_GeneralStateData> { public: void SetRenderIntent(const CFX_ByteString& ri); int GetBlendType() const { return m_pObject ? m_pObject->m_BlendType : FXDIB_BLEND_NORMAL; } int GetAlpha(FX_BOOL bStroke) const { return m_pObject ? FXSYS_round((bStroke ? m_pObject->m_StrokeAlpha : m_pObject->m_FillAlpha) * 255) : 255; } }; class CPDF_ContentMarkItem { public: typedef enum { None, PropertiesDict, DirectDict, MCID } ParamType; CPDF_ContentMarkItem(); CPDF_ContentMarkItem(const CPDF_ContentMarkItem& src); ~CPDF_ContentMarkItem(); inline const CFX_ByteString& GetName() const { return m_MarkName; } inline ParamType GetParamType() const { return m_ParamType; } inline void* GetParam() const { return m_pParam; } inline FX_BOOL HasMCID() const; inline void SetName(const CFX_ByteString& name) { m_MarkName = name; } inline void SetParam(ParamType type, void* param) { m_ParamType = type; m_pParam = param; } private: CFX_ByteString m_MarkName; ParamType m_ParamType; void* m_pParam; }; class CPDF_ContentMarkData { public: CPDF_ContentMarkData() {} CPDF_ContentMarkData(const CPDF_ContentMarkData& src); inline int CountItems() const { return m_Marks.GetSize(); } inline CPDF_ContentMarkItem& GetItem(int index) const { return m_Marks[index]; } int GetMCID() const; void AddMark(const CFX_ByteString& name, CPDF_Dictionary* pDict, FX_BOOL bDictNeedClone); void DeleteLastMark(); private: CFX_ObjectArray<CPDF_ContentMarkItem> m_Marks; }; class CPDF_ContentMark : public CFX_CountRef<CPDF_ContentMarkData> { public: int GetMCID() const { return m_pObject ? m_pObject->GetMCID() : -1; } FX_BOOL HasMark(const CFX_ByteStringC& mark) const; FX_BOOL LookupMark(const CFX_ByteStringC& mark, CPDF_Dictionary*& pDict) const; }; #define PDFPAGE_TEXT 1 #define PDFPAGE_PATH 2 #define PDFPAGE_IMAGE 3 #define PDFPAGE_SHADING 4 #define PDFPAGE_FORM 5 class CPDF_GraphicStates { public: void CopyStates(const CPDF_GraphicStates& src); void DefaultStates(); CPDF_ClipPath m_ClipPath; CPDF_GraphState m_GraphState; CPDF_ColorState m_ColorState; CPDF_TextState m_TextState; CPDF_GeneralState m_GeneralState; }; class CPDF_PageObject : public CPDF_GraphicStates { public: static CPDF_PageObject* Create(int type); virtual ~CPDF_PageObject(); CPDF_PageObject* Clone() const; void Copy(const CPDF_PageObject* pSrcObject); virtual void Transform(const CFX_Matrix& matrix) = 0; void RemoveClipPath(); void AppendClipPath(CPDF_Path path, int type, FX_BOOL bAutoMerge); void CopyClipPath(CPDF_PageObject* pObj); void TransformClipPath(CFX_Matrix& matrix); void TransformGeneralState(CFX_Matrix& matrix); void SetColorState(CPDF_ColorState state) { m_ColorState = state; } FX_RECT GetBBox(const CFX_Matrix* pMatrix) const; int m_Type; FX_FLOAT m_Left; FX_FLOAT m_Right; FX_FLOAT m_Top; FX_FLOAT m_Bottom; CPDF_ContentMark m_ContentMark; protected: virtual void CopyData(const CPDF_PageObject* pSrcObject) = 0; void RecalcBBox(); CPDF_PageObject() {} }; struct CPDF_TextObjectItem { FX_DWORD m_CharCode; FX_FLOAT m_OriginX; FX_FLOAT m_OriginY; }; class CPDF_TextObject : public CPDF_PageObject { public: CPDF_TextObject(); ~CPDF_TextObject() override; int CountItems() const { return m_nChars; } void GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const; int CountChars() const; void GetCharInfo(int index, FX_DWORD& charcode, FX_FLOAT& kerning) const; void GetCharInfo(int index, CPDF_TextObjectItem* pInfo) const; void GetCharRect(int index, CFX_FloatRect& rect) const; FX_FLOAT GetCharWidth(FX_DWORD charcode) const; FX_FLOAT GetSpaceCharWidth() const; FX_FLOAT GetPosX() const { return m_PosX; } FX_FLOAT GetPosY() const { return m_PosY; } void GetTextMatrix(CFX_Matrix* pMatrix) const; CPDF_Font* GetFont() const { return m_TextState.GetFont(); } FX_FLOAT GetFontSize() const { return m_TextState.GetFontSize(); } void SetEmpty(); void SetText(const CFX_ByteString& text); void SetText(CFX_ByteString* pStrs, FX_FLOAT* pKerning, int nSegs); void SetText(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pKernings); void SetPosition(FX_FLOAT x, FX_FLOAT y); void SetTextState(CPDF_TextState TextState); // CPDF_PageObject: void Transform(const CFX_Matrix& matrix) override; void CalcCharPos(FX_FLOAT* pPosArray) const; void SetData(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, FX_FLOAT x, FX_FLOAT y); void GetData(int& nChars, FX_DWORD*& pCharCodes, FX_FLOAT*& pCharPos) { nChars = m_nChars; pCharCodes = m_pCharCodes; pCharPos = m_pCharPos; } void RecalcPositionData() { CalcPositionData(nullptr, nullptr, 1); } protected: friend class CPDF_RenderStatus; friend class CPDF_StreamContentParser; friend class CPDF_TextRenderer; friend class CTextPage; // CPDF_PageObject: void CopyData(const CPDF_PageObject* pSrcObject) override; void SetSegments(const CFX_ByteString* pStrs, FX_FLOAT* pKerning, int nSegs); void CalcPositionData(FX_FLOAT* pTextAdvanceX, FX_FLOAT* pTextAdvanceY, FX_FLOAT horz_scale, int level = 0); FX_FLOAT m_PosX; FX_FLOAT m_PosY; int m_nChars; FX_DWORD* m_pCharCodes; FX_FLOAT* m_pCharPos; }; class CPDF_PathObject : public CPDF_PageObject { public: CPDF_PathObject() { m_Type = PDFPAGE_PATH; } ~CPDF_PathObject() override {} void Transform(const CFX_Matrix& maxtrix) override; void SetGraphState(CPDF_GraphState GraphState); void CalcBoundingBox(); CPDF_Path m_Path; int m_FillType; FX_BOOL m_bStroke; CFX_Matrix m_Matrix; protected: void CopyData(const CPDF_PageObject* pSrcObject) override; }; class CPDF_ImageObject : public CPDF_PageObject { public: CPDF_ImageObject(); ~CPDF_ImageObject() override; void Transform(const CFX_Matrix& matrix) override; CPDF_Image* m_pImage; CFX_Matrix m_Matrix; void CalcBoundingBox(); private: void CopyData(const CPDF_PageObject* pSrcObject) override; }; class CPDF_ShadingObject : public CPDF_PageObject { public: CPDF_ShadingObject(); ~CPDF_ShadingObject() override; CPDF_ShadingPattern* m_pShading; CFX_Matrix m_Matrix; void Transform(const CFX_Matrix& matrix) override; void CalcBoundingBox(); protected: void CopyData(const CPDF_PageObject* pSrcObject) override; }; class CPDF_FormObject : public CPDF_PageObject { public: CPDF_FormObject() { m_Type = PDFPAGE_FORM; m_pForm = NULL; } ~CPDF_FormObject() override; void Transform(const CFX_Matrix& matrix) override; CPDF_Form* m_pForm; CFX_Matrix m_FormMatrix; void CalcBoundingBox(); protected: void CopyData(const CPDF_PageObject* pSrcObject) override; }; #endif // CORE_INCLUDE_FPDFAPI_FPDF_PAGEOBJ_H_