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