1 /****************************************************************************** 2 * $Id: pdfcreatefromcomposition.h 842d122d2f23aaebb28362e083b52d6bc7dbcde2 2019-08-11 17:42:34 +0200 Even Rouault $ 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) 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 PDFCREATEFROMCOMPOSITION_H_INCLUDED 31 #define PDFCREATEFROMCOMPOSITION_H_INCLUDED 32 33 #include "gdal_pdf.h" 34 #include "pdfcreatecopy.h" 35 #include "cpl_minixml.h" 36 #include "ogrsf_frmts.h" 37 #include "ogr_geometry.h" 38 39 #include <map> 40 #include <memory> 41 #include <vector> 42 43 class GDALPDFComposerWriter final: public GDALPDFBaseWriter 44 { 45 CPLString m_osJPEG2000Driver{}; 46 struct TreeOfOCG 47 { 48 GDALPDFObjectNum m_nNum{}; 49 bool m_bInitiallyVisible{true}; 50 std::vector<std::unique_ptr<TreeOfOCG>> m_children{}; 51 }; 52 bool m_bDisplayLayersOnlyOnVisiblePages = false; 53 TreeOfOCG m_oTreeOfOGC{}; 54 std::map<CPLString, std::vector<GDALPDFObjectNum>> m_oMapExclusiveOCGIdToOCGs{}; 55 56 std::map<CPLString, GDALPDFObjectNum> m_oMapLayerIdToOCG{}; 57 58 struct xyPair 59 { 60 double x = 0; 61 double y = 0; xxyPair62 xyPair(double xin = 0.0, double yin = 0.0): x(xin), y(yin) {} 63 }; 64 65 struct Georeferencing 66 { 67 CPLString m_osID{}; 68 OGRSpatialReference m_oSRS{}; 69 double m_bboxX1{}; 70 double m_bboxY1{}; 71 double m_bboxX2{}; 72 double m_bboxY2{}; 73 double m_adfGT[6]{0,1,0,0,0,1}; 74 }; 75 76 std::vector<GDALPDFObjectNum> m_anParentElements; 77 std::vector<GDALPDFObjectNum> m_anFeatureLayerId; 78 std::map<CPLString, GDALPDFObjectNum> m_oMapPageIdToObjectNum; 79 struct PageContext 80 { 81 double m_dfWidthInUserUnit = 0; 82 double m_dfHeightInUserUnit = 0; 83 CPLString m_osDrawingStream{}; 84 std::vector<GDALPDFObjectNum> m_anFeatureUserProperties; 85 int m_nMCID = 0; 86 PDFCompressMethod m_eStreamCompressMethod = COMPRESS_DEFLATE; 87 std::map<CPLString, GDALPDFObjectNum> m_oXObjects{}; 88 std::map<CPLString, GDALPDFObjectNum> m_oProperties{}; 89 std::map<CPLString, GDALPDFObjectNum> m_oExtGState{}; 90 std::vector<GDALPDFObjectNum> m_anAnnotationsId{}; 91 std::map<CPLString, Georeferencing> m_oMapGeoreferencedId{}; 92 }; 93 94 bool CreateLayerTree(const CPLXMLNode* psNode, 95 const GDALPDFObjectNum& nParentId, 96 TreeOfOCG* parent); 97 98 struct Action 99 { 100 virtual ~Action() = default; 101 }; 102 103 struct GotoPageAction final: public Action 104 { 105 GDALPDFObjectNum m_nPageDestId{}; 106 double m_dfX1 = 0; 107 double m_dfX2 = 0; 108 double m_dfY1 = 0; 109 double m_dfY2 = 0; 110 }; 111 112 struct SetLayerStateAction final: public Action 113 { 114 std::set<GDALPDFObjectNum> m_anONLayers{}; 115 std::set<GDALPDFObjectNum> m_anOFFLayers{}; 116 }; 117 118 struct JavascriptAction final: public Action 119 { 120 CPLString m_osScript{}; 121 }; 122 123 bool ParseActions(const CPLXMLNode* psNode, 124 std::vector<std::unique_ptr<Action>>& actions); 125 static GDALPDFDictionaryRW* SerializeActions( 126 GDALPDFDictionaryRW* poDictForDest, 127 const std::vector<std::unique_ptr<Action>>& actions); 128 129 struct OutlineItem 130 { 131 GDALPDFObjectNum m_nObjId{}; 132 CPLString m_osName{}; 133 bool m_bOpen = true; 134 int m_nFlags = 0; 135 std::vector<std::unique_ptr<Action>> m_aoActions{}; 136 std::vector<std::unique_ptr<OutlineItem>> m_aoKids{}; 137 int m_nKidsRecCount = 0; 138 }; 139 GDALPDFObjectNum m_nOutlinesId{}; 140 141 bool CreateOutlineFirstPass(const CPLXMLNode* psNode, 142 OutlineItem* poParentItem); 143 bool SerializeOutlineKids(const OutlineItem* poParentItem); 144 bool CreateOutline(const CPLXMLNode* psNode); 145 146 void WritePages(); 147 148 static GDALPDFArrayRW* CreateOCGOrder(const TreeOfOCG* parent); 149 static void CollectOffOCG(std::vector<GDALPDFObjectNum>& ar, 150 const TreeOfOCG* parent); 151 bool GeneratePage(const CPLXMLNode* psPage); 152 bool GenerateGeoreferencing(const CPLXMLNode* psGeoreferencing, 153 double dfWidthInUserUnit, 154 double dfHeightInUserUnit, 155 GDALPDFObjectNum& nViewportId, 156 GDALPDFObjectNum& nLGIDictId, 157 Georeferencing& georeferencing); 158 159 GDALPDFObjectNum GenerateISO32000_Georeferencing( 160 OGRSpatialReferenceH hSRS, 161 double bboxX1, double bboxY1, double bboxX2, double bboxY2, 162 const std::vector<GDAL_GCP>& aGCPs, 163 const std::vector<xyPair>& aBoundingPolygon); 164 165 GDALPDFObjectNum GenerateOGC_BP_Georeferencing( 166 OGRSpatialReferenceH hSRS, 167 double bboxX1, double bboxY1, double bboxX2, double bboxY2, 168 const std::vector<GDAL_GCP>& aGCPs, 169 const std::vector<xyPair>& aBoundingPolygon); 170 171 bool ExploreContent(const CPLXMLNode* psNode, PageContext& oPageContext); 172 bool WriteRaster(const CPLXMLNode* psNode, PageContext& oPageContext); 173 bool WriteVector(const CPLXMLNode* psNode, PageContext& oPageContext); 174 bool WriteVectorLabel(const CPLXMLNode* psNode, PageContext& oPageContext); 175 void StartBlending(const CPLXMLNode* psNode, PageContext& oPageContext, 176 double& dfOpacity); 177 static void EndBlending(const CPLXMLNode* psNode, PageContext& oPageContext); 178 179 static bool SetupVectorGeoreferencing( 180 const char* pszGeoreferencingId, 181 OGRLayer* poLayer, 182 const PageContext& oPageContext, 183 double& dfClippingMinX, 184 double& dfClippingMinY, 185 double& dfClippingMaxX, 186 double& dfClippingMaxY, 187 double adfMatrix[4], 188 std::unique_ptr<OGRCoordinateTransformation>& poCT); 189 190 #ifdef HAVE_PDF_READ_SUPPORT 191 bool WritePDF(const CPLXMLNode* psNode, PageContext& oPageContext); 192 193 typedef std::map< std::pair<int, int>, GDALPDFObjectNum> RemapType; 194 GDALPDFObjectNum EmitNewObject(GDALPDFObject* poObj, 195 RemapType& oRemapObjectRefs); 196 GDALPDFObjectNum SerializeAndRenumber(GDALPDFObject* poObj); 197 bool SerializeAndRenumber(CPLString& osStr, 198 GDALPDFObject* poObj, 199 RemapType& oRemapObjectRefs); 200 bool SerializeAndRenumberIgnoreRef(CPLString& osStr, 201 GDALPDFObject* poObj, 202 RemapType& oRemapObjectRefs); 203 #endif 204 205 public: 206 explicit GDALPDFComposerWriter(VSILFILE* fp); 207 ~GDALPDFComposerWriter(); 208 209 bool Generate(const CPLXMLNode* psComposition); 210 void Close(); 211 }; 212 213 GDALDataset* GDALPDFCreateFromCompositionFile(const char* pszPDFFilename, 214 const char *pszXMLFilename); 215 216 217 #endif // PDFCREATEFROMCOMPOSITION_H_INCLUDED 218