/*--------------------------------------------------------+
 | DynaPDF 4.0                                            |
 +--------------------------------------------------------+
 | Copyright (C) 2003-2023                                |
 | Jens Boschulte @ DynaForms GmbH. All rights reserved.  |
 +--------------------------------------------------------+
 | Please report errors or other potential problems to    |
 | info@dynaforms.com.                                    |
 | The current version is available at www.dynaforms.com. |
 +--------------------------------------------------------*/

#ifndef pdf_parser_interfaceH
#define pdf_parser_interfaceH

#include "dynapdf.h"

#include <math.h>

#ifdef __cplusplus
namespace DynaPDF
{
#endif

typedef enum TNodeFlags
{
   nfDefault  = 0,
   nfIsolated = 1, // Transparency groups only
   nfKnockout = 2, // Transparency groups only
   nfLoaded   = 4, // If set, the template or pattern was already loaded
   nfVisible  = 8  // If set, the object is visible (this is the layer state and has nothing to do with clipping)
}TNodeFlags;

typedef enum TPDFOperator
{
   opNull,                 // This represents a deleted node.
   opBeginCompatibility,   // No params -> Ignore unknown operators until the section is terminated with opEndCompatibility.
   opBeginMarkedContent,   // TBeginMarkedContentOP
   opBeginText,            // No params
   opClipPath,             // TClipPathOP
   opClipPathExt,          // TClipPathExt
   opDrawImage,            // TDrawImageOP
   opDrawInlineImage,      // TDrawInlineImageOP
   opDrawPath,             // TDrawPathOP
   opDrawPathExt,          // TDrawPathExt
   opDrawShading,          // TDrawShadingOP
   opDrawTemplate,         // TDrawTemplateOP
   opDrawTranspGroup,      // TDrawGroupOP
   opEndCompatibility,     // No params
   opEndMarkedContent,     // No params
   opEndText,              // No params
   opInitType3Glyph0,      // TInitType3Glyph0OP
   opInitType3Glyph1,      // TInitType3Glyph1OP
   opInsertPostscript,     // TInsertPostscriptOP -> Can be considered when printing on a Postscript device.
   opMarkedContPoint,      // TMarkedContPntOP
   opMulMatrix,            // TMulMatrixOP
   opPageHeader,           // TPageHeader
   opRestoreGS,            // No params
   opSaveGS,               // No params
   opSetCharSpacing,       // TFloatOP
   opSetExtGState,         // TSetExtGStateOP
   opSetFillColor,         // TSetColorOP
   opSetFillColorSpace,    // TSetColorSpaceOP
   opSetFillPattern,       // TSetPatternOP
   opSetFlatnessTolerance, // TFloatOP
   opSetFont,              // TSetFontOP
   opSetLineCapStyle,      // TIntOP
   opSetLineDashPattern,   // TSetLineDashPatternOP
   opSetLineJoinStyle,     // TIntOP
   opSetLineWidth,         // TFloatOP
   opSetMiterLimit,        // TFloatOP
   opSetRenderingIntent,   // TIntOP
   opSetStrokeColor,       // TSetColorOP
   opSetStrokeColorSpace,  // TSetColorSpaceOP
   opSetStrokePattern,     // TSetPatternOP
   opSetTextDrawMode,      // TIntOP
   opSetTextScale,         // TFloatOP
   opSetWordSpacing,       // TFloatOP
   opShowText              // TShowTextOP
}TPDFOperator;

/* ------------------------------- Path construction ------------------------------ */

typedef enum TPDFPathOP
{
   poBezier1   = 0, // TBezier1OP
   poBezier2   = 1, // TBezier2OP
   poBezier3   = 2, // TBezier3OP
   poClosePath = 3, // TClosePathOP
   poLineTo    = 4, // TLineToOP
   poMoveTo    = 5, // TMoveToOP
   poRectangle = 6  // TRectangleOP
}TPDFPathOP;

struct TBezier1OP
{
   float x1;
   float y1;
   float x3;
   float y3;
};

struct TBezier2OP
{
   float x2;
   float y2;
   float x3;
   float y3;
};

struct TBezier3OP
{
   float x1;
   float y1;
   float x2;
   float y2;
   float x3;
   float y3;
};

struct TLineToOP
{
   float x;
   float y;
};

typedef struct TLineToOP TMoveToOP;

struct TRectangleOP
{
   float x;      // Original coordinate
   float y;      // Original coordinate
   float Width;  // Original width
   float Height; // Original height
};

/* -------------------------------------------------------------------------------- */

#define PDF_FORM_FIELD 0x80000000            // Flag to distinguish between ordinary annotations and form fields.

struct TPageHeader
{
   UI32*     Actions;                        // Array of action handles. Top level handles, excluding further actions which can be referenced by the Next key.
   UI32      ActionsCount;                   // Number of actions in the array.
   UI32*     Annots;                         // Array of annotation handles. This array includes form fields. A form field has the PDF_FORM_FIELD flag set.
   UI32      AnnotsCount;                    // Number of annotation handles in the array.

   IPDFObj*  DefaultGray;                    // Default Gray color space if set.
   IPDFObj*  DefaultRGB;                     // Default RGB color space if set.
   IPDFObj*  DefaultCMYK;                    // Default CMYK color space if set.

   LBOOL     HaveBBoxes;                     // If true, bounding boxes of all objects were computed.
   LBOOL     HaveBlackGeneration;            // If true, one or more black generation functions are defined in extended graphics state dictionaries.
   LBOOL     HaveTransferFuncs;              // If true, one or more transfer functions are defined in extended graphics state dictionaries.
   LBOOL     HaveTransparency;               // If true, transparent objects are drawn on the page.
   LBOOL     HaveUnderColorRemoval;          // If true, one or more undercolor-removal functions are defined in extended graphics state dictionaries.

   UI32      NumClipPaths;                   // Number of used clipping paths.
   UI32      NumColorants;                   // Maximum number of colorants used in all referenced color spaces.
   UI32      NumGroups;                      // Number of transparency groups.
   UI32      NumImages;                      // Number of images.
   UI32      NumPaths;                       // Number of paths.
   UI32      NumPatterns;                    // Number of patterns.
   UI32      NumTemplates;                   // Number of templates.
   UI32      NumTextRecords;                 // Number of text records.
   TTabOrder TabOrder;                       // Optional tab order for annotations and form fields. Default -> toNone.
};

struct TSetColor
{
   float*         Color;
   TExtColorSpace ColorSpace;
   IPDFObj*       ColorSpaceObj;
   UI32           NumComponents;
};

static PDF_INLINE TBlendMode       psrGetBlendMode(UI32 DrawParms)                               {return (TBlendMode)(DrawParms & 0xFF);}                    // Used internally
static PDF_INLINE LBOOL            psrIsInvisible(UI32 DrawParms, LBOOL FillClr)                 {return FillClr ? ((DrawParms >> 28) & 1) != 0 : ((DrawParms >> 28) & 2) != 0;}
static PDF_INLINE TLineCapStyle    psrGetLineCapStyle(UI32 DrawParms)                            {return (TLineCapStyle)   ((DrawParms >>  8) & 3);}
static PDF_INLINE TLineJoinStyle   psrGetLineJoinStyle(UI32 DrawParms)                           {return (TLineJoinStyle)  ((DrawParms >> 12) & 3);}
static PDF_INLINE TRenderingIntent psrGetRenderingIntent(UI32 DrawParms)                         {return (TRenderingIntent)((DrawParms >> 16) & 0x0F);}
static PDF_INLINE TDrawMode        psrGetTextDrawMode(UI32 DrawParms)                            {return (TDrawMode)       ((DrawParms >> 20) & 0xFF);}
static PDF_INLINE void             psrSetBlendMode(UI32* DrawParms, UI32 Value)                  {*(DrawParms) &= ~0x000000FF; *(DrawParms) |= Value;}       // Used internally
static PDF_INLINE void             psrSetLineCapStyle(UI32* DrawParms, TLineCapStyle Value)      {*(DrawParms) &= ~0x00000F00; *(DrawParms) |= Value << 8;}
static PDF_INLINE void             psrSetLineJoinStyle(UI32* DrawParms, TLineJoinStyle Value)    {*(DrawParms) &= ~0x0000F000; *(DrawParms) |= Value << 12;}
static PDF_INLINE void             psrSetRenderingIntent(UI32* DrawParms, TRenderingIntent Value){*(DrawParms) &= ~0x000F0000; *(DrawParms) |= Value << 16;}
static PDF_INLINE void             psrSetTextDrawMode(UI32* DrawParms, TDrawMode Value)          {*(DrawParms) &= ~0x0FF00000; *(DrawParms) |= Value << 20;}

/* -------------------------------------------------------------------------------- */

typedef enum TMarkedContType
{
   mctOCG,           // The Handle parameter is a Optional Content Group (also called Layer).
   mctOCMD,          // The Handle parameter is a Optional Content Membership Dictionary (an OCMD represents a visibility expression).
   mctMarkedContSeq, // A marked content sequence of no specific type.
   mctStructElem     // A marked content sequence having a MCID (Marked Content ID) to access a structure element.
}TMarkedContType;

struct TBeginMarkedContentOP                 // BDC, BMC
{
   SI32                 Handle;              // MCID or handle of an OCG or OCMD.
   LBOOL                Visible;             // Current visibility state.
   TMarkedContType      MCType;              // The type of marked content.
   BYTE*                Name;                // Internal link name of a named resource.
   BYTE*                Parms;               // Optional parameters (null-terminated string if present (inline dictionary)).
   UI32                 ParmsLen;            // Length in bytes.
   IPDFObj*             PDFObject;           // Pointer of a PDF object if the operator references one. This is usually a structure element.
   BYTE*                Tag;                 // The marked content tag (null-terminated string).
   UI32                 TagLen;              // Length in bytes.
};

struct TClipPathOP
{
   struct TBBox         BBox;
   TPathFillMode        Mode;                // Path fill mode.
   BYTE*                OP;                  // Operant array that specifies the type of data in the Elems array.
   UI32                 OPCount;             // The number of operants in the array ElemOP.
   struct TFltPoint*    Vertices;            // The vertices which define the path.
   UI32                 VerticesCount;       // Number of vertices in the array.
   LBOOL                EvenOdd;             // A clipping path has its own even odd flag. This flag must be considered when creating the clipping area.
};

struct TClipPathExt
{
   struct TBBox         BBox;
   SI32                 Index;               // The index was returned by the TPsrClipPath callback function.
   TPathFillMode        Mode;                // Path fill mode
   LBOOL                EvenOdd;             // A clipping path has its own even odd flag. This flag must be considered when creating the clipping area.
};

#pragma pack(1)
struct TContentOP
{
   BYTE  OP;                                 // Operator to excecute.
   void* Param;                              // It is guaranteed that this pointer is set for operators which have parameters.
};
#pragma pack()

struct TContent
{
   UI32                 Count;               // Number of available operators.
   struct TContentOP*   OP;                  // Array of operators.
};

struct TDrawGroupOP // Transparency group
{
   struct TBBox         BBox;                // The bounding box to enable fast skipping of invisible objects.
   struct TContent      Elems;               // The elements which draw the soft mask or transparency group.
   TNodeFlags           Flags;               // Loading state, visibility state, isolated or non-isolated group, knockout flag. Invisible groups are not loaded by default.
   UI32                 Handle;              // Template handle.
   float                Matrix[6];           // Pre-multiplied matrix to map form space to user space.
   BYTE*                Name;                // Internal link name.
   IPDFObj*             Resources;           // Pointer to internal resource tree of that object.
   IPDFObj*             Template;            // Pointer of the template. A Transparency group is an extended template.
   TExtColorSpace       BlendCS;             // This can be any device or ICC based color space.
   IPDFObj*             BlendCSObj;          // Set only if BlendCS is a non-device space.
   SI32                 OC;                  // OC or OCMD handle or -1 if not set (requires version 4.0.71.196 or higher)
  #ifdef __cplusplus
   bool IsIsolated(void){return (Flags & nfIsolated) != 0;}
   bool IsKnockout(void){return (Flags & nfKnockout) != 0;}
   bool IsVisible(void) {return (Flags & nfVisible)  != 0;}
  #endif
};

struct TDrawImageOP
{
   UI32                 Handle;              // Image handle. Can be used with pdfGetImageObj().
   IPDFObj*             Image;               // Internal object pointer. Can be used with pdfGetImageObjEx().
   SI32                 Index;               // This index is set by the TPsrDrawImage callback function, -1 otherwise. It can be used to access the cached image if created.
   BYTE*                Name;                // Internal link name.
   LBOOL                Visible;             // Layer visibility. If false, the object can be skipped.
   SI32                 OC;                  // OC or OCMD handle or -1 if not set (requires version 4.0.71.196 or higher)
};

struct TDrawInlineImageOP
{
   TExtColorSpace       BaseColorSpace;      // The color space in which the buffer or color table is defined.
   BYTE*                Buffer;              // Image buffer.
   UI32                 BufSize;             // Buffer size in bytes.
   UI32                 BitsPerComponent;    // Valid values are 1, 2, 4, 8, or 16 bits per component.
   UI32                 ColorCount;          // Number of colors in the table.
   TExtColorSpace       ColorSpace;          // If the the image uses an extended color space, like Separation, DeviceN or Indexed, BaseColorSpace is the color space in which the buffer or color table is defined.
   BYTE*                ColorSpaceName;      // Internal link name if not defined inline.
   IPDFObj*             ColorSpaceObj;       // Pointer of the color space object.
   BYTE*                ColorTable;          // Indexed color space only.
   UI32                 ColorTableLen;       // It is guaranteed that the table contains ColorCount values.
   float*               Decode;              // Min/max per component.
   UI32                 Height;              // Image height.
   LBOOL                ImageMask;           // 1 bit images only. If true, non-zero pixel values must be drawn with the current fill color.
   SI32                 Index;               // This index is set by the TPsrDrawInlineImage callback function, -1 otherwise. It can be used to access the cached image if created.
   TRenderingIntent     Intent;              // Rendering intent.
   LBOOL                Interpolate;         // If true, the image should be interpolated.
   UI32                 NumComponents;       // The number of components in the pixel buffer or color table if one is present.
   TDecodeFilter        OrgFilter;           // The image was compressed with this filter. The image is always returned uncompressed.
   LBOOL                Visible;             // Layer visibility. If false, the object can be skipped.
   UI32                 Width;               // Image width.
};

struct TDrawPathOP
{
   struct TBBox         BBox;
   TPathFillMode        Mode;                // Path fill mode.
   BYTE*                OP;                  // Operant array that specifies the type of data in the Elems array.
   UI32                 OPCount;             // The number of operants in the array ElemOP.
   struct TFltPoint*    Vertices;            // The vertices which define the path.
   UI32                 VerticesCount;       // Number of vertices in the array.
};

struct TDrawPathExt
{
   struct TBBox         BBox;
   SI32                 Index;               // The index was returned by the TPsrDrawPath callback function.
   TPathFillMode        Mode;                // Path fill mode.
};

struct TDrawShadingOP
{
   BYTE*                Name;                // Internal link name.
   IPDFObj*             Shading;             // Internal object pointer.
   TShadingType         ShadingType;         // Shading type.
};

struct TDrawTemplateOP
{
   struct TBBox         BBox;
   struct TContent      Elems;
   TNodeFlags           Flags;               // Loading state, visibility state. Invisible templates are not loaded by default.
   UI32                 Handle;              // Template handle.
   float                Matrix[6];           // Pre-multiplied matrix to map form space to user space.
   BYTE*                Name;                // Internal link name.
   IPDFObj*             Resources;           // Pointer to internal resource tree of that object.
   IPDFObj*             Template;            // Pointer of the template object.
   SI32                 OC;                  // OC or OCMD handle or -1 if not set (requires version 4.0.71.196 or higher)
};

struct TFloatOP
{
   float                Value;
};

// The first operator in a Type3 content stream must initialize the type of glyph.
struct TInitType3Glyph0OP                    // The glyph defines the shape and color.
{
   float                Wx;                  // Horizontal displacement.
   float                Wy;                  // Should be zero.
};

struct TInitType3Glyph1OP                    // The glyph defines the shape but no color.
{
   struct TBBox         BBox;                // The glyphs bounding box.
   float                Wx;                  // Horizontal displacement.
   float                Wy;                  // Should be zero.
};

struct TInsertPostscriptOP
{
   BYTE*                Buffer;
   UI32                 Length;
   BYTE*                Name;                // Internal link name.
   IPDFObj*             Template;            // Pointer of the template. PostScript code is stored in a special type of template.
};

struct TIntOP
{
   SI32                 Value;
};

struct TMarkedContPntOP // MP, DP
{
   BYTE*                Name;                // Internal link name of a named resource.
   BYTE*                Parms;               // Optional parameters (null-terminated string if present (inline dictionary)).
   UI32                 ParmsLen;            // Length in bytes.
   IPDFObj*             PDFObject;           // Pointer of a PDF object if the operator references one. This is usually a structure element.
   BYTE*                Tag;                 // Null-terminated string.
   UI32                 TagLen;              // String length.
   LBOOL                Visible;             // Information only.
};

struct TMulMatrixOP
{
   float                Matrix[6];
};

typedef enum TSetColorOPFlags
{
   scofCSMask     = 0x000000FF,              // The color space is encoded in the lower 8 bits.
   scofDefCSShift = 0x00000008,              // Required right shift to extract the base color space: (TPDFColorSpace)((CS >> scofDefCSShift) & scofCSMask).
   scofDefCS      = 0x00010000,              // If set, this is a reference of a default color space.
   scofUsed       = 0x00020000               // If set, the operator was used.
}TSetColorOPFlags;

struct TSetColorOP
{
   UI32                 CS;                  // Color space and various flags. See TSetColorOPFlags for further information.
   UI32                 DeviceColor;         // Set only if the flag cpfCalcDeviceColors is set.
   float*               Value;               // Array of floating point values. One value per component.
   UI32                 NumComponents;       // Number of components.
};

struct TSetColorSpaceOP
{
   UI32                 CS;                  // The color space is encoded in the lower 12 bits -> (TExtColorSpace)(CS & 0xFFF);
                                             // If bit 16 is set, the color space is a default color space -> (CS & 0x20000).
                                             // The underlying base color space is encoded in the upper 8 bits -> (TPDFColorSpace)(CS >> 24).
   IPDFObj*             CSObj;               // Color space object.
   LBOOL                Invisible;           // If true, the color space is fully invisible -> special colorant None.
   BYTE*                Name;                // Internal link name.
};

struct TSoftMaskOP
{
   UI32                 BackColor;           // Isolated groups only.
   TPDFColorSpace       BackColorCS;         // This is always a device color space.
   LBOOL                Luminosity;          // If true, the mask is used as an alpha channel.
   IPDFObj*             Resources;           // Pointer to internal resource tree of that object.
   struct TDrawGroupOP* TranspGroup;         // The transparency group that draws the soft mask.
   IPDFObj*             TransferFunc;        // If set, the result must be passed to the transfer function.
};

struct TSetExtGStateOP
{
   IPDFObj*             ExtGState;           // Pointer of the original object.
   LBOOL                AlphaIsShape;        // PDF_MAX_INT if not set.
   LBOOL                AutoStrokeAdjust;    // PDF_MAX_INT if not set.
   IPDFObj*             BlackGen;            // Function object or NULL.
   IPDFObj*             BlackGen2;           // Function object or NULL.
   TBlendMode           BlendMode;           // Blend mode.
   float                FillAlpha;           // -1.0 if not set.
   float                FlatnessTol;         // -1.0 if not set.
   IPDFObj*             Halftone;            // Halftone object or NULL.
   BYTE*                Name;                // Internal link name.
   LBOOL                OverPrintFill;       // PDF_MAX_INT if not set.
   LBOOL                OverPrintStroke;     // PDF_MAX_INT if not set.
   LBOOL                OverPrintMode;       // PDF_MAX_INT if not set.
   IPDFObj*             PDFObject;           // A pointer of the original object.
   TRenderingIntent     RenderingIntent;     // riNone if not set.
   float                SmoothnessTol;       // -1.0 if not set.
   struct TSoftMaskOP*  SoftMask;            // Soft mask.
   LBOOL                SoftMaskNone;        // If true, the softmask must be disabled.
   float                StrokeAlpha;         // -1.0 if not set.
   LBOOL                TextKnockout;        // PDF_MAX_INT if not set.
   IPDFObj*             TransferFunc;        // Function object or NULL.
   IPDFObj*             TransferFunc2;       // Function object or NULL.
   IPDFObj*             UnderColorRem;       // Function object or NULL.
   IPDFObj*             UnderColorRem2;      // Function object or NULL.
   UI32                 UseBlackPTComp;      // PDF_MAX_INT if not set, 0 = OFF, 1 = ON, 2 = Default.
};

struct TSetFontOP
{
   struct TBBox         FontBBox;            // The scaled bounding box of the largest glyph. The bounding box must be transformed with the current transformation matrix.
   float                FontSize;            // Note that the font size can be negative!
   IPDFObj*             IFont;               // The font can be accessed with fntGetFont().
   BYTE*                Name;                // Internal link name.
};

struct TSetLineDashPatternOP
{
   float*               Dash;                // Can be NULL to disable the active dash pattern.
   UI32                 DashLen;
   float                Phase;
};

struct TSetPatternOP
{
   struct TBBox         BBox;                // Bounding box of the pattern.
   float*               Color;               // Pattern color -> uncolored tiling patterns only.
   TExtColorSpace       CS;                  // The color space in which the color is defined. It was already set with a TSetColorSpaceOP record.
   IPDFObj*             CSObj;               // Corresponding color space object.
   struct TContent      Elems;               // Tiling patterns only.
   struct TSetExtGStateOP* ExtGState;        // Shading patterns only.
   TNodeFlags           Flags;               // Loading state.
   IPDFObj*             Pattern;             // A pointer of the pattern dictionary.
   BYTE*                Name;                // Internal link name.
   UI32                 NumComponents;       // Number of color components.
   TPatternType         PatternType;         // Pattern type.
   IPDFObj*             Resources;           // Pointer to internal resource tree of that object.
   IPDFObj*             Shading;             // Pointer to shading object (shading patterns only).
   float                StepX;               // Tiling patterns only.
   float                StepY;               // Tiling patterns only.
   TTilingType          TilingType;          // The way how a tiling pattern should be drawn.
   float                Matrix[6];           // Matrix to map pattern space to user space.
};

struct SetTextDrawModeOP
{
   TDrawMode            Mode;
};

struct TOutline
{
   float                Matrix[6];
   struct TContent      Elems;
   struct TOutline*     Next;
   IPDFObj*             Stream;              // Pointer of the internal stream object.
   float                Width;               // Unscaled glyph width.
};

struct TTextNode
{
   float                Advance;             // Negative values move the cursor to the right, positive to the left. The value is measured in text space!
   struct TBBox         BBox;                // Bounding box of the text node.
   BYTE*                Text;                // Raw text (not null-terminated).
   UI32                 Length;              // Raw text length in bytes.
   BYTE*                UniCodeLengths;      // The number of source bytes required to encode the Unicode text. One entry for every character in UniText.
   UI16*                UniText;             // Translated Unicode text.
   UI32                 UniTextLength;       // Number of characters in UniText.
   float                Width;               // Full text width measured in text space!
   float*               Widths;              // Glyph widths measured in text space.
   struct TOutline*     Outlines;            // Type3 fonts only. One outline for every character in the text.
   struct TTextNode*    Next;
};

/*
   This structure is set if the flag cpfEnableTextSelection was set.

   The matrix DeviceSpace is calculated for text extraction. This is the vertically mirrored and de-rotated page space matrix
   as it would be calculated when rendering a page. This coordinate system flows from top to down and from left to right.

   The members PosX, PosY, SpaceWidthU, are calculated in DeviceSpace since we need these members to efficiently calucalte the
   visible position of text on a page independent of the object in which it is stored, e.g. in a template or pattern.

   PageSpace maps text space to page space. This matrix is required by psrReplaceSelText() in order to place new text on a page.
   New text is always placed on the page independent on where it was found, e.g. in the page or in a template or pattern.
*/
struct TShowTextExt
{
   struct TBBox         BBox;                // Bounding box of the text record measured in text space.
   float                CharSpacing;         // Optimization for text extraction (user space).
   float                DeviceSpace[6];      // The device space matrix is used to calculate the final position of text on a page. This matrix is used for text extraction and selection.
   struct TSetColorOP*  FillColor;           // Optimization for text extraction.
   IPDFObj*             FillColorCS;         // Color space object -> Optimization for text extraction.
   float                LineWidth;           // Optimization for text extraction.
   float                PageSpace[6];        // Page space matrix that is used to place new text on a page.
   float                PosX;                // Position measured in user space.
   float                PosY;                // Position measured in user space.
   float                SpaceWidthT;         // Space width measured in text space.
   float                SpaceWidthU;         // Space width measured in device space.
   struct TSetColorOP*  StrokeColor;         // Optimization for text extraction.
   IPDFObj*             StrokeColorCS;       // Color space object -> Optimization for text extraction.
   float                TextScale;           // Optimization for text extraction.
   TDrawMode            TextDrawMode;        // Optimization for text extraction.
   float                WordSpacing;         // Optimization for text extraction (device space).
};

struct TShowTextOP
{
   struct TShowTextExt* Ext;                 // Additional properties for text selection and text extraction. This structure is available if the flag cpfEnableTextSelection was set.
   IPDFObj*             Font;                // This is the font that is currently active in the graphics state.
   float                FontSize;            // The active font size.
   UI32                 Index;               // Array index of the operator.
   float                Matrix[6];           // All text positioning operators were taken into account.
   struct TTextNode*    Text;                // One or more text nodes.
   LBOOL                Visible;             // Layer state.
   float                Width;               // The width of the entire text record measured in text space (the sum of all sub nodes).
};

static const UI16 PDF_OP_STRUCT_SIZE[] =
{
   0, // opNull
   0, // opBeginCompatibility
   (UI16)sizeof(struct TBeginMarkedContentOP),
   0, // opBeginText
   (UI16)sizeof(struct TClipPathOP),
   (UI16)sizeof(struct TClipPathExt),
   (UI16)sizeof(struct TDrawImageOP),
   (UI16)sizeof(struct TDrawInlineImageOP),
   (UI16)sizeof(struct TDrawPathOP),
   (UI16)sizeof(struct TDrawPathExt),
   (UI16)sizeof(struct TDrawShadingOP),
   (UI16)sizeof(struct TDrawTemplateOP),
   (UI16)sizeof(struct TDrawGroupOP),
   0, // opEndCompatibility
   0, // opEndMarketContent
   0, // opEndText
   (UI16)sizeof(struct TInitType3Glyph0OP),
   (UI16)sizeof(struct TInitType3Glyph1OP),
   (UI16)sizeof(struct TInsertPostscriptOP),
   (UI16)sizeof(struct TMarkedContPntOP),
   (UI16)sizeof(struct TMulMatrixOP),
   (UI16)sizeof(struct TPageHeader),
   0, // opRestoreGS
   0, // opSaveGS
   (UI16)sizeof(struct TFloatOP),
   (UI16)sizeof(struct TSetExtGStateOP),
   (UI16)sizeof(struct TSetColorOP),
   (UI16)sizeof(struct TSetColorSpaceOP),
   (UI16)sizeof(struct TSetPatternOP),
   (UI16)sizeof(struct TFloatOP),
   (UI16)sizeof(struct TSetFontOP),
   (UI16)sizeof(struct TIntOP),
   (UI16)sizeof(struct TSetLineDashPatternOP),
   (UI16)sizeof(struct TIntOP),
   (UI16)sizeof(struct TFloatOP),
   (UI16)sizeof(struct TFloatOP),
   (UI16)sizeof(struct TIntOP),
   (UI16)sizeof(struct TSetColorOP),
   (UI16)sizeof(struct TSetColorSpaceOP),
   (UI16)sizeof(struct TSetPatternOP),
   (UI16)sizeof(struct TIntOP),
   (UI16)sizeof(struct TFloatOP),
   (UI16)sizeof(struct TFloatOP),
   (UI16)sizeof(struct TShowTextOP)
};

typedef void  PDF_CALL TPsrBeginGroup(const void* Data, struct TDrawGroupOP* OP);
typedef void  PDF_CALL TPsrBeginMarkedContent(const void* Data, struct TBeginMarkedContentOP* OP);
typedef void  PDF_CALL TPsrBeginTemplate(const void* Data, struct TDrawTemplateOP* OP);
typedef SI32  PDF_CALL TPsrClipPath(const void* Data, struct TClipPathOP* OP);
typedef SI32  PDF_CALL TPsrDrawImage(const void* Data, struct TDrawImageOP* OP);
typedef SI32  PDF_CALL TPsrDrawInlineImage(const void* Data, struct TDrawInlineImageOP* OP);
typedef SI32  PDF_CALL TPsrDrawPath(const void* Data, struct TDrawPathOP* OP);
typedef void  PDF_CALL TPsrDrawShading(const void* Data, struct TDrawShadingOP* OP);
typedef void  PDF_CALL TPsrEndMarkedContent(const void* Data, LBOOL Visible);
typedef void  PDF_CALL TPsrInsertPostscript(const void* Data, struct TInsertPostscriptOP* OP);
typedef void  PDF_CALL TPsrMarkedContPnt(const void* Data, struct TMarkedContPntOP* OP);
typedef void  PDF_CALL TPsrMulMatrix(const void* Data, const float Matrix[6]);
typedef void  PDF_CALL TPsrNoParams(const void* Data);
typedef void  PDF_CALL TPsrSetColor(const void* Data, struct TSetColorOP* OP);
typedef void  PDF_CALL TPsrSetColorSpace(const void* Data, struct TSetColorSpaceOP* OP);
typedef void  PDF_CALL TPsrSetExtGState(const void* Data, struct TSetExtGStateOP* OP);
typedef void  PDF_CALL TPsrSetFloat(const void* Data, float Value);
typedef void  PDF_CALL TPsrSetFont(const void* Data, struct TSetFontOP* OP);
typedef void  PDF_CALL TPsrSetLineCapStyle(const void* Data, TLineCapStyle Value);
typedef void  PDF_CALL TPsrSetLineDashPattern(const void* Data, struct TSetLineDashPatternOP* OP);
typedef void  PDF_CALL TPsrSetLineJoinStyle(const void* Data, TLineJoinStyle Value);
typedef void  PDF_CALL TPsrSetPattern(const void* Data, struct TSetPatternOP* OP);
typedef void  PDF_CALL TPsrSetRenderingIntent(const void* Data, TRenderingIntent Value);
typedef void  PDF_CALL TPsrSetTextDrawMode(const void* Data, TDrawMode Value);
typedef void  PDF_CALL TPsrShowText(const void* Data, struct TShowTextOP* OP);

struct TPDFParseCallbacks
{
   UI32                       StructSize;
   TPsrNoParams*              BeginCompatibility;
   TPsrBeginGroup*            BeginGroup;
   TPsrBeginMarkedContent*    BeginMarkedContent;
   TPsrBeginTemplate*         BeginTemplate;
   TPsrNoParams*              BeginText;
   TPsrClipPath*              ClipPath;
   TPsrDrawImage*             DrawImage;
   TPsrDrawInlineImage*       DrawInlineImage;
   TPsrDrawPath*              DrawPath;
   TPsrDrawShading*           DrawShading;
   TPsrNoParams*              EndCompatibility;
   TPsrNoParams*              EndGroup;
   TPsrEndMarkedContent*      EndMarkedContent;
   TPsrNoParams*              EndTemplate;
   TPsrNoParams*              EndText;
   TPsrInsertPostscript*      InsertPostscript;
   TPsrMarkedContPnt*         MarkedContPnt;
   TPsrMulMatrix*             MulMatrix;
   TPsrNoParams*              RestoreGS;
   TPsrNoParams*              SaveGS;
   TPsrSetFloat*              SetCharSpacing;
   TPsrSetExtGState*          SetExtGState;
   TPsrSetColor*              SetFillColor;
   TPsrSetColorSpace*         SetFillColorSpace;
   TPsrSetPattern*            SetFillPattern;
   TPsrSetFloat*              SetFlatnessTolerance;
   TPsrSetFont*               SetFont;
   TPsrSetLineCapStyle*       SetLineCapStyle;
   TPsrSetLineDashPattern*    SetLineDashPattern;
   TPsrSetLineJoinStyle*      SetLineJoinStyle;
   TPsrSetFloat*              SetLineWidth;
   TPsrSetFloat*              SetMiterLimit;
   TPsrSetRenderingIntent*    SetRenderingIntent;
   TPsrSetColor*              SetStrokeColor;
   TPsrSetColorSpace*         SetStrokeColorSpace;
   TPsrSetPattern*            SetStrokePattern;
   TPsrSetTextDrawMode*       SetTextDrawMode;
   TPsrSetFloat*              SetTextScaling;
   TPsrSetFloat*              SetWordSpacing;
   TPsrShowText*              ShowText;
};

typedef enum TContentParseFlags
{
   cpfDefault              = 0x00000000, // Nothing special to do.
   cpfComputeBBox          = 0x00000001, // Compute bounding boxes of all objects.
   cpfFlattenLayers        = 0x00000002, // Flatten layers.
   cpfSkipInvisibleObjects = 0x00000004, // Ignore invisible objects.
   cpfFullRecursive        = 0x00000008, // Parse all objects recursively.
   cpfNoInlineTemplate     = 0x00000010, // Do not resolve templates with a reference count of 1.
   cpfCalcDeviceColors     = 0x00000020, // Compute device colors of all colors which are set in the content streams.
   cpfImidiateMode         = 0x00000040, // Internal. This flag is always set if the TPDFParseCallbacks structure is passed to ParsePage(). It disables certain optimisations.
   cpfNewLinkNames         = 0x00000080, // Internal. Create new link names for all objects. This flag is used by Optimize() and CheckConformance().
   cpfEnableTextSelection  = 0x00000100, // This flag is required to enable text selection and text extraction.
   cpfInitMatrix           = 0x00000200, // The transformation matrix must be set in the TContentParseParms structure.
   cpfSkipClipPaths        = 0x00000400, // Useful for debugging purposes.
   cpfSkipImages           = 0x00000800, // Ignore all images. This flag is useful for text extraction.
   cpfSkipShadings         = 0x00001000, // Useful for debugging purposes.
   cpfSkipText             = 0x00002000, // Useful for debugging purposes.
   cpfSkipVector           = 0x00004000  // Useful for debugging purposes. Exclude vector graphics with exception of clipping paths.
}TContentParseFlags;

struct TContentParseParms
{
   UI32        StructSize;
   struct TCTM InitMatrix; // Considered only if the flag cpfInitMatrix is set.
};

typedef enum TReplaceTextFlags
{
   rtfDefault = 0
}TReplaceTextFlags;

typedef enum TDeleteTextFlags
{
   dtfDefault = 0
}TDeleteTextFlags;

typedef enum TSearchType
{
   stDefault         = 0, // Case sensitive search
   stWholeWord       = 1, // Only whole words
   stCaseInSensitive = 2  // Case insensitive search
}TSearchType;

struct TTextSelection
{
   UI32                   StructSize; // Must be set to sizeof(TTextSelection).
   UI32                   Line;       // Index of the text line.
   struct TCTM            Matrix;     // Text matrix pre-calculated in user space.
   UI32                   Sub1;       // Index of the text node.
   SI32                   Sub2;       // Index of the sub text node.
   SI32                   TextLen;    // How many characters of this record are selected?
   struct TShowTextOP*    TextOP;     // The text record in which the text was found.
   SI32                   TextPos;    // Index where the first character of the search text was found.
   float                  X;          // X-Coordinate in text space
   float                  Y;          // Y-Coordinate in text space
   struct TTextSelection* Next;       // Next record if the search text spans multiple text records.
   struct TTextSelection* Prev;       // Prev record if any.
};

/* ------------------------------------- Helper functions -------------------------------------- */

static inline bool IsCloser(BYTE OP)
{
   switch(OP)
   {
      case opEndCompatibility:
      case opEndMarkedContent:
      case opEndText:
      case opRestoreGS: return true;
      default:          return false;
   }
}

static inline bool IsOpener(BYTE OP)
{
   switch(OP)
   {
      case opBeginCompatibility:
      case opBeginMarkedContent:
      case opBeginText:
      case opSaveGS: return true;
      default:       return false;
   }
}

static inline bool IsGSProperty(BYTE OP)
{
   switch(OP)
   {
      case opClipPath:
      case opClipPathExt:
      case opMulMatrix:
      case opSetCharSpacing:
      case opSetExtGState:
      case opSetFillColor:
      case opSetFillColorSpace:
      case opSetFillPattern:
      case opSetFlatnessTolerance:
      case opSetFont:
      case opSetLineCapStyle:
      case opSetLineDashPattern:
      case opSetLineJoinStyle:
      case opSetLineWidth:
      case opSetMiterLimit:
      case opSetRenderingIntent:
      case opSetStrokeColor:
      case opSetStrokeColorSpace:
      case opSetStrokePattern:
      case opSetTextDrawMode:
      case opSetTextScale:
      case opSetWordSpacing: return true;
      default:               return false;
   }
}

static inline bool IsDrawingCommand(BYTE OP)
{
   switch(OP)
   {
      case opDrawImage:
      case opDrawInlineImage:
      case opDrawPath:
      case opDrawPathExt:
      case opDrawShading:
      case opDrawTemplate:
      case opDrawTranspGroup:
      case opInsertPostscript:
      case opShowText: return true;
      default:         return false;
   }
}

/* ---------------------------------------- Parser API ----------------------------------------- */

PDF_EXP void  PDF_CALL psrAbort(const IPSR* Ctx);
PDF_EXP LBOOL PDF_CALL psrChangeAltFont(const PPDF* IPDF, const IPSR* Ctx, UI32 Handle);
PDF_EXP void  PDF_CALL psrClearSelection(const IPSR* Ctx);
PDF_EXP IPSR* PDF_CALL psrCreateParserContext(const PPDF* IPDF, TOptimizeFlags Flags, struct TOptimizeParams* Parms);
PDF_EXP LBOOL PDF_CALL psrDeleteOperator(const IPSR* Ctx, UI32 Index);
PDF_EXP LBOOL PDF_CALL psrDeleteOperatorInObject(const IPSR* Ctx, IPDFObj* ObjPtr, UI32 Index);
PDF_EXP void  PDF_CALL psrDeleteParserContext(IPSR** Ctx);
PDF_EXP LBOOL PDF_CALL psrDeleteText(const PPDF* IPDF, const IPSR* Ctx, struct TFltRect* Area, TDeleteTextFlags Flags);
PDF_EXP LBOOL PDF_CALL psrExtractText(const PPDF* IPDF, const IPSR* Ctx, TTextExtractionFlags Flags, struct TFltRect* Area, UI16** Text, UI32* TextLen);
PDF_EXP LBOOL PDF_CALL psrFindText(const PPDF* IPDF, const IPSR* Ctx, struct TFltRect* Area, TSearchType SearchType, struct TTextSelection* Last, const UI16* Text, UI32 TextLen, struct TTextSelection* SelText /*out*/);
PDF_EXP LBOOL PDF_CALL psrParsePage(const PPDF* IPDF, const IPSR* Ctx, const void* UserData, struct TPDFParseCallbacks* Funcs, UI32 PageNum, TContentParseFlags Flags, struct TContentParseParms* Parms, struct TContent* Out);
PDF_EXP LBOOL PDF_CALL psrReplaceSelText(const PPDF* IPDF, const IPSR* Ctx, TReplaceTextFlags Flags, struct TTextSelection* SelText, const UI16* Text, UI32 TextLen);
PDF_EXP void  PDF_CALL psrReset(const IPSR* Ctx);
PDF_EXP SI32  PDF_CALL psrSetAltFontA(const PPDF* IPDF, const IPSR* Ctx, const char* Name, TFStyle Style, double Size, LBOOL Embed, TCodepage CP);
PDF_EXP SI32  PDF_CALL psrSetAltFontW(const PPDF* IPDF, const IPSR* Ctx, const UI16* Name, TFStyle Style, double Size, LBOOL Embed, TCodepage CP);
PDF_EXP LBOOL PDF_CALL psrWriteToPage(const PPDF* IPDF, const IPSR* Ctx, TOptimizeFlags Flags, struct TOptimizeParams* Parms);

#if defined(_UNICODE) || defined(UNICODE)
   #define psrSetAltFont         psrSetAltFontW
#else
   #define psrSetAltFont         psrSetAltFontA
#endif

#ifdef __cplusplus
}
#endif

#endif
