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