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