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