LCOV - code coverage report
Current view: top level - frmts/pdf - pdfcreatecopy.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 6 6 100.0 %
Date: 2025-06-08 21:14:40 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  PDF driver
       4             :  * Purpose:  GDALDataset driver for PDF dataset.
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys dot com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2012-2019, Even Rouault <even dot rouault at spatialys dot com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef PDFCREATECOPY_H_INCLUDED
      14             : #define PDFCREATECOPY_H_INCLUDED
      15             : 
      16             : #include "pdfobject.h"
      17             : #include "gdal_priv.h"
      18             : #include <vector>
      19             : #include <map>
      20             : 
      21             : #include "ogr_api.h"
      22             : #include "ogr_spatialref.h"
      23             : 
      24             : /* Cf PDF reference v1.7, Appendix C, page 993 */
      25             : #define MAXIMUM_SIZE_IN_UNITS 14400
      26             : 
      27             : #define APPLY_GT_X(gt, x, y) ((gt)[0] + (x) * (gt)[1] + (y) * (gt)[2])
      28             : #define APPLY_GT_Y(gt, x, y) ((gt)[3] + (x) * (gt)[4] + (y) * (gt)[5])
      29             : 
      30             : typedef enum
      31             : {
      32             :     COMPRESS_NONE,
      33             :     COMPRESS_DEFLATE,
      34             :     COMPRESS_JPEG,
      35             :     COMPRESS_JPEG2000,
      36             :     COMPRESS_DEFAULT
      37             : } PDFCompressMethod;
      38             : 
      39             : struct PDFMargins
      40             : {
      41             :     int nLeft = 0;
      42             :     int nRight = 0;
      43             :     int nTop = 0;
      44             :     int nBottom = 0;
      45             : };
      46             : 
      47          20 : class GDALFakePDFDataset final : public GDALDataset
      48             : {
      49             :   public:
      50          10 :     GDALFakePDFDataset() = default;
      51             :     ~GDALFakePDFDataset() override;
      52             : };
      53             : 
      54             : /************************************************************************/
      55             : /*                          GDALPDFWriter                               */
      56             : /************************************************************************/
      57             : 
      58             : class GDALXRefEntry
      59             : {
      60             :   public:
      61             :     vsi_l_offset nOffset = 0;
      62             :     int nGen = 0;
      63             :     int bFree = FALSE;
      64             : 
      65        2720 :     GDALXRefEntry() = default;
      66             : 
      67             :     explicit GDALXRefEntry(vsi_l_offset nOffsetIn, int nGenIn = 0)
      68             :         : nOffset(nOffsetIn), nGen(nGenIn)
      69             :     {
      70             :     }
      71             : 
      72        5614 :     GDALXRefEntry(const GDALXRefEntry &oOther)
      73        5614 :         : nOffset(oOther.nOffset), nGen(oOther.nGen), bFree(oOther.bFree)
      74             :     {
      75        5614 :     }
      76             : 
      77             :     GDALXRefEntry &operator=(const GDALXRefEntry &oOther)
      78             :     {
      79             :         nOffset = oOther.nOffset;
      80             :         nGen = oOther.nGen;
      81             :         bFree = oOther.bFree;
      82             :         return *this;
      83             :     }
      84             : };
      85             : 
      86             : class GDALPDFImageDesc
      87             : {
      88             :   public:
      89             :     GDALPDFObjectNum nImageId{};
      90             :     double dfXOff = 0;
      91             :     double dfYOff = 0;
      92             :     double dfXSize = 0;
      93             :     double dfYSize = 0;
      94             : };
      95             : 
      96             : class GDALPDFLayerDesc
      97             : {
      98             :   public:
      99             :     GDALPDFObjectNum nOCGId{};
     100             :     GDALPDFObjectNum nOCGTextId{};
     101             :     GDALPDFObjectNum nFeatureLayerId{};
     102             :     CPLString osLayerName{};
     103             :     int bWriteOGRAttributes{false};
     104             :     std::vector<GDALPDFObjectNum> aIds{};
     105             :     std::vector<GDALPDFObjectNum> aIdsText{};
     106             :     std::vector<GDALPDFObjectNum> aUserPropertiesIds{};
     107             :     std::vector<CPLString> aFeatureNames{};
     108             :     std::vector<CPLString> aosIncludedFields{};
     109             : };
     110             : 
     111             : class GDALPDFRasterDesc
     112             : {
     113             :   public:
     114             :     GDALPDFObjectNum nOCGRasterId{};
     115             :     std::vector<GDALPDFImageDesc> asImageDesc{};
     116             : };
     117             : 
     118             : class GDALPDFPageContext
     119             : {
     120             :   public:
     121             :     GDALDataset *poClippingDS = nullptr;
     122             :     PDFCompressMethod eStreamCompressMethod = COMPRESS_NONE;
     123             :     double dfDPI{0};
     124             :     PDFMargins sMargins{};
     125             :     GDALPDFObjectNum nPageId{};
     126             :     GDALPDFObjectNum nContentId{};
     127             :     GDALPDFObjectNum nResourcesId{};
     128             :     std::vector<GDALPDFLayerDesc> asVectorDesc{};
     129             :     std::vector<GDALPDFRasterDesc> asRasterDesc{};
     130             :     GDALPDFObjectNum nAnnotsId{};
     131             :     std::vector<GDALPDFObjectNum> anAnnotationsId{};
     132             : };
     133             : 
     134             : class GDALPDFOCGDesc
     135             : {
     136             :   public:
     137             :     GDALPDFObjectNum nId{};
     138             :     GDALPDFObjectNum nParentId{};
     139             :     CPLString osLayerName{};
     140             : };
     141             : 
     142             : class GDALPDFBaseWriter
     143             : {
     144             :   protected:
     145             :     VSILFILE *m_fp = nullptr;
     146             :     bool m_bInWriteObj = false;
     147             :     std::vector<GDALXRefEntry> m_asXRefEntries{};
     148             :     GDALPDFObjectNum m_nPageResourceId{};
     149             :     GDALPDFObjectNum m_nCatalogId{};
     150             :     int m_nCatalogGen = 0;
     151             :     GDALPDFObjectNum m_nInfoId{};
     152             :     int m_nInfoGen = 0;
     153             :     GDALPDFObjectNum m_nXMPId{};
     154             :     int m_nXMPGen = 0;
     155             :     GDALPDFObjectNum m_nStructTreeRootId{};
     156             :     GDALPDFObjectNum m_nNamesId{};
     157             : 
     158             :     GDALPDFObjectNum m_nContentLengthId{};
     159             :     VSILFILE *m_fpBack = nullptr;
     160             :     VSILFILE *m_fpGZip = nullptr;
     161             :     vsi_l_offset m_nStreamStart = 0;
     162             : 
     163             :     std::vector<GDALPDFObjectNum> m_asPageId{};
     164             :     std::vector<GDALPDFOCGDesc> m_asOCGs{};
     165             :     std::map<CPLString, GDALPDFImageDesc> m_oMapSymbolFilenameToDesc{};
     166             : 
     167             :   public:
     168             :     struct ObjectStyle
     169             :     {
     170             :         unsigned int nPenR = 0;
     171             :         unsigned int nPenG = 0;
     172             :         unsigned int nPenB = 0;
     173             :         unsigned int nPenA = 255;
     174             :         unsigned int nBrushR = 127;
     175             :         unsigned int nBrushG = 127;
     176             :         unsigned int nBrushB = 127;
     177             :         unsigned int nBrushA = 127;
     178             :         unsigned int nTextR = 0;
     179             :         unsigned int nTextG = 0;
     180             :         unsigned int nTextB = 0;
     181             :         unsigned int nTextA = 255;
     182             :         int bSymbolColorDefined = FALSE;
     183             :         unsigned int nSymbolR = 0;
     184             :         unsigned int nSymbolG = 0;
     185             :         unsigned int nSymbolB = 0;
     186             :         unsigned int nSymbolA = 255;
     187             :         bool bHasPenBrushOrSymbol = false;
     188             :         CPLString osTextFont{};
     189             :         bool bTextBold = false;
     190             :         bool bTextItalic = false;
     191             :         double dfTextSize = 12.0;
     192             :         double dfTextAngle = 0.0;
     193             :         double dfTextStretch = 1.0;
     194             :         double dfTextDx = 0.0;
     195             :         double dfTextDy = 0.0;
     196             :         int nTextAnchor = 1;
     197             :         double dfPenWidth = 1.0;
     198             :         double dfSymbolSize = 5.0;
     199             :         CPLString osDashArray{};
     200             :         CPLString osLabelText{};
     201             :         CPLString osSymbolId{};
     202             :         GDALPDFObjectNum nImageSymbolId{};
     203             :         int nImageWidth = 0;
     204             :         int nImageHeight = 0;
     205             :     };
     206             : 
     207             :   protected:
     208             :     explicit GDALPDFBaseWriter(VSILFILE *fp);
     209             :     ~GDALPDFBaseWriter();
     210             : 
     211             :     GDALPDFObjectNum AllocNewObject();
     212             : 
     213             :     void StartObj(const GDALPDFObjectNum &nObjectId, int nGen = 0);
     214             :     void EndObj();
     215             : 
     216             :     void StartObjWithStream(const GDALPDFObjectNum &nObjectId,
     217             :                             GDALPDFDictionaryRW &oDict, bool bDeflate);
     218             :     void EndObjWithStream();
     219             : 
     220             :     void StartNewDoc();
     221             :     void Close();
     222             : 
     223             :     void WriteXRefTableAndTrailer(bool bUpdate, vsi_l_offset nLastStartXRef);
     224             : 
     225             :     GDALPDFObjectNum WriteSRS_ISO32000(GDALDataset *poSrcDS, double dfUserUnit,
     226             :                                        const char *pszNEATLINE,
     227             :                                        PDFMargins *psMargins,
     228             :                                        int bWriteViewport);
     229             : 
     230             :     GDALPDFObjectNum
     231             :     WriteOCG(const char *pszLayerName,
     232             :              const GDALPDFObjectNum &nParentId = GDALPDFObjectNum());
     233             : 
     234             :     GDALPDFObjectNum
     235             :     WriteBlock(GDALDataset *poSrcDS, int nXOff, int nYOff, int nReqXSize,
     236             :                int nReqYSize, const GDALPDFObjectNum &nColorTableIdIn,
     237             :                PDFCompressMethod eCompressMethod, int nPredictor,
     238             :                int nJPEGQuality, const char *pszJPEG2000_DRIVER,
     239             :                GDALProgressFunc pfnProgress, void *pProgressData);
     240             :     GDALPDFObjectNum WriteMask(GDALDataset *poSrcDS, int nXOff, int nYOff,
     241             :                                int nReqXSize, int nReqYSize,
     242             :                                PDFCompressMethod eCompressMethod);
     243             : 
     244             :     GDALPDFObjectNum WriteColorTable(GDALDataset *poSrcDS);
     245             : 
     246             :     void GetObjectStyle(
     247             :         const char *pszStyleString, OGRFeatureH hFeat,
     248             :         const double adfMatrix[4],
     249             :         std::map<CPLString, GDALPDFImageDesc> oMapSymbolFilenameToDesc,
     250             :         ObjectStyle &os);
     251             :     static CPLString GenerateDrawingStream(OGRGeometryH hGeom,
     252             :                                            const double adfMatrix[4],
     253             :                                            ObjectStyle &os, double dfRadius);
     254             :     GDALPDFObjectNum
     255             :     WriteAttributes(OGRFeatureH hFeat,
     256             :                     const std::vector<CPLString> &aosIncludedFields,
     257             :                     const char *pszOGRDisplayField, int nMCID,
     258             :                     const GDALPDFObjectNum &oParent,
     259             :                     const GDALPDFObjectNum &oPage, CPLString &osOutFeatureName);
     260             : 
     261             :     GDALPDFObjectNum WriteLabel(OGRGeometryH hGeom, const double adfMatrix[4],
     262             :                                 ObjectStyle &os,
     263             :                                 PDFCompressMethod eStreamCompressMethod,
     264             :                                 double bboxXMin, double bboxYMin,
     265             :                                 double bboxXMax, double bboxYMax);
     266             : 
     267             :     GDALPDFObjectNum WriteLink(OGRFeatureH hFeat, const char *pszOGRLinkField,
     268             :                                const double adfMatrix[4], int bboxXMin,
     269             :                                int bboxYMin, int bboxXMax, int bboxYMax);
     270             : 
     271             :     static void ComputeIntBBox(OGRGeometryH hGeom, const OGREnvelope &sEnvelope,
     272             :                                const double adfMatrix[4], const ObjectStyle &os,
     273             :                                double dfRadius, int &bboxXMin, int &bboxYMin,
     274             :                                int &bboxXMax, int &bboxYMax);
     275             : 
     276             :     GDALPDFObjectNum WriteJavascript(const char *pszJavascript, bool bDeflate);
     277             : 
     278             :   public:
     279             :     GDALPDFObjectNum SetInfo(GDALDataset *poSrcDS, char **papszOptions);
     280             :     GDALPDFObjectNum SetInfo(const char *pszAUTHOR, const char *pszPRODUCER,
     281             :                              const char *pszCREATOR,
     282             :                              const char *pszCREATION_DATE,
     283             :                              const char *pszSUBJECT, const char *pszTITLE,
     284             :                              const char *pszKEYWORDS);
     285             :     GDALPDFObjectNum SetXMP(GDALDataset *poSrcDS, const char *pszXMP);
     286             : 
     287             :   private:
     288             :     CPL_DISALLOW_COPY_ASSIGN(GDALPDFBaseWriter)
     289             : };
     290             : 
     291             : class GDALPDFUpdateWriter final : public GDALPDFBaseWriter
     292             : {
     293             :     bool m_bUpdateNeeded = false;
     294             :     vsi_l_offset m_nLastStartXRef = 0;
     295             :     int m_nLastXRefSize = 0;
     296             : 
     297             :   public:
     298             :     explicit GDALPDFUpdateWriter(VSILFILE *fpIn);
     299             :     ~GDALPDFUpdateWriter();
     300             : 
     301             :     void Close();
     302             : 
     303             :     const GDALPDFObjectNum &GetCatalogNum() const
     304             :     {
     305             :         return m_nCatalogId;
     306             :     }
     307             : 
     308             :     int GetCatalogGen() const
     309             :     {
     310             :         return m_nCatalogGen;
     311             :     }
     312             : 
     313             :     int ParseTrailerAndXRef();
     314             :     void UpdateProj(GDALDataset *poSrcDS, double dfDPI,
     315             :                     GDALPDFDictionaryRW *poPageDict,
     316             :                     const GDALPDFObjectNum &nPageId, int nPageGen);
     317             :     void UpdateInfo(GDALDataset *poSrcDS);
     318             :     void UpdateXMP(GDALDataset *poSrcDS, GDALPDFDictionaryRW *poCatalogDict);
     319             : };
     320             : 
     321             : class GDALPDFWriter final : public GDALPDFBaseWriter
     322             : {
     323             :     GDALPDFPageContext oPageContext{};
     324             : 
     325             :     CPLString m_osOffLayers{};
     326             :     CPLString m_osExclusiveLayers{};
     327             : 
     328             :     void WritePages();
     329             : 
     330             :   public:
     331             :     explicit GDALPDFWriter(VSILFILE *fpIn);
     332             :     ~GDALPDFWriter();
     333             : 
     334             :     void Close();
     335             : 
     336             :     bool StartPage(GDALDataset *poSrcDS, double dfDPI, bool bWriteUserUnit,
     337             :                    const char *pszGEO_ENCODING, const char *pszNEATLINE,
     338             :                    PDFMargins *psMargins,
     339             :                    PDFCompressMethod eStreamCompressMethod, int bHasOGRData);
     340             : 
     341             :     bool WriteImagery(GDALDataset *poDS, const char *pszLayerName,
     342             :                       PDFCompressMethod eCompressMethod, int nPredictor,
     343             :                       int nJPEGQuality, const char *pszJPEG2000_DRIVER,
     344             :                       int nBlockXSize, int nBlockYSize,
     345             :                       GDALProgressFunc pfnProgress, void *pProgressData);
     346             : 
     347             :     bool WriteClippedImagery(GDALDataset *poDS, const char *pszLayerName,
     348             :                              PDFCompressMethod eCompressMethod, int nPredictor,
     349             :                              int nJPEGQuality, const char *pszJPEG2000_DRIVER,
     350             :                              int nBlockXSize, int nBlockYSize,
     351             :                              GDALProgressFunc pfnProgress, void *pProgressData);
     352             :     bool WriteOGRDataSource(const char *pszOGRDataSource,
     353             :                             const char *pszOGRDisplayField,
     354             :                             const char *pszOGRDisplayLayerNames,
     355             :                             const char *pszOGRLinkField,
     356             :                             int bWriteOGRAttributes);
     357             : 
     358             :     GDALPDFLayerDesc StartOGRLayer(const std::string &osLayerName,
     359             :                                    int bWriteOGRAttributes);
     360             :     void EndOGRLayer(GDALPDFLayerDesc &osVectorDesc);
     361             : 
     362             :     int WriteOGRLayer(GDALDatasetH hDS, int iLayer,
     363             :                       const char *pszOGRDisplayField,
     364             :                       const char *pszOGRLinkField,
     365             :                       const std::string &osLayerName, int bWriteOGRAttributes,
     366             :                       int &iObj);
     367             : 
     368             :     int WriteOGRFeature(GDALPDFLayerDesc &osVectorDesc, OGRFeatureH hFeat,
     369             :                         OGRCoordinateTransformationH hCT,
     370             :                         const char *pszOGRDisplayField,
     371             :                         const char *pszOGRLinkField, int bWriteOGRAttributes,
     372             :                         int &iObj);
     373             : 
     374             :     GDALPDFObjectNum WriteJavascript(const char *pszJavascript);
     375             :     GDALPDFObjectNum WriteJavascriptFile(const char *pszJavascriptFile);
     376             : 
     377             :     int EndPage(const char *pszExtraImages, const char *pszExtraStream,
     378             :                 const char *pszExtraLayerName, const char *pszOffLayers,
     379             :                 const char *pszExclusiveLayers);
     380             : };
     381             : 
     382             : GDALDataset *GDALPDFCreateCopy(const char *, GDALDataset *, int, char **,
     383             :                                GDALProgressFunc pfnProgress,
     384             :                                void *pProgressData);
     385             : 
     386             : #endif  // PDFCREATECOPY_H_INCLUDED

Generated by: LCOV version 1.14