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