1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 #include "objpdffile.h"
8 #include "colormgmt/sccolormgmtengine.h"
9 #include "cmdutil.h"
10 #include "prefsmanager.h"
11 #include "scribusdoc.h"
12 #include "scribuscore.h"
13 #include "scribusview.h"
14 #include <structmember.h>
15 #include "ui/bookmarkpalette.h"
16
17 #include <QFileInfo>
18 #include <QImage>
19 #include <QList>
20 #include <vector>
21
22 // these functions are located at utils.cpp
23 void SCRIBUS_API ReOrderText(ScribusDoc *doc, ScribusView *view);
24 // end of utils.cpp
25 //this is in file scribus.cpp
26
27
minmaxi(int val,int min,int max)28 static int minmaxi(int val, int min, int max)
29 {
30 if (val < min)
31 return min;
32 if (val > max)
33 return max;
34 return val;
35 }
36
minmaxd(double val,double min,double max)37 static double minmaxd(double val, double min, double max)
38 {
39 if (val < min)
40 return min;
41 if (val > max)
42 return max;
43 return val;
44 }
45
46 typedef struct
47 {
48 PyObject_HEAD
49 PyObject *file; // string - file to save into
50 PyObject *fontEmbedding; // int - 0: Embed fonts, 1:Outline fonts, 2:Dont embed any font
51 PyObject *fonts; // list of string - fonts to embed
52 PyObject *subsetList; // list of string - fonts to outline
53 PyObject *pages; // list of int - pages to print
54 int thumbnails; // bool -
55 int cropMarks; // bool -
56 int bleedMarks; // bool -
57 int registrationMarks; // bool -
58 int colorMarks; // bool -
59 int docInfoMarks; // bool -
60 double markOffset; // double -
61 double markLength; // double -
62 int compress; // bool -
63 int compressmtd; // int - 0=automatic 1=jpeg 2=zip 3=none
64 int quality; // int - 0=Maximum 4=minimum
65 PyObject *resolution; // int - 35 - 4000 default=300 dpi
66 PyObject *downsample; // int - 35 - 4000 default=0 do not downsample ; other downsample to this resolution
67 int bookmarks; // bool -
68 int binding; // bool - 0 -left margin 1 -right margin
69 int presentation; // bool -
70 PyObject *effval; // list of list of 5 int - effect to apply to each page during presentation
71 int article; // bool -
72 int encrypt; // bool -
73 int uselpi; // bool -
74 int usespot;
75 int domulti;
76 PyObject *lpival; // list of elements which has structure [siii]
77 PyObject *owner; // string - owner's password
78 PyObject *user; // string - user's password
79 int allowPrinting; // bool - allow printing
80 int allowChange; // bool - allow changing
81 int allowCopy; // bool - allow copying
82 int allowAnnots; // bool - allow adding annotation and fields
83 int version; // int - version of pdf (12=1.2; 13=1.3; 14=1.4; 15=1.5)
84 int outdst; // int - output destination 0 - screen, 1 - printer
85
86 int profiles; // bool
87 int profilei; // bool
88 int intents; // int - 0 - 3 QString tmp_ip[] = { tr("Perceptual"), tr("Relative Colorimetric"), tr("Saturation"), tr("Absolute Colorimetric")};
89 int intenti; // int - 0 - 3 QString tmp_ip[] = { tr("Perceptual"), tr("Relative Colorimetric"), tr("Saturation"), tr("Absolute Colorimetric")};
90 int noembicc; // bool - "Don't use embedded ICC profiles"
91 PyObject *solidpr; // string
92 PyObject *imagepr; // string
93 PyObject *printprofc; // string
94 PyObject *info; // string
95 double bleedt; // double - 0 to height of page
96 double bleedl; // double - 0 to width of page
97 double bleedr; // double - 0 to width of page
98 double bleedb; // double - 0 to height of page
99 int useDocBleeds; // bool
100 int useLayers;
101 int embedPDF;
102 int mirrorH;
103 int mirrorV;
104 int doClip;
105 PyObject * rotateDeg; // int
106 int isGrayscale;
107 int pageLayout;
108 int displayBookmarks;
109 int displayThumbs;
110 int displayLayers;
111 int displayFullscreen;
112 int hideToolBar;
113 int hideMenuBar;
114 int fitWindow;
115 PyObject *openAction;
116
117 } PDFfile;
118
PDFfile_dealloc(PDFfile * self)119 static void PDFfile_dealloc(PDFfile *self)
120 {
121 Py_XDECREF(self->file);
122 Py_XDECREF(self->fontEmbedding);
123 Py_XDECREF(self->fonts);
124 Py_XDECREF(self->subsetList);
125 Py_XDECREF(self->pages);
126 Py_XDECREF(self->resolution);
127 Py_XDECREF(self->downsample);
128 Py_XDECREF(self->effval);
129 Py_XDECREF(self->lpival);
130 Py_XDECREF(self->owner);
131 Py_XDECREF(self->user);
132 Py_XDECREF(self->solidpr);
133 Py_XDECREF(self->imagepr);
134 Py_XDECREF(self->printprofc);
135 Py_XDECREF(self->info);
136 Py_XDECREF(self->rotateDeg);
137 Py_XDECREF(self->openAction);
138 Py_TYPE(self)->tp_free((PyObject *)self);
139 }
140
PDFfile_new(PyTypeObject * type,PyObject *,PyObject *)141 static PyObject * PDFfile_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
142 {
143 // Do not create new object if there is no opened document
144 if (!checkHaveDocument())
145 return nullptr;
146
147 PDFfile *self;
148
149 self = (PDFfile *)type->tp_alloc(type, 0);
150 if (self)
151 {
152 // Set file attribute
153 self->file = PyUnicode_FromString("");
154 if (!self->file)
155 {
156 Py_DECREF(self);
157 return nullptr;
158 }
159 // Set font embedding mode attribute
160 self->fontEmbedding = PyLong_FromLong(0);
161 if (!self->fontEmbedding)
162 {
163 Py_DECREF(self);
164 return nullptr;
165 }
166 // Set fonts attribute
167 self->fonts = PyList_New(0);
168 if (!self->fonts)
169 {
170 Py_DECREF(self);
171 return nullptr;
172 }
173 self->subsetList = PyList_New(0);
174 if (!self->subsetList)
175 {
176 Py_DECREF(self);
177 return nullptr;
178 }
179 // Set pages attribute
180 self->pages = PyList_New(0);
181 if (self->pages == nullptr)
182 {
183 Py_DECREF(self);
184 return nullptr;
185 }
186 // Set thumbnails attribute
187 self->thumbnails = 0;
188 // Set cropMarks attribute
189 self->cropMarks = 0;
190 // Set bleedMarks attribute
191 self->bleedMarks = 0;
192 // Set registrationMarks attribute
193 self->registrationMarks = 0;
194 // Set colorMarks attribute
195 self->colorMarks = 0;
196 // Set docInfoMarks attribute
197 self->docInfoMarks = 0;
198 // Set mark offset attribute
199 self->markOffset = 0;
200 // Set mark length attribute
201 self->markLength = 0;
202 // Set compress attribute
203 self->compress = 0;
204 // Set compressmtd attribute
205 self->compressmtd = 0;
206 // Set quality attribute
207 self->quality = 0;
208 // Set resolution attribute
209 self->resolution = PyLong_FromLong(300);
210 if (!self->resolution)
211 {
212 Py_DECREF(self);
213 return nullptr;
214 }
215 // Set downsample attribute
216 self->downsample = PyLong_FromLong(0);
217 if (!self->downsample)
218 {
219 Py_DECREF(self);
220 return nullptr;
221 }
222 // Set bookmarks attribute
223 self->bookmarks = 0;
224 // Set binding attribute
225 self->binding = 0;
226 // Set presentation attribute
227 self->presentation = 0;
228 // Set effval attribute
229 self->effval = PyList_New(0);
230 if (!self->effval)
231 {
232 Py_DECREF(self);
233 return nullptr;
234 }
235 // Set article attribute
236 self->article = 0;
237 // Set encrypt attribute
238 self->encrypt = 0;
239 // Set uselpi attribute
240 self->uselpi = 0;
241 self->usespot = 1;
242 self->domulti = 0;
243 // Set lpival attribute
244 self->lpival = PyList_New(0);
245 if (!self->lpival)
246 {
247 Py_DECREF(self);
248 return nullptr;
249 }
250 // Set owner attribute
251 self->owner = PyUnicode_FromString("");
252 if (!self->owner)
253 {
254 Py_DECREF(self);
255 return nullptr;
256 }
257 // Set user attribute
258 self->user = PyUnicode_FromString("");
259 if (!self->user)
260 {
261 Py_DECREF(self);
262 return nullptr;
263 }
264 // Set allowPrinting attribute
265 self->allowPrinting = 1;
266 // Set allowChange attribute
267 self->allowChange = 1;
268 // Set allowCopy attribute
269 self->allowCopy = 1;
270 // Set allowAnnots attribute
271 self->allowAnnots = 1;
272 // Set version attribute
273 self->version = 14;
274 // Set output attribute
275 self->outdst = 0;
276
277 self->profiles = 0; // bool
278 self->profilei = 0; // bool
279 self->intents = 0; // int - 0 - ?
280 self->intenti = 0; // int - 0 - ?
281 self->noembicc = 0; // bool
282 self->solidpr = PyUnicode_FromString("");
283 if (!self->solidpr)
284 {
285 Py_DECREF(self);
286 return nullptr;
287 }
288 self->imagepr = PyUnicode_FromString("");
289 if (!self->imagepr)
290 {
291 Py_DECREF(self);
292 return nullptr;
293 }
294 self->printprofc = PyUnicode_FromString("");
295 if (!self->printprofc)
296 {
297 Py_DECREF(self);
298 return nullptr;
299 }
300 self->info = PyUnicode_FromString("");
301 if (!self->info)
302 {
303 Py_DECREF(self);
304 return nullptr;
305 }
306 self->bleedt = 0; // double -
307 self->bleedl = 0; // double -
308 self->bleedr = 0; // double -
309 self->bleedb = 0; // double -
310 self->useDocBleeds = 1; // bool
311 self->useLayers = 0;
312 self->embedPDF = 0;
313 self->mirrorH = 0;
314 self->mirrorV = 0;
315 self->doClip = 0;
316 self->rotateDeg = PyLong_FromLong(0);
317 if (!self->rotateDeg)
318 {
319 Py_DECREF(self);
320 return nullptr;
321 }
322 self->isGrayscale = 0;
323 self->pageLayout = 0;
324 self->displayBookmarks = 0;
325 self->displayThumbs = 0;
326 self->displayLayers = 0;
327 self->displayFullscreen = 0;
328 self->hideToolBar = 0;
329 self->hideMenuBar = 0;
330 self->fitWindow = 0;
331 self->openAction = PyUnicode_FromString("");
332 if (!self->openAction)
333 {
334 Py_DECREF(self);
335 return nullptr;
336 }
337 }
338 return (PyObject *) self;
339 }
340
PDFfile_init(PDFfile * self,PyObject *,PyObject *)341 static int PDFfile_init(PDFfile *self, PyObject * /*args*/, PyObject * /*kwds*/)
342 {
343 int i;
344 if (!checkHaveDocument())
345 return -1;
346
347 ScribusDoc* currentDoc = ScCore->primaryMainWindow()->doc;
348 PDFOptions& pdfOptions = currentDoc->pdfOptions();
349
350 // Defaut save into file
351 QString tf = pdfOptions.fileName;
352 if (tf.isEmpty())
353 {
354 QFileInfo fi = QFileInfo(currentDoc->documentFileName());
355 tf = fi.path() + "/" + fi.baseName() + ".pdf";
356 }
357
358 PyObject *file = PyUnicode_FromString(tf.toUtf8());
359 if (file)
360 {
361 Py_DECREF(self->file);
362 self->file = file;
363 }
364 else
365 {
366 PyErr_SetString(PyExc_SystemError, "Can not initialize 'file' attribute");
367 return -1;
368 }
369
370 // Font embedding mode
371 PyObject *embeddingMode = PyLong_FromLong(pdfOptions.FontEmbedding);
372 if (embeddingMode)
373 {
374 Py_DECREF(self->fontEmbedding);
375 self->fontEmbedding = embeddingMode;
376 }
377 else
378 {
379 PyErr_SetString(PyExc_SystemError, "Can not initialize 'fontEmbedding' attribute");
380 return -1;
381 }
382
383 // Embed all used fonts
384 PyObject *fonts = PyList_New(0);
385 if (fonts)
386 {
387 Py_DECREF(self->fonts);
388 self->fonts = fonts;
389 }
390 else
391 {
392 PyErr_SetString(PyExc_SystemError, "Can not initialize 'fonts' attribute");
393 return -1;
394 }
395
396 // Get all used fonts
397 QMap<QString,int> ReallyUsed = currentDoc->UsedFonts;
398 // Create list of all used fonts
399 QList<QString> tmpEm = ReallyUsed.keys();
400 for (int i = 0; i < tmpEm.count(); ++i)
401 {
402 const QString& fontName = tmpEm.at(i);
403 PyObject *tmp = PyUnicode_FromString(fontName.toUtf8());
404 if (tmp)
405 {
406 PyList_Append(self->fonts, tmp);
407 // Do i need Py_DECREF(tmp) here?
408 // Does PyList_Append increase reference or 'steal' one from provided argument
409 // If it 'steal' reference comment next line
410 Py_DECREF(tmp);
411 }
412 else
413 {
414 PyErr_SetString(PyExc_SystemError, "Can not initialize 'fonts' attribute");
415 return -1;
416 }
417 }
418
419 // Init subsetList
420 fonts = PyList_New(0);
421 if (fonts)
422 {
423 Py_DECREF(self->subsetList);
424 self->subsetList = fonts;
425 }
426 else
427 {
428 PyErr_SetString(PyExc_SystemError, "Can not initialize 'subsetList' attribute");
429 return -1;
430 }
431
432 // Copied from TabPDFOptions::restoreDefaults()
433 for (int fe = 0; fe < pdfOptions.SubsetList.count(); ++fe)
434 {
435 PyObject *tmp= nullptr;
436 tmp = PyUnicode_FromString(pdfOptions.SubsetList[fe].toUtf8().data());
437 if (tmp)
438 {
439 PyList_Append(self->subsetList, tmp);
440 Py_DECREF(tmp);
441 }
442 else
443 {
444 PyErr_SetString(PyExc_SystemError, "Can not initialize 'subsetList' attribute");
445 return -1;
446 }
447 }
448
449 // Set to print all pages
450 int num = currentDoc->Pages->count();
451 PyObject *pages = PyList_New(num);
452 if (!pages)
453 {
454 PyErr_SetString(PyExc_SystemError, "Can not initialize 'pages' attribute");
455 return -1;
456 }
457 for (i = 0; i < num; ++i)
458 {
459 PyObject *tmp = PyLong_FromLong((long) i + 1L);
460 if (tmp)
461 PyList_SetItem(pages, i, tmp);
462 else
463 {
464 PyErr_SetString(PyExc_SystemError, "Can not initialize 'pages' attribute");
465 return -1;
466 }
467 }
468 Py_DECREF(self->pages);
469 self->pages = pages;
470 // Print thumbnails ?
471 self->thumbnails = pdfOptions.Thumbnails;
472 // Output crop marks ?
473 self->cropMarks = pdfOptions.cropMarks;
474 // Output bleed marks ?
475 self->bleedMarks = pdfOptions.bleedMarks;
476 // Output registration marks ?
477 self->registrationMarks = pdfOptions.registrationMarks;
478 // Output color bars ?
479 self->colorMarks = pdfOptions.colorMarks;
480 // Output doc info marks ?
481 self->docInfoMarks = pdfOptions.docInfoMarks;
482 // Cropmarks offset
483 self->markOffset = pdfOptions.markOffset * currentDoc->unitRatio();
484 // Cropmarks length
485 self->markLength = pdfOptions.markLength * currentDoc->unitRatio();
486 // Set automatic compression
487 self->compress = pdfOptions.Compress;
488 self->compressmtd = pdfOptions.CompressMethod;
489 // Use maximum image quality
490 self->quality = pdfOptions.Quality;
491 // Default resolution
492 PyObject *resolution = nullptr;
493 resolution = PyLong_FromLong(300);
494 if (resolution)
495 {
496 Py_DECREF(self->resolution);
497 self->resolution = resolution;
498 }
499 else
500 {
501 PyErr_SetString(PyExc_SystemError, "Can not initialize 'resolution' attribute");
502 return -1;
503 }
504 // Do not downsample images
505 int down = pdfOptions.RecalcPic ? pdfOptions.PicRes : 0;
506 PyObject *downsample = nullptr;
507 downsample = PyLong_FromLong(down);
508 if (downsample)
509 {
510 Py_DECREF(self->downsample);
511 self->downsample = downsample;
512 }
513 else
514 {
515 PyErr_SetString(PyExc_SystemError, "Can not initialize 'downsamle' attribute");
516 return -1;
517 }
518 // No bookmarks
519 self->bookmarks = pdfOptions.Bookmarks;
520 // Left margin binding
521 self->binding = pdfOptions.Binding;
522 // Do not enable presentation effects
523 self->presentation = pdfOptions.PresentMode;
524 // Set effects values for all pages
525 PyObject *effval = nullptr;
526 num = currentDoc->Pages->count();
527 effval = PyList_New(num);
528 if (!effval)
529 {
530 PyErr_SetString(PyExc_SystemError, "Can not initialize 'effval' attribute");
531 return -1;
532 }
533 for (i = 0; i < num; ++i)
534 {
535 PyObject *tmp;
536 PDFPresentationData t = currentDoc->Pages->at(i)->PresentVals;
537 tmp = Py_BuildValue(const_cast<char*>("[iiiiii]"), t.pageEffectDuration, t.pageViewDuration, t.effectType, t.Dm, t.M, t.Di );
538 if (tmp)
539 PyList_SetItem(effval, i, tmp);
540 else
541 {
542 PyErr_SetString(PyExc_SystemError, "Can not initialize 'effval' attribute");
543 return -1;
544 }
545 for (; i < num; ++i)
546 {
547 PyObject *tmp = Py_BuildValue(const_cast<char*>("[iiiiii]"), 1, 1, 0, 0, 0, 0);
548 if (tmp)
549 PyList_SetItem(effval, i, tmp);
550 else
551 {
552 PyErr_SetString(PyExc_SystemError, "Can not initialize 'effval' attribute");
553 return -1;
554 }
555 }
556 }
557 Py_DECREF(self->effval);
558 self->effval = effval;
559 // Do not save linked text frames as PDF article
560 self->article = pdfOptions.Articles;
561 // Do not encrypt file
562 self->encrypt = pdfOptions.Encrypt;
563 // Do not Use Custom Rendering Settings
564 self->uselpi = pdfOptions.UseLPI;
565 self->usespot = pdfOptions.UseSpotColors;
566 self->domulti = pdfOptions.doMultiFile;
567 // Get default values for lpival
568 int n = pdfOptions.LPISettings.size();
569 PyObject *lpival=PyList_New(n);
570 if (!lpival)
571 {
572 PyErr_SetString(PyExc_SystemError, "Can not initialize 'lpival' attribute");
573 return -1;
574 }
575 QMap<QString,LPIData>::Iterator it = pdfOptions.LPISettings.begin();
576 while (it != pdfOptions.LPISettings.end())
577 {
578 PyObject *tmp;
579 tmp = Py_BuildValue(const_cast<char*>("[siii]"), it.key().toLatin1().constData(), it.value().Frequency, it.value().Angle, it.value().SpotFunc);
580 if (!tmp)
581 {
582 PyErr_SetString(PyExc_SystemError, "Can not initialize 'lpival' attribute");
583 return -1;
584 }
585 PyList_SetItem(lpival, --n, tmp);
586 ++it;
587 }
588 PyList_Reverse(lpival);
589 Py_DECREF(self->lpival);
590 self->lpival = lpival;
591 // Set owner's password
592 PyObject *owner = PyUnicode_FromString(pdfOptions.PassOwner.toUtf8());
593 if (owner)
594 {
595 Py_DECREF(self->owner);
596 self->owner = owner;
597 }
598 else
599 {
600 PyErr_SetString(PyExc_SystemError, "Can not initialize 'owner' attribute");
601 return -1;
602 }
603 // Set user'a password
604 PyObject *user = PyUnicode_FromString(pdfOptions.PassUser.toUtf8());
605 if (user)
606 {
607 Py_DECREF(self->user);
608 self->user = user;
609 }
610 else
611 {
612 PyErr_SetString(PyExc_SystemError, "Can not initialize 'user' attribute");
613 return -1;
614 }
615 // Allow printing document
616 self->allowPrinting = pdfOptions.Permissions & 4;
617 // Allow changing document
618 self->allowChange = pdfOptions.Permissions & 8;
619 // Allow copying document
620 self->allowCopy = pdfOptions.Permissions & 16;
621 // Allow adding annotation and fields
622 self->allowAnnots = pdfOptions.Permissions & 32;
623 // Use 1.4 pdf version *aka. Acrobat 5)
624 self->version = pdfOptions.Version;
625 // Output destination is screen
626 self->outdst = pdfOptions.UseRGB ? 0 : 1;
627
628 self->profiles = pdfOptions.UseProfiles; // bool
629 self->profilei = pdfOptions.UseProfiles2; // bool
630 self->noembicc = pdfOptions.EmbeddedI; // bool
631 self->intents = pdfOptions.Intent; // int - 0 - 3
632 self->intenti = pdfOptions.Intent2; // int - 0 - 3
633 QString tp = pdfOptions.SolidProf;
634 if (!ScCore->InputProfiles.contains(tp))
635 tp = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
636 PyObject *solidpr = PyUnicode_FromString(tp.toUtf8());
637 if (solidpr)
638 {
639 Py_DECREF(self->solidpr);
640 self->solidpr = solidpr;
641 }
642 else
643 {
644 PyErr_SetString(PyExc_SystemError, "Can not initialize 'solidpr' attribute");
645 return -1;
646 }
647 QString tp2 = pdfOptions.ImageProf;
648 if (!ScCore->InputProfiles.contains(tp2))
649 tp2 = currentDoc->cmsSettings().DefaultSolidColorRGBProfile;
650 PyObject *imagepr = PyUnicode_FromString(tp2.toUtf8());
651 if (imagepr)
652 {
653 Py_DECREF(self->imagepr);
654 self->imagepr = imagepr;
655 }
656 else
657 {
658 PyErr_SetString(PyExc_SystemError, "Can not initialize 'imagepr' attribute");
659 return -1;
660 }
661 QString tp3 = pdfOptions.PrintProf;
662 if (!ScCore->PDFXProfiles.contains(tp3))
663 tp3 = currentDoc->cmsSettings().DefaultPrinterProfile;
664 PyObject *printprofc = nullptr;
665 printprofc = PyUnicode_FromString(tp3.toUtf8());
666 if (printprofc)
667 {
668 Py_DECREF(self->printprofc);
669 self->printprofc = printprofc;
670 }
671 else
672 {
673 PyErr_SetString(PyExc_SystemError, "Can not initialize 'printprofc' attribute");
674 return -1;
675 }
676 QString tinfo = pdfOptions.Info;
677 PyObject *info = PyUnicode_FromString(tinfo.toUtf8());
678 if (info)
679 {
680 Py_DECREF(self->info);
681 self->info = info;
682 }
683 else
684 {
685 PyErr_SetString(PyExc_SystemError, "Can not initialize 'info' attribute");
686 return -1;
687 }
688 self->bleedt = pdfOptions.bleeds.top() * currentDoc->unitRatio(); // double -
689 self->bleedl = pdfOptions.bleeds.left() * currentDoc->unitRatio(); // double -
690 self->bleedr = pdfOptions.bleeds.right() * currentDoc->unitRatio(); // double -
691 self->bleedb = pdfOptions.bleeds.bottom() * currentDoc->unitRatio(); // double -
692 self->useDocBleeds = pdfOptions.useDocBleeds; // bool
693 self->useLayers = pdfOptions.useLayers; // bool
694 self->embedPDF = pdfOptions.embedPDF; // bool
695 self->mirrorH = pdfOptions.MirrorH; // bool
696 self->mirrorV = pdfOptions.MirrorV; // bool
697 self->doClip = pdfOptions.doClip; // bool
698 PyObject *rotateDeg = PyLong_FromLong(0);
699 if (rotateDeg)
700 {
701 Py_DECREF(self->rotateDeg);
702 self->rotateDeg = rotateDeg;
703 }
704 else
705 {
706 PyErr_SetString(PyExc_SystemError, "Can not initialize 'rotateDeg' attribute");
707 return -1;
708 }
709 self->isGrayscale = pdfOptions.isGrayscale; // bool
710 self->pageLayout = pdfOptions.PageLayout; // int
711 self->displayBookmarks = pdfOptions.displayBookmarks; // bool
712 self->displayThumbs = pdfOptions.displayThumbs; // bool
713 self->displayLayers = pdfOptions.displayLayers; // bool
714 self->displayFullscreen = pdfOptions.displayFullscreen; // bool
715 self->hideToolBar = pdfOptions.hideToolBar; // bool
716 self->hideMenuBar = pdfOptions.hideMenuBar; // bool
717 self->fitWindow = pdfOptions.fitWindow; // bool
718
719 PyObject *openAction = PyUnicode_FromString(pdfOptions.openAction.toUtf8().data());
720 if (openAction)
721 {
722 Py_DECREF(self->openAction);
723 self->openAction = openAction;
724 }
725 else
726 {
727 PyErr_SetString(PyExc_SystemError, "Can not initialize 'openAction' attribute");
728 return -1;
729 }
730
731 return 0;
732 }
733
734 static PyMemberDef PDFfile_members[] = {
735 {const_cast<char*>("thumbnails"), T_INT, offsetof(PDFfile, thumbnails), 0, const_cast<char*>("Generate thumbnails. Bool value.")},
736 {const_cast<char*>("cropMarks"), T_INT, offsetof(PDFfile, cropMarks), 0, const_cast<char*>("Create crop marks in the PDF indicating where the paper should be cut or trimmed after printing.")},
737 {const_cast<char*>("bleedMarks"), T_INT, offsetof(PDFfile, bleedMarks), 0, const_cast<char*>("Create marks delimiting the bleed area.")},
738 {const_cast<char*>("registrationMarks"), T_INT, offsetof(PDFfile, registrationMarks), 0, const_cast<char*>("Add registration marks to each separation.")},
739 {const_cast<char*>("colorMarks"), T_INT, offsetof(PDFfile, colorMarks), 0, const_cast<char*>("Add color calibration bars.")},
740 {const_cast<char*>("docInfoMarks"), T_INT, offsetof(PDFfile, docInfoMarks), 0, const_cast<char*>("Add document information which includes the document title and page numbers.")},
741 {const_cast<char*>("markOffset"), T_DOUBLE, offsetof(PDFfile, markOffset), 0, const_cast<char*>("Indicate the distance offset between mark and page area.")},
742 {const_cast<char*>("markLength"), T_DOUBLE, offsetof(PDFfile, markLength), 0, const_cast<char*>("Indicate the length of crop and bleed marks.")},
743 {const_cast<char*>("compress"), T_INT, offsetof(PDFfile, compress), 0, const_cast<char*>("Compression switch. Bool value.")},
744 {const_cast<char*>("compressmtd"), T_INT, offsetof(PDFfile, compressmtd), 0, const_cast<char*>("Compression method.\n\t0 - Automatic\n\t1 - JPEG\n\t2 - zip\n\t3 - None.")},
745 {const_cast<char*>("quality"), T_INT, offsetof(PDFfile, quality), 0, const_cast<char*>("Image quality\n\t0 - Maximum\n\t1 - High\n\t2 - Medium\n\t3 - Low\n\t4 - Minimum")},
746 {const_cast<char*>("bookmarks"), T_INT, offsetof(PDFfile, bookmarks), 0, const_cast<char*>("Embed the bookmarks you created in your document.\nThese are useful for navigating long PDF documents.\nBool value")},
747 {const_cast<char*>("binding"), T_INT, offsetof(PDFfile, binding), 0, const_cast<char*>("Choose binding.\n\t0 - Left binding\n\t1 - Right binding")},
748 {const_cast<char*>("presentation"), T_INT, offsetof(PDFfile, presentation), 0, const_cast<char*>("Enable Presentation Effects.Bool value")},
749 {const_cast<char*>("article"), T_INT, offsetof(PDFfile, article), 0, const_cast<char*>("Save Linked Text Frames as PDF Articles\n\tBool value")},
750 {const_cast<char*>("encrypt"), T_INT, offsetof(PDFfile, encrypt), 0, const_cast<char*>("Use Encription. Bool value")},
751 {const_cast<char*>("uselpi"), T_INT, offsetof(PDFfile, uselpi), 0, const_cast<char*>("Use Custom Rendering Settings. Bool value")},
752 {const_cast<char*>("usespot"), T_INT, offsetof(PDFfile, usespot), 0, const_cast<char*>("Use Spot Colors. Bool value")},
753 {const_cast<char*>("domulti"), T_INT, offsetof(PDFfile, domulti), 0, const_cast<char*>("Produce a PDF File for every Page. Bool value")},
754 {const_cast<char*>("allowPrinting"), T_INT, offsetof(PDFfile, allowPrinting), 0, const_cast<char*>("Allow Printing the Document. Bool value")},
755 {const_cast<char*>("allowChange"), T_INT, offsetof(PDFfile, allowChange), 0, const_cast<char*>("Allow Changing the Document. Bool value")},
756 {const_cast<char*>("allowCopy"), T_INT, offsetof(PDFfile, allowCopy), 0, const_cast<char*>("Allow Copying Text and Graphics. Bool value")},
757 {const_cast<char*>("allowAnnots"), T_INT, offsetof(PDFfile, allowAnnots), 0, const_cast<char*>("Allow Adding Annotations and Fields. Bool value")},
758 {const_cast<char*>("version"), T_INT, offsetof(PDFfile, version), 0, const_cast<char*>("Choose PDF version to use:\n\t10 = PDF/X4\n\t11 = PDF/X1a\n\t12 = PDF/X-3\n\t13 = PDF 1.3 (Acrobat 4)\n\t14 = PDF 1.4 (Acrobat 5)\n\t15 = PDF 1.5 (Acrobat 6)")},
759 {const_cast<char*>("outdst"), T_INT, offsetof(PDFfile, outdst), 0, const_cast<char*>("Output destination.\n\t0 - screen\n\t1 - printer")},
760 {const_cast<char*>("profiles"), T_INT, offsetof(PDFfile, profiles), 0, const_cast<char*>("Embed a color profile for solid colors. Bool value.")},
761 {const_cast<char*>("profilei"), T_INT, offsetof(PDFfile, profilei), 0, const_cast<char*>("Embed a color profile for images. Bool value.")},
762 {const_cast<char*>("intents"), T_INT, offsetof(PDFfile, intents), 0, const_cast<char*>("Rendering intent for solid colors\n\t0 - Perceptual\n\t1 - Relative Colorimetric\n\t2 - Saturation\n\t3 - Absolute Colorimetric")},
763 {const_cast<char*>("intenti"), T_INT, offsetof(PDFfile, intenti), 0, const_cast<char*>("Rendering intent for images\n\t0 - Perceptual\n\t1 - Relative Colorimetric\n\t2 - Saturation\n\t3 - Absolute Colorimetric")},
764 {const_cast<char*>("noembicc"), T_INT, offsetof(PDFfile, noembicc), 0, const_cast<char*>("Don't use embedded ICC profiles. Bool value")},
765 {const_cast<char*>("bleedt"), T_DOUBLE, offsetof(PDFfile, bleedt), 0, const_cast<char*>("Bleed Top\n""Distance for bleed from the top of the physical page")},
766 {const_cast<char*>("bleedl"), T_DOUBLE, offsetof(PDFfile, bleedl), 0, const_cast<char*>("Bleed Left\n""Distance for bleed from the left of the physical page")},
767 {const_cast<char*>("bleedr"), T_DOUBLE, offsetof(PDFfile, bleedr), 0, const_cast<char*>("Bleed Right\n""Distance for bleed from the right of the physical page")},
768 {const_cast<char*>("bleedb"), T_DOUBLE, offsetof(PDFfile, bleedb), 0, const_cast<char*>("Bleed Bottom\n""Distance for bleed from the bottom of the physical page")},
769 {const_cast<char*>("useDocBleeds"), T_INT, offsetof(PDFfile, useDocBleeds), 0, const_cast<char*>("Use the existing bleed settings from the document preferences. Bool value")},
770 {const_cast<char*>("useLayers"), T_INT, offsetof(PDFfile, useLayers), 0, const_cast<char*>("Layers in your document are exported to the PDF. Only available if PDF 1.5 is chosen.")},
771 {const_cast<char*>("embedPDF"), T_INT, offsetof(PDFfile, embedPDF), 0, const_cast<char*>("Export EPS and PDFs in image frames as embedded PDFs. This does *not* yet take care of colorspaces, so you should know what you are doing before setting this to 'true'.")},
772 {const_cast<char*>("mirrorH"), T_INT, offsetof(PDFfile, mirrorH), 0, const_cast<char*>("Mirror Page(s) horizontally")},
773 {const_cast<char*>("mirrorV"), T_INT, offsetof(PDFfile, mirrorV), 0, const_cast<char*>("Mirror Page(s) vertically")},
774 {const_cast<char*>("doClip"), T_INT, offsetof(PDFfile, doClip), 0, const_cast<char*>("Do not show objects outside the margins in the exported file")},
775 {const_cast<char*>("isGrayscale"), T_INT, offsetof(PDFfile, isGrayscale), 0, const_cast<char*>("Export PDF in grayscale")},
776 {const_cast<char*>("pageLayout"), T_INT, offsetof(PDFfile, pageLayout), 0, const_cast<char*>("Document layout in PDF viewer:\n"
777 "\t0 - Show the document in single page mode\n"
778 "\t1 - Show the document in single page mode with the pages displayed continuously end to end like a scroll\n"
779 "\t2 - Show the document with facing pages, starting with the first page displayed on the left\n"
780 "\t3 - Show the document with facing pages, starting with the first page displayed on the right"
781 )},
782 {const_cast<char*>("displayBookmarks"), T_INT, offsetof(PDFfile, displayBookmarks), 0, const_cast<char*>("Display the bookmarks upon opening")},
783 {const_cast<char*>("displayThumbs"), T_INT, offsetof(PDFfile, displayThumbs), 0, const_cast<char*>("Display the page thumbnails upon opening")},
784 {const_cast<char*>("displayLayers"), T_INT, offsetof(PDFfile, displayLayers), 0, const_cast<char*>("Display the layer list upon opening. Useful only for PDF 1.5+.")},
785 {const_cast<char*>("displayFullscreen"), T_INT, offsetof(PDFfile, displayFullscreen), 0, const_cast<char*>("Display the document in full screen mode upon opening.")},
786 {const_cast<char*>("hideToolBar"), T_INT, offsetof(PDFfile, hideToolBar), 0, const_cast<char*>("Hide the viewer toolbar. The toolbar has usually selection and other editing capabilities.")},
787 {const_cast<char*>("hideMenuBar"), T_INT, offsetof(PDFfile, hideMenuBar), 0, const_cast<char*>("Hide the viewer menu bar, the PDF will display in a plain window.")},
788 {const_cast<char*>("fitWindow"), T_INT, offsetof(PDFfile, fitWindow), 0, const_cast<char*>("Fit the document page or pages to the available space in the viewer window.")},
789 /** Deprecated members */
790 {const_cast<char*>("aprint"), T_INT, offsetof(PDFfile, allowPrinting), 0, const_cast<char*>("Deprecated. Use 'allowPrinting' instead.")},
791 {const_cast<char*>("achange"), T_INT, offsetof(PDFfile, allowChange), 0, const_cast<char*>("Deprecated. Use 'allowChange' instead.")},
792 {const_cast<char*>("acopy"), T_INT, offsetof(PDFfile, allowCopy), 0, const_cast<char*>("Deprecated. Use 'allowCopy' instead.")},
793 {const_cast<char*>("aanot"), T_INT, offsetof(PDFfile, allowAnnots), 0, const_cast<char*>("Deprecated. Use 'allowAnnots' instead.")},
794 {nullptr, 0, 0, 0, nullptr} // sentinel
795 };
796
797
798 /* Here begins Getter & Setter functions */
799
PDFfile_getfile(PDFfile * self,void *)800 static PyObject *PDFfile_getfile(PDFfile *self, void * /*closure*/)
801 {
802 Py_INCREF(self->file);
803 return self->file;
804 }
805
PDFfile_setfile(PDFfile * self,PyObject * value,void *)806 static int PDFfile_setfile(PDFfile *self, PyObject *value, void * /*closure*/)
807 {
808 if (value == nullptr)
809 {
810 PyErr_SetString(PyExc_TypeError, "Cannot delete 'file' attribute.");
811 return -1;
812 }
813 if (!PyUnicode_Check(value))
814 {
815 PyErr_SetString(PyExc_TypeError, "The 'file' attribute value must be string.");
816 return -1;
817 }
818 Py_DECREF(self->file);
819 Py_INCREF(value);
820 self->file = value;
821 return 0;
822 }
823
PDFfile_getFontEmbeddingMode(PDFfile * self,void *)824 static PyObject *PDFfile_getFontEmbeddingMode(PDFfile *self, void * /*closure*/)
825 {
826 Py_INCREF(self->fontEmbedding);
827 return self->fontEmbedding;
828 }
829
PDFfile_setFontEmbeddingMode(PDFfile * self,PyObject * value,void *)830 static int PDFfile_setFontEmbeddingMode(PDFfile *self, PyObject *value, void * /*closure*/)
831 {
832 if (value == nullptr)
833 {
834 PyErr_SetString(PyExc_TypeError, "Cannot delete 'fontEmbedding' attribute.");
835 return -1;
836 }
837 if (!PyLong_Check(value))
838 {
839 PyErr_SetString(PyExc_TypeError, "'fontEmbedding' attribute value must be integer.");
840 return -1;
841 }
842 int n = PyLong_AsLong(value);
843 if (n < 0 || n > 2)
844 {
845 PyErr_SetString(PyExc_ValueError, "'fontEmbedding' value must be an integer between 0 and 2");
846 return -1;
847 }
848 Py_DECREF(self->fontEmbedding);
849 Py_INCREF(value);
850 self->fontEmbedding = value;
851 return 0;
852 }
853
PDFfile_getfonts(PDFfile * self,void *)854 static PyObject *PDFfile_getfonts(PDFfile *self, void * /*closure*/)
855 {
856 Py_INCREF(self->fonts);
857 return self->fonts;
858 }
859
PDFfile_setfonts(PDFfile * self,PyObject * value,void *)860 static int PDFfile_setfonts(PDFfile *self, PyObject *value, void * /*closure*/)
861 {
862 if (value == nullptr)
863 {
864 PyErr_SetString(PyExc_TypeError, "Cannot delete 'fonts' attribute.");
865 return -1;
866 }
867 if (!PyList_Check(value))
868 {
869 PyErr_SetString(PyExc_TypeError, "The 'fonts' attribute value must be list of strings.");
870 return -1;
871 }
872 int n = PyList_Size(value);
873 for (int i = 0; i < n; ++i)
874 {
875 if (!PyUnicode_Check(PyList_GetItem(value, i)))
876 {
877 PyErr_SetString(PyExc_TypeError, "The 'fonts' list must contain only strings.");
878 return -1;
879 }
880 }
881 // Do I need to check if supplied string is really
882 // name of available font???
883 // this is not implemented yet
884 Py_DECREF(self->fonts);
885 Py_INCREF(value);
886 self->fonts = value;
887 PyList_Sort(self->fonts);
888 return 0;
889 }
890
PDFfile_getSubsetList(PDFfile * self,void *)891 static PyObject *PDFfile_getSubsetList(PDFfile *self, void * /*closure*/)
892 {
893 Py_INCREF(self->subsetList);
894 return self->subsetList;
895 }
896
PDFfile_setSubsetList(PDFfile * self,PyObject * value,void *)897 static int PDFfile_setSubsetList(PDFfile *self, PyObject *value, void * /*closure*/)
898 {
899 if (value == nullptr)
900 {
901 PyErr_SetString(PyExc_TypeError, "Cannot delete 'subsetList' attribute.");
902 return -1;
903 }
904 if (!PyList_Check(value))
905 {
906 PyErr_SetString(PyExc_TypeError, "The 'subsetList' attribute value must be list of strings.");
907 return -1;
908 }
909 int n = PyList_Size(value);
910 for (int i = 0; i < n; ++i)
911 {
912 if (!PyUnicode_Check(PyList_GetItem(value, i)))
913 {
914 PyErr_SetString(PyExc_TypeError, "The 'subsetList' list must contain only strings.");
915 return -1;
916 }
917 }
918 Py_DECREF(self->subsetList);
919 Py_INCREF(value);
920 self->subsetList = value;
921 PyList_Sort(self->subsetList);
922 return 0;
923 }
924
PDFfile_getpages(PDFfile * self,void *)925 static PyObject *PDFfile_getpages(PDFfile *self, void * /*closure*/)
926 {
927 Py_INCREF(self->pages);
928 return self->pages;
929 }
930
PDFfile_setpages(PDFfile * self,PyObject * value,void *)931 static int PDFfile_setpages(PDFfile *self, PyObject *value, void * /*closure*/)
932 {
933 if (value == nullptr)
934 {
935 PyErr_SetString(PyExc_TypeError, "Cannot delete 'pages' attribute.");
936 return -1;
937 }
938 if (!PyList_Check(value))
939 {
940 PyErr_SetString(PyExc_TypeError, "'pages' attribute value must be list of integers.");
941 return -1;
942 }
943 int len = PyList_Size(value);
944 for (int i = 0; i < len; i++)
945 {
946 PyObject *tmp = PyList_GetItem(value, i);
947 // I did not check if tmp is nullptr
948 // how can PyList_GetItem fail in this case (my guess: short of available memory?)
949 // Also do I need Py_INCREF or Py_DECREF here?
950 if (!PyLong_Check(tmp))
951 {
952 PyErr_SetString(PyExc_TypeError, "'pages' list must contain only integers.");
953 return -1;
954 }
955 if (PyLong_AsLong(tmp) > static_cast<int>(ScCore->primaryMainWindow()->doc->Pages->count()) || PyLong_AsLong(tmp) < 1)
956 {
957 PyErr_SetString(PyExc_ValueError, "'pages' value out of range.");
958 return -1;
959 }
960 }
961 Py_DECREF(self->pages);
962 Py_INCREF(value);
963 self->pages = value;
964 return 0;
965 }
966
967
PDFfile_getresolution(PDFfile * self,void *)968 static PyObject *PDFfile_getresolution(PDFfile *self, void * /*closure*/)
969 {
970 Py_INCREF(self->resolution);
971 return self->resolution;
972 }
973
PDFfile_setresolution(PDFfile * self,PyObject * value,void *)974 static int PDFfile_setresolution(PDFfile *self, PyObject *value, void * /*closure*/)
975 {
976 if (value == nullptr)
977 {
978 PyErr_SetString(PyExc_TypeError, "Cannot delete 'resolution' attribute.");
979 return -1;
980 }
981 if (!PyLong_Check(value))
982 {
983 PyErr_SetString(PyExc_TypeError, "'resolution' attribute value must be integer.");
984 return -1;
985 }
986 int n = PyLong_AsLong(value);
987 if (n < 35 || n > 4000)
988 {
989 PyErr_SetString(PyExc_ValueError, "'resolution' value must be in interval from 35 to 4000");
990 return -1;
991 }
992 Py_DECREF(self->resolution);
993 Py_INCREF(value);
994 self->resolution = value;
995 return 0;
996 }
997
PDFfile_getdownsample(PDFfile * self,void *)998 static PyObject *PDFfile_getdownsample(PDFfile *self, void * /*closure*/)
999 {
1000 Py_INCREF(self->downsample);
1001 return self->downsample;
1002 }
1003
PDFfile_setdownsample(PDFfile * self,PyObject * value,void *)1004 static int PDFfile_setdownsample(PDFfile *self, PyObject *value, void * /*closure*/)
1005 {
1006 if (value == nullptr)
1007 {
1008 PyErr_SetString(PyExc_TypeError, "Cannot delete 'downsample' attribute.");
1009 return -1;
1010 }
1011 if (!PyLong_Check(value))
1012 {
1013 PyErr_SetString(PyExc_TypeError, "'downsample' attribute value must be integer.");
1014 return -1;
1015 }
1016 int n = PyLong_AsLong(value);
1017 if (n != 0 && (n < 35 || n > PyLong_AsLong(self->resolution)))
1018 {
1019 PyErr_SetString(PyExc_TypeError, "'downsample' value must be 0 or in interval from 35 to value of 'resolution'");
1020 return -1;
1021 }
1022 Py_DECREF(self->downsample);
1023 Py_INCREF(value);
1024 self->downsample = value;
1025 return 0;
1026 }
1027
PDFfile_geteffval(PDFfile * self,void *)1028 static PyObject *PDFfile_geteffval(PDFfile *self, void * /*closure*/)
1029 {
1030 Py_INCREF(self->effval);
1031 return self->effval;
1032 }
1033
PDFfile_seteffval(PDFfile * self,PyObject * value,void *)1034 static int PDFfile_seteffval(PDFfile *self, PyObject *value, void * /*closure*/)
1035 {
1036 if (value == nullptr)
1037 {
1038 PyErr_SetString(PyExc_TypeError, "Cannot delete 'effval' attribute.");
1039 return -1;
1040 }
1041 if (!PyList_Check(value))
1042 {
1043 PyErr_SetString(PyExc_TypeError, "'effval' must be list.");
1044 return -1;
1045 }
1046 int n = PyList_Size(value);
1047 for (int i = 0; i < n; ++i)
1048 {
1049 PyObject *tmp = PyList_GetItem(value, i);
1050 if (!PyList_Check(tmp))
1051 {
1052 PyErr_SetString(PyExc_TypeError, "elemets of 'effval' must be list of five integers.");
1053 return -1;
1054 }
1055 int j = PyList_Size(tmp);
1056 if (j != 6)
1057 {
1058 PyErr_SetString(PyExc_TypeError, "elemets of 'effval' must have exactly six integers.");
1059 return -1;
1060 }
1061 for (--j; j > -1; --j)
1062 {
1063 if (!PyLong_Check(PyList_GetItem(tmp, j)))
1064 {
1065 PyErr_SetString(PyExc_TypeError, "innermost element of 'effval' must be integers.");
1066 return -1;
1067 }
1068 }
1069 }
1070 Py_DECREF(self->effval);
1071 Py_INCREF(value);
1072 self->effval = value;
1073 return 0;
1074 }
1075
PDFfile_getlpival(PDFfile * self,void *)1076 static PyObject *PDFfile_getlpival(PDFfile *self, void * /*closure*/)
1077 {
1078 Py_INCREF(self->lpival);
1079 return self->lpival;
1080 }
1081
PDFfile_setlpival(PDFfile * self,PyObject * value,void *)1082 static int PDFfile_setlpival(PDFfile *self, PyObject *value, void * /*closure*/)
1083 {
1084 if (value == nullptr)
1085 {
1086 PyErr_SetString(PyExc_TypeError, "Cannot delete 'lpival' attribute.");
1087 return -1;
1088 }
1089 if (!PyList_Check(value))
1090 {
1091 PyErr_SetString(PyExc_TypeError, "'lpival' must be list.");
1092 return -1;
1093 }
1094 // Do I need Py_INCREF or Py_DECREF here?
1095 int n = PyList_Size(value);
1096 for (int i = 0; i < n; ++i)
1097 {
1098 PyObject *tmp = PyList_GetItem(value, i);
1099 if (!PyList_Check(tmp))
1100 {
1101 PyErr_SetString(PyExc_TypeError, "elements of 'lpival' must be list of five integers.");
1102 return -1;
1103 }
1104 int j = PyList_Size(tmp);
1105 if (j != 4)
1106 {
1107 PyErr_SetString(PyExc_TypeError, "elements of 'lpival' must have exactly four members.");
1108 return -1;
1109 }
1110 for (--j; j > 0; --j)
1111 {
1112 if (!PyLong_Check(PyList_GetItem(tmp, j)))
1113 {
1114 PyErr_SetString(PyExc_TypeError, "'lpival'elements must have structure [siii]");
1115 return -1;
1116 }
1117 }
1118 if (!PyUnicode_Check(PyList_GetItem(tmp, 0)))
1119 {
1120 PyErr_SetString(PyExc_TypeError, "'lpival'elements must have structure [siii]");
1121 return -1;
1122 }
1123 }
1124 Py_DECREF(self->lpival);
1125 Py_INCREF(value);
1126 self->lpival = value;
1127 return 0;
1128 }
1129
PDFfile_getowner(PDFfile * self,void *)1130 static PyObject *PDFfile_getowner(PDFfile *self, void * /*closure*/)
1131 {
1132 Py_INCREF(self->owner);
1133 return self->owner;
1134 }
1135
PDFfile_setowner(PDFfile * self,PyObject * value,void *)1136 static int PDFfile_setowner(PDFfile *self, PyObject *value, void * /*closure*/)
1137 {
1138 if (value == nullptr)
1139 {
1140 PyErr_SetString(PyExc_TypeError, "Cannot delete 'owner' attribute.");
1141 return -1;
1142 }
1143 if (!PyUnicode_Check(value))
1144 {
1145 PyErr_SetString(PyExc_TypeError, "'owner' attribute value must be string.");
1146 return -1;
1147 }
1148 Py_DECREF(self->owner);
1149 Py_INCREF(value);
1150 self->owner = value;
1151 return 0;
1152 }
1153
PDFfile_getuser(PDFfile * self,void *)1154 static PyObject *PDFfile_getuser(PDFfile *self, void * /*closure*/)
1155 {
1156 Py_INCREF(self->user);
1157 return self->user;
1158 }
1159
PDFfile_setuser(PDFfile * self,PyObject * value,void *)1160 static int PDFfile_setuser(PDFfile *self, PyObject *value, void * /*closure*/)
1161 {
1162 if (value == nullptr)
1163 {
1164 PyErr_SetString(PyExc_TypeError, "Cannot delete 'user' attribute.");
1165 return -1;
1166 }
1167 if (!PyUnicode_Check(value))
1168 {
1169 PyErr_SetString(PyExc_TypeError, "'user' attribute value must be string.");
1170 return -1;
1171 }
1172 Py_DECREF(self->user);
1173 Py_INCREF(value);
1174 self->user = value;
1175 return 0;
1176 }
1177
PDFfile_getsolidpr(PDFfile * self,void *)1178 static PyObject *PDFfile_getsolidpr(PDFfile *self, void * /*closure*/)
1179 {
1180 Py_INCREF(self->solidpr);
1181 return self->solidpr;
1182 }
1183
PDFfile_setsolidpr(PDFfile * self,PyObject * value,void *)1184 static int PDFfile_setsolidpr(PDFfile *self, PyObject *value, void * /*closure*/)
1185 {
1186 if (value == nullptr)
1187 {
1188 PyErr_SetString(PyExc_TypeError, "Cannot delete 'solidpr' attribute.");
1189 return -1;
1190 }
1191 if (!PyUnicode_Check(value))
1192 {
1193 PyErr_SetString(PyExc_TypeError, "The 'solidpr' attribute value must be string.");
1194 return -1;
1195 }
1196 Py_DECREF(self->solidpr);
1197 Py_INCREF(value);
1198 self->solidpr = value;
1199 return 0;
1200 }
1201
PDFfile_getimagepr(PDFfile * self,void *)1202 static PyObject *PDFfile_getimagepr(PDFfile *self, void * /*closure*/)
1203 {
1204 Py_INCREF(self->imagepr);
1205 return self->imagepr;
1206 }
1207
PDFfile_setimagepr(PDFfile * self,PyObject * value,void *)1208 static int PDFfile_setimagepr(PDFfile *self, PyObject *value, void * /*closure*/)
1209 {
1210 if (value == nullptr)
1211 {
1212 PyErr_SetString(PyExc_TypeError, "Cannot delete 'imagepr' attribute.");
1213 return -1;
1214 }
1215 if (!PyUnicode_Check(value))
1216 {
1217 PyErr_SetString(PyExc_TypeError, "The 'imagepr' attribute value must be string.");
1218 return -1;
1219 }
1220 Py_DECREF(self->imagepr);
1221 Py_INCREF(value);
1222 self->imagepr = value;
1223 return 0;
1224 }
1225
PDFfile_getprintprofc(PDFfile * self,void *)1226 static PyObject *PDFfile_getprintprofc(PDFfile *self, void * /*closure*/)
1227 {
1228 Py_INCREF(self->printprofc);
1229 return self->printprofc;
1230 }
1231
PDFfile_setprintprofc(PDFfile * self,PyObject * value,void *)1232 static int PDFfile_setprintprofc(PDFfile *self, PyObject *value, void * /*closure*/)
1233 {
1234 if (value == nullptr)
1235 {
1236 PyErr_SetString(PyExc_TypeError, "Cannot delete 'printprofc' attribute.");
1237 return -1;
1238 }
1239 if (!PyUnicode_Check(value))
1240 {
1241 PyErr_SetString(PyExc_TypeError, "The 'printprofc' attribute value must be string.");
1242 return -1;
1243 }
1244 Py_DECREF(self->printprofc);
1245 Py_INCREF(value);
1246 self->printprofc = value;
1247 return 0;
1248 }
1249
PDFfile_getinfo(PDFfile * self,void *)1250 static PyObject *PDFfile_getinfo(PDFfile *self, void * /*closure*/)
1251 {
1252 Py_INCREF(self->info);
1253 return self->info;
1254 }
1255
PDFfile_setinfo(PDFfile * self,PyObject * value,void *)1256 static int PDFfile_setinfo(PDFfile *self, PyObject *value, void * /*closure*/)
1257 {
1258 if (value == nullptr)
1259 {
1260 PyErr_SetString(PyExc_TypeError, "Cannot delete 'info' attribute.");
1261 return -1;
1262 }
1263 if (!PyUnicode_Check(value))
1264 {
1265 PyErr_SetString(PyExc_TypeError, "The 'info' attribute value must be string.");
1266 return -1;
1267 }
1268 Py_DECREF(self->info);
1269 Py_INCREF(value);
1270 self->info = value;
1271 return 0;
1272 }
1273
PDFfile_getRotateDeg(PDFfile * self,void *)1274 static PyObject *PDFfile_getRotateDeg(PDFfile *self, void * /*closure*/)
1275 {
1276 Py_INCREF(self->rotateDeg);
1277 return self->rotateDeg;
1278 }
1279
PDFfile_setRotateDeg(PDFfile * self,PyObject * value,void *)1280 static int PDFfile_setRotateDeg(PDFfile *self, PyObject *value, void * /*closure*/)
1281 {
1282 if (value == nullptr)
1283 {
1284 PyErr_SetString(PyExc_TypeError, "Cannot delete 'rotateDeg' attribute.");
1285 return -1;
1286 }
1287 if (!PyLong_Check(value))
1288 {
1289 PyErr_SetString(PyExc_TypeError, "'rotateDeg' attribute value must be integer.");
1290 return -1;
1291 }
1292 int n = PyLong_AsLong(value);
1293 if (n != 0 && n != 90 && n != 180 && n != 270)
1294 {
1295 PyErr_SetString(PyExc_TypeError, "'rotateDeg' value must be 0 or 90 or 180 or 270");
1296 return -1;
1297 }
1298 Py_DECREF(self->rotateDeg);
1299 Py_INCREF(value);
1300 self->rotateDeg = value;
1301 return 0;
1302 }
1303
PDFfile_getopenAction(PDFfile * self,void *)1304 static PyObject *PDFfile_getopenAction(PDFfile *self, void * /*closure*/)
1305 {
1306 Py_INCREF(self->openAction);
1307 return self->openAction;
1308 }
1309
PDFfile_setopenAction(PDFfile * self,PyObject * value,void *)1310 static int PDFfile_setopenAction(PDFfile *self, PyObject *value, void * /*closure*/)
1311 {
1312 if (value == nullptr)
1313 {
1314 PyErr_SetString(PyExc_TypeError, "Cannot delete 'openAction' attribute.");
1315 return -1;
1316 }
1317 if (!PyUnicode_Check(value))
1318 {
1319 PyErr_SetString(PyExc_TypeError, "'openAction' attribute value must be string.");
1320 return -1;
1321 }
1322 Py_DECREF(self->openAction);
1323 Py_INCREF(value);
1324 self->openAction = value;
1325 return 0;
1326 }
1327
1328 static char *effval_doc = const_cast<char*>(
1329 "List of effection values for each saved page.\n"
1330 "It is list of list of six integers. Those int has followin meaning:\n\t"
1331 "- Length of time the page is shown before the presentation\n\tstarts on the selected page. (1-3600)\n\t"
1332 "- Length of time the effect runs. (1 - 3600)\n\t\tA shorter time will speed up the effect,\n\t\ta longer one will slow it down\n\t"
1333 "- Type of the display effect\n\t\t0 - No Effect\n\t\t1 - Blinds\n\t\t2 - Box\n\t\t3 - Dissolve\n\t\t4 - Glitter\n\t\t5 - Split\n\t\t6 - Wipe\n\t"
1334 "- Direction of the effect of moving lines\n\tfor the split and blind effects.\n\t\t0 - Horizontal\n\t\t1 - Vertical\n\t"
1335 "- Starting position for the box and split effects.\n\t\t0 - Inside\n\t\t1 - Outside\n\t"
1336 "- Direction of the glitter or wipe effects.\n\t\t0 - Left to Right\n\t\t1 - Top to Bottom\n\t\t2 - Bottom to Top\n\t\t3 - Right to Left\n\t\t4 - Top-left to Bottom-Right");
1337
1338 static char *lpival_doc = const_cast<char*>(
1339 "Rendering Settings for individual colors.\n\n"
1340 "This is list of values for each color\n"
1341 "Color values have structure [siii] which stand for:\n\t"
1342 "s - Color name ('Black', 'Cyan', 'Magenta', 'Yellow')\n\t"
1343 "i - Frequency (10 to 1000)\n\t"
1344 "i - Angle (-180 to 180)\n\t"
1345 "i - Spot Function\n\t\t0 - Simple Dot\n\t\t1 - Line\n\t\t2 - Round\n\t\t3 - Ellipse\n"
1346 "Be careful when supplying these values as they\nare not checked for validity.");
1347
1348 static PyGetSetDef PDFfile_getseters [] = {
1349 {const_cast<char*>("file"), (getter)PDFfile_getfile, (setter)PDFfile_setfile, const_cast<char*>("Name of file to save into"), nullptr},
1350 {const_cast<char*>("fontEmbedding"), (getter)PDFfile_getFontEmbeddingMode, (setter)PDFfile_setFontEmbeddingMode, const_cast<char*>("Font embedding mode.\n\tValue must be one of integers: 0 (Embed), 1 (Outline), 2 (No embedding)."), nullptr},
1351 {const_cast<char*>("fonts"), (getter)PDFfile_getfonts, (setter)PDFfile_setfonts, const_cast<char*>("List of fonts to embed."), nullptr},
1352 {const_cast<char*>("subsetList"), (getter)PDFfile_getSubsetList, (setter)PDFfile_setSubsetList, const_cast<char*>("List of fonts to subsetted."), nullptr},
1353 {const_cast<char*>("pages"), (getter)PDFfile_getpages, (setter)PDFfile_setpages, const_cast<char*>("List of pages to print"), nullptr},
1354 {const_cast<char*>("resolution"), (getter)PDFfile_getresolution, (setter)PDFfile_setresolution, const_cast<char*>("Resolution of output file. Values from 35 to 4000."), nullptr},
1355 {const_cast<char*>("downsample"), (getter)PDFfile_getdownsample, (setter)PDFfile_setdownsample, const_cast<char*>("Downsample image resolusion to this value. Values from 35 to 4000\nSet 0 for not to downsample"), nullptr},
1356 {const_cast<char*>("effval"), (getter)PDFfile_geteffval, (setter)PDFfile_seteffval, effval_doc, nullptr},
1357 {const_cast<char*>("lpival"), (getter)PDFfile_getlpival, (setter)PDFfile_setlpival, lpival_doc, nullptr},
1358 {const_cast<char*>("owner"), (getter)PDFfile_getowner, (setter)PDFfile_setowner, const_cast<char*>("Owner's password"), nullptr},
1359 {const_cast<char*>("user"), (getter)PDFfile_getuser, (setter)PDFfile_setuser, const_cast<char*>("User's password"), nullptr},
1360 {const_cast<char*>("solidpr"), (getter)PDFfile_getsolidpr, (setter)PDFfile_setsolidpr, const_cast<char*>("Color profile for solid colors"), nullptr},
1361 {const_cast<char*>("imagepr"), (getter)PDFfile_getimagepr, (setter)PDFfile_setimagepr, const_cast<char*>("Color profile for images"), nullptr},
1362 {const_cast<char*>("printprofc"), (getter)PDFfile_getprintprofc, (setter)PDFfile_setprintprofc, const_cast<char*>("Output profile for printing. If possible, get some guidance from your printer on profile selection."), nullptr},
1363 {const_cast<char*>("info"), (getter)PDFfile_getinfo, (setter)PDFfile_setinfo, const_cast<char*>("Mandatory string for PDF/X or the PDF will fail\nPDF/X conformance. We recommend you use the title of the document."), nullptr},
1364 {const_cast<char*>("rotateDeg"), (getter)PDFfile_getRotateDeg, (setter)PDFfile_setRotateDeg, const_cast<char*>("Automatically rotate the exported pages\n\tValue must be one of integers: 0, 90, 180 or 270"), nullptr},
1365 {const_cast<char*>("openAction"), (getter)PDFfile_getopenAction, (setter)PDFfile_setopenAction, const_cast<char*>("Javascript to be executed when PDF document is opened."), nullptr},
1366 {nullptr, nullptr, nullptr, nullptr, nullptr} // sentinel
1367 };
1368
PDFfile_save(PDFfile * self)1369 static PyObject *PDFfile_save(PDFfile *self)
1370 {
1371 if (!checkHaveDocument())
1372 return nullptr;
1373
1374 ScribusDoc* currentDoc = ScCore->primaryMainWindow()->doc;
1375 PDFOptions& pdfOptions = currentDoc->pdfOptions();
1376
1377 // Copied from file scribus.cpp
1378 // void ScribusMainWindow::SaveAsPDF()
1379 if (ScCore->primaryMainWindow()->bookmarkPalette->BView->topLevelItemCount() == 0)
1380 pdfOptions.Bookmarks = false;
1381
1382 // Get PDF version
1383 self->version = minmaxi(self->version, PDFVersion::PDFVersion_Min, PDFVersion::PDFVersion_Max);
1384 pdfOptions.Version = (PDFVersion::Version) self->version;
1385
1386 // Update used fonts
1387 currentDoc->reorganiseFonts();
1388
1389 // Apply fonts attribute
1390 pdfOptions.EmbedList.clear();
1391 int n = PyList_Size(self->fonts);
1392 for (int i = 0; i < n; ++i)
1393 {
1394 QString tmpFon;
1395 tmpFon = PyUnicode_asQString(PyList_GetItem(self->fonts, i));
1396 pdfOptions.EmbedList.append(tmpFon);
1397 }
1398 // Apply SubsetList attribute
1399 pdfOptions.SubsetList.clear();
1400 n = PyList_Size(self->subsetList);
1401 for (int i = 0; i < n; ++i)
1402 {
1403 QString tmpFon;
1404 tmpFon = PyUnicode_asQString(PyList_GetItem(self->subsetList, i));
1405 pdfOptions.SubsetList.append(tmpFon);
1406 }
1407 // Apply font embedding mode
1408 pdfOptions.FontEmbedding = (PDFOptions::PDFFontEmbedding) PyLong_AsLong(self->fontEmbedding);
1409 if (pdfOptions.Version == PDFVersion::PDF_X1a ||
1410 pdfOptions.Version == PDFVersion::PDF_X3 ||
1411 pdfOptions.Version == PDFVersion::PDF_X4)
1412 {
1413 pdfOptions.FontEmbedding = PDFOptions::EmbedFonts;
1414 }
1415 if (pdfOptions.FontEmbedding == PDFOptions::EmbedFonts)
1416 {
1417 QStringList docFonts = currentDoc->UsedFonts.keys();
1418 for (int i = 0; i < docFonts.count(); ++i)
1419 {
1420 const QString& fontName = docFonts.at(i);
1421 if (pdfOptions.SubsetList.contains(fontName))
1422 continue;
1423 if (pdfOptions.EmbedList.contains(fontName))
1424 continue;
1425 pdfOptions.SubsetList.append(fontName);
1426 }
1427 pdfOptions.OutlineList = QStringList();
1428 }
1429 else if (pdfOptions.FontEmbedding == PDFOptions::OutlineFonts)
1430 {
1431 pdfOptions.EmbedList = QStringList();
1432 pdfOptions.SubsetList = QStringList();
1433 pdfOptions.OutlineList = currentDoc->UsedFonts.keys();
1434 }
1435 else
1436 {
1437 pdfOptions.EmbedList = QStringList();
1438 pdfOptions.SubsetList = QStringList();
1439 pdfOptions.OutlineList = QStringList();
1440 }
1441 // Apply file attribute
1442 QString fn = PyUnicode_asQString(self->file);
1443 pdfOptions.fileName = fn;
1444 // Apply pages attribute
1445 std::vector<int> pageNs;
1446 int nn = PyList_Size(self->pages);
1447 for (int i = 0; i < nn; ++i) {
1448 pageNs.push_back((int) PyLong_AsLong(PyList_GetItem(self->pages, i)));
1449 }
1450 // Apply thumbnails attribute
1451 pdfOptions.Thumbnails = self->thumbnails;
1452 // Apply cropmarks attribute
1453 pdfOptions.cropMarks = self->cropMarks;
1454 // Apply bleedmarks attribute
1455 pdfOptions.bleedMarks = self->bleedMarks;
1456 // Apply registrationmarks attribute
1457 pdfOptions.registrationMarks = self->registrationMarks;
1458 // Apply colormarks attribute
1459 pdfOptions.colorMarks = self->colorMarks;
1460 // Apply docInfoMark attribute
1461 pdfOptions.docInfoMarks = self->docInfoMarks;
1462 // Apply mark offset attribute
1463 pdfOptions.markOffset = qMax(0.0, self->markOffset / currentDoc->unitRatio());
1464 // Apply mark length attribute
1465 pdfOptions.markLength = qMax(0.0, self->markLength / currentDoc->unitRatio());
1466 // Apply compress attribute
1467 self->compressmtd = minmaxi(self->compressmtd, 0, 3);
1468 pdfOptions.Compress = self->compress;
1469 pdfOptions.CompressMethod = (PDFOptions::PDFCompression) self->compressmtd;
1470 // Apply quality attribute
1471 self->quality = minmaxi(self->quality, 0, 4);
1472 pdfOptions.Quality = self->quality;
1473 // Apply resolusion attribute
1474 pdfOptions.Resolution = PyLong_AsLong(self->resolution);
1475 // Apply downsample attribute
1476 pdfOptions.RecalcPic = PyLong_AsLong(self->downsample);
1477 if (pdfOptions.RecalcPic)
1478 pdfOptions.PicRes = PyLong_AsLong(self->downsample);
1479 else
1480 pdfOptions.PicRes = pdfOptions.Resolution;
1481 // Apply bookmarks attribute
1482 pdfOptions.Bookmarks = self->bookmarks;
1483 // Apply binding attribute
1484 pdfOptions.Binding = self->binding;
1485 // Apply presentation attribute
1486 pdfOptions.PresentMode = self->presentation;
1487
1488 int tmpnum = PyList_Size(self->effval);
1489 for (int i = 0; i < tmpnum; ++i)
1490 {
1491 PDFPresentationData t;
1492 PyObject *ti = PyList_GetItem(self->effval, i);
1493 if (!ti)
1494 continue;
1495 // Do I Need to check if every PyLong_AsLong and PyList_GetItem funtion succeed???
1496 t.pageEffectDuration = PyLong_AsLong(PyList_GetItem(ti, 0));
1497 t.pageViewDuration = PyLong_AsLong(PyList_GetItem(ti, 1));
1498 t.effectType = PyLong_AsLong(PyList_GetItem(ti, 2));
1499 t.Dm = PyLong_AsLong(PyList_GetItem(ti, 3));
1500 t.M = PyLong_AsLong(PyList_GetItem(ti, 4));
1501 t.Di = PyLong_AsLong(PyList_GetItem(ti, 5));
1502 // PresentVals.append(t);
1503 }
1504 // pdfOptions.PresentVals = PresentVals;
1505
1506 // Apply lpival
1507 int n2 = PyList_Size(self->lpival);
1508 for (int i = 0; i < n2; ++i)
1509 {
1510 LPIData lpi;
1511 PyObject *t = PyList_GetItem(self->lpival, i);
1512 // This code always raise exception - WHY???
1513 // char *s;
1514 // if (!PyArg_ParseTuple(t, "[siii]", &s, &lpi.Frequency,
1515 // &lpi.Angle, &lpi.SpotFunc)) {
1516 // PyErr_SetString(PyExc_SystemError, "while parsing 'lpival'. WHY THIS HAPPENED????");
1517 // return nullptr;
1518 // }
1519 // pdfOptions.LPISettings[QString(s)]=lpi;
1520 QString st = PyUnicode_asQString(PyList_GetItem(t, 0));
1521 lpi.Frequency = PyLong_AsLong(PyList_GetItem(t, 1));
1522 lpi.Angle = PyLong_AsLong(PyList_GetItem(t, 2));
1523 lpi.SpotFunc = PyLong_AsLong(PyList_GetItem(t, 3));
1524 pdfOptions.LPISettings[st] = lpi;
1525 }
1526
1527 pdfOptions.Articles = self->article;
1528 pdfOptions.Encrypt = self->encrypt;
1529 pdfOptions.UseLPI = self->uselpi;
1530 pdfOptions.UseSpotColors = self->usespot;
1531 pdfOptions.doMultiFile = self->domulti;
1532
1533 if (self->encrypt)
1534 {
1535 int Perm = -64;
1536 if (pdfOptions.Version == PDFVersion::PDF_14)
1537 Perm &= ~0x00240000;
1538 if (self->allowPrinting)
1539 Perm += 4;
1540 if (self->allowChange)
1541 Perm += 8;
1542 if (self->allowCopy)
1543 Perm += 16;
1544 if (self->allowAnnots)
1545 Perm += 32;
1546 pdfOptions.Permissions = Perm;
1547 pdfOptions.PassOwner = PyUnicode_asQString(self->owner);
1548 pdfOptions.PassUser = PyUnicode_asQString(self->user);
1549 }
1550 if (self->outdst == 0)
1551 {
1552 pdfOptions.UseRGB = true;
1553 pdfOptions.UseProfiles = false;
1554 pdfOptions.UseProfiles2 = false;
1555 }
1556 else
1557 {
1558 pdfOptions.UseRGB = false;
1559 if (ScCore->primaryMainWindow()->doc->HasCMS)
1560 {
1561 pdfOptions.UseProfiles = self->profiles;
1562 pdfOptions.UseProfiles2 = self->profilei;
1563 self->intents = minmaxi(self->intents, 0, 3);
1564 pdfOptions.Intent = self->intents;
1565 self->intenti = minmaxi(self->intenti, 0, 3);
1566 pdfOptions.Intent2 = self->intenti;
1567 pdfOptions.EmbeddedI = self->noembicc;
1568 pdfOptions.SolidProf = PyUnicode_asQString(self->solidpr);
1569 pdfOptions.ImageProf = PyUnicode_asQString(self->imagepr);
1570 pdfOptions.PrintProf = PyUnicode_asQString(self->printprofc);
1571 if (pdfOptions.Version == PDFVersion::PDF_X1a ||
1572 pdfOptions.Version == PDFVersion::PDF_X3 ||
1573 pdfOptions.Version == PDFVersion::PDF_X4)
1574 {
1575 pdfOptions.Info = PyUnicode_asQString(self->info);
1576 pdfOptions.Encrypt = false;
1577 pdfOptions.PresentMode = false;
1578 }
1579 }
1580 else
1581 {
1582 pdfOptions.UseProfiles = false;
1583 pdfOptions.UseProfiles2 = false;
1584 }
1585 }
1586
1587 QMap<int, QImage> thumbs;
1588 PageToPixmapFlags pixmapFlags = Pixmap_DontReloadImages | Pixmap_DrawWhiteBackground;
1589 for (uint ap = 0; ap < pageNs.size(); ++ap)
1590 {
1591 QImage thumb(10, 10, QImage::Format_ARGB32_Premultiplied );
1592 if (pdfOptions.Thumbnails)
1593 thumb = ScCore->primaryMainWindow()->view->PageToPixmap(pageNs[ap] - 1, 100, pixmapFlags);
1594 thumbs.insert(pageNs[ap], thumb);
1595 }
1596
1597 ReOrderText(ScCore->primaryMainWindow()->doc, ScCore->primaryMainWindow()->view);
1598
1599 MarginStruct optBleeds(pdfOptions.bleeds);
1600 pdfOptions.useDocBleeds = self->useDocBleeds;
1601 if (self->useDocBleeds)
1602 pdfOptions.bleeds = ScCore->primaryMainWindow()->doc->bleedsVal();
1603 else
1604 {
1605 self->bleedt = minmaxd(self->bleedt, 0, currentDoc->pageHeight() * currentDoc->unitRatio());
1606 pdfOptions.bleeds.setTop(self->bleedt / currentDoc->unitRatio());
1607 self->bleedl = minmaxd(self->bleedl, 0, currentDoc->pageWidth() * currentDoc->unitRatio());
1608 pdfOptions.bleeds.setLeft(self->bleedl / currentDoc->unitRatio());
1609 self->bleedr = minmaxd(self->bleedr, 0, currentDoc->pageWidth() * currentDoc->unitRatio());
1610 pdfOptions.bleeds.setRight(self->bleedr / currentDoc->unitRatio());
1611 self->bleedb = minmaxd(self->bleedb, 0, currentDoc->pageHeight() * currentDoc->unitRatio());
1612 pdfOptions.bleeds.setBottom(self->bleedb / currentDoc->unitRatio());
1613 }
1614 pdfOptions.useLayers = self->useLayers;
1615 pdfOptions.embedPDF = self->embedPDF;
1616 pdfOptions.MirrorH = self->mirrorH;
1617 pdfOptions.MirrorV = self->mirrorV;
1618 pdfOptions.doClip = self->doClip;
1619 pdfOptions.RotateDeg = PyLong_AsLong(self->rotateDeg);
1620 pdfOptions.isGrayscale = self->isGrayscale;
1621 pdfOptions.PageLayout = minmaxi(self->pageLayout, 0, 3);
1622 pdfOptions.displayBookmarks = self->displayBookmarks;
1623 pdfOptions.displayThumbs = self->displayThumbs;
1624 pdfOptions.displayLayers = self->displayLayers;
1625 pdfOptions.displayFullscreen = self->displayFullscreen;
1626 pdfOptions.hideToolBar = self->hideToolBar;
1627 pdfOptions.hideMenuBar = self->hideMenuBar;
1628 pdfOptions.fitWindow = self->fitWindow;
1629 pdfOptions.openAction = PyUnicode_asQString(self->openAction);
1630 pdfOptions.firstUse = false;
1631
1632 QString errorMessage;
1633 bool success = ScCore->primaryMainWindow()->getPDFDriver(fn, pageNs, thumbs, errorMessage);
1634 if (!success)
1635 {
1636 fn = "Cannot write the File: " + fn;
1637 if (!errorMessage.isEmpty())
1638 fn += QString("\n%1").arg(errorMessage);
1639 PyErr_SetString(PyExc_SystemError, fn.toLatin1());
1640 }
1641
1642 if (self->useDocBleeds)
1643 pdfOptions.bleeds = optBleeds;
1644
1645 if (success)
1646 Py_RETURN_NONE;
1647 return nullptr;
1648 }
1649
1650 static PyMethodDef PDFfile_methods[] = {
1651 {const_cast<char*>("save"), (PyCFunction)PDFfile_save, METH_NOARGS, pdffile_save__doc__},
1652 {nullptr, (PyCFunction)(nullptr), 0, nullptr} // sentinel
1653 };
1654
1655 PyTypeObject PDFfile_Type = {
1656 PyVarObject_HEAD_INIT(nullptr, 0) // PyObject_VAR_HEAD //
1657 const_cast<char*>("scribus.PDFfile"), // char *tp_name; /* For printing, in format "<module>.<name>" */
1658 sizeof(PDFfile), // int tp_basicsize, /* For allocation */
1659 0, // int tp_itemsize; /* For allocation */
1660
1661 /* Methods to implement standard operations */
1662
1663 (destructor) PDFfile_dealloc, // destructor tp_dealloc;
1664 #if PY_VERSION_HEX >= 0x03080000
1665 0, // Py_ssize_t tp_vectorcall_offset
1666 #else
1667 nullptr, // printfunc tp_print;
1668 #endif
1669 nullptr, // getattrfunc tp_getattr;
1670 nullptr, // setattrfunc tp_setattr;
1671 nullptr, // cmpfunc tp_as_async;
1672 nullptr, // reprfunc tp_repr;
1673
1674 /* Method suites for standard classes */
1675
1676 nullptr, // PyNumberMethods *tp_as_number;
1677 nullptr, // PySequenceMethods *tp_as_sequence;
1678 nullptr, // PyMappingMethods *tp_as_mapping;
1679
1680 /* More standard operations (here for binary compatibility) */
1681
1682 nullptr, // hashfunc tp_hash;
1683 nullptr, // ternaryfunc tp_call;
1684 nullptr, // reprfunc tp_str;
1685 nullptr, // getattrofunc tp_getattro;
1686 nullptr, // setattrofunc tp_setattro;
1687
1688 /* Functions to access object as input/output buffer */
1689 nullptr, // PyBufferProcs *tp_as_buffer;
1690
1691 /* Flags to define presence of optional/expanded features */
1692 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, // long tp_flags;
1693
1694 pdffile__doc__, // char *tp_doc; /* Documentation string */
1695
1696 /* Assigned meaning in release 2.0 */
1697 /* call function for all accessible objects */
1698 nullptr, // traverseproc tp_traverse;
1699
1700 /* delete references to contained objects */
1701 nullptr, // inquiry tp_clear;
1702
1703 /* Assigned meaning in release 2.1 */
1704 /* rich comparisons */
1705 nullptr, // richcmpfunc tp_richcompare;
1706
1707 /* weak reference enabler */
1708 0, // long tp_weaklistoffset;
1709
1710 /* Added in release 2.2 */
1711 /* Iterators */
1712 nullptr, // getiterfunc tp_iter;
1713 nullptr, // iternextfunc tp_iternext;
1714
1715 /* Attribute descriptor and subclassing stuff */
1716 PDFfile_methods, // struct PyMethodDef *tp_methods;
1717 PDFfile_members, // struct PyMemberDef *tp_members;
1718 PDFfile_getseters, // struct PyGetSetDef *tp_getset;
1719 nullptr, // struct _typeobject *tp_base;
1720 nullptr, // PyObject *tp_dict;
1721 nullptr, // descrgetfunc tp_descr_get;
1722 nullptr, // descrsetfunc tp_descr_set;
1723 0, // long tp_dictoffset;
1724 (initproc)PDFfile_init, // initproc tp_init;
1725 nullptr, // allocfunc tp_alloc;
1726 PDFfile_new, // newfunc tp_new;
1727 nullptr, // freefunc tp_free; /* Low-level free-memory routine */
1728 nullptr, // inquiry tp_is_gc; /* For PyObject_IS_GC */
1729 nullptr, // PyObject *tp_bases;
1730 nullptr, // PyObject *tp_mro; /* method resolution order */
1731 nullptr, // PyObject *tp_cache;
1732 nullptr, // PyObject *tp_subclasses;
1733 nullptr, // PyObject *tp_weaklist;
1734 nullptr, // destructor tp_del;
1735 0, // unsigned int tp_version_tag;
1736 0, // destructor tp_finalize;
1737 #if PY_VERSION_HEX >= 0x03080000
1738 nullptr, // tp_vectorcall
1739 #endif
1740 #if PY_VERSION_HEX >= 0x03080000 && PY_VERSION_HEX < 0x03090000
1741 nullptr, //deprecated tp_print
1742 #endif
1743
1744 #ifdef COUNT_ALLOCS
1745 /* these must be last and never explicitly initialized */
1746 // int tp_allocs;
1747 // int tp_frees;
1748 // int tp_maxalloc;
1749 // struct _typeobject *tp_prev;
1750 // struct _typeobject *tp_next;
1751 #endif
1752 };
1753