LCOV - code coverage report
Current view: top level - frmts/pdf - pdfcreatecopy.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 5 5 100.0 %
Date: 2024-05-04 12:52:34 Functions: 3 3 100.0 %

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

Generated by: LCOV version 1.14