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
8 #include <QApplication>
9 #include <QDesktopWidget>
10 #include <QMap>
11 #include <QTemporaryFile>
12
13 #include "outputpreview_pdf.h"
14 #include "cmsettings.h"
15 #include "filewatcher.h"
16 #include "iconmanager.h"
17 #include "pageitemiterator.h"
18 #include "pdflib.h"
19 #include "pdflib_core.h"
20 #include "prefsfile.h"
21 #include "prefsmanager.h"
22 #include "prefstable.h"
23 #include "sccolor.h"
24 #include "sccolorengine.h"
25 #include "scpaths.h"
26 #include "scribus.h"
27 #include "scribuscore.h"
28 #include "scribusdoc.h"
29 #include "util.h"
30 #include "util_ghostscript.h"
31
32 #include "ui_outputpreviewbase.h"
33 #include "ui_outputpreview_pdf.h"
34
OutputPreview_PDF(QWidget * parent,ScribusDoc * doc)35 OutputPreview_PDF::OutputPreview_PDF(QWidget* parent, ScribusDoc* doc) :
36 OutputPreviewBase(parent, doc),
37 m_pdfOptions(doc->pdfOptions()),
38 m_prefsManager(PrefsManager::instance())
39 {
40 int inkTableWidth = 0;
41
42 setModal(true);
43 setWindowIcon(IconManager::instance().loadIcon("AppIcon.png"));
44
45 QString caption = tr("PDF Output Preview");
46 setWindowTitle(caption);
47
48 m_havePngAlpha = ScCore->havePNGAlpha();
49 m_haveTiffSep = ScCore->haveTIFFSep();
50 getNumericGSVersion(m_gsVersion);
51
52 m_optionsUi = new Ui::OutputPreview_PDF();
53 m_optionsUi->setupUi(m_uiBase->optionWidget);
54
55 if (m_haveTiffSep)
56 {
57 ColorList usedSpots;
58 doc->getUsedColors(usedSpots, true);
59 QStringList spots = usedSpots.keys();
60
61 m_inkMax = (spots.count() + 4) * 255;
62 m_optionsUi->coverThresholdValue->setMaximum((spots.count() + 4) * 100.0);
63
64 m_optionsUi->inkTable->setColumnCount(2);
65 m_optionsUi->inkTable->setRowCount(4 + spots.count());
66 m_optionsUi->inkTable->setHorizontalHeaderItem(0, new QTableWidgetItem(IconManager::instance().loadIcon("16/show-object.png"), ""));
67 m_optionsUi->inkTable->setHorizontalHeaderItem(1, new QTableWidgetItem( tr("Separation Name")));
68
69 QHeaderView *header = m_optionsUi->inkTable->horizontalHeader();
70 header->setStretchLastSection(true);
71 header->setSectionsMovable(false);
72 header->setSectionResizeMode(QHeaderView::Fixed);
73
74 m_optionsUi->inkTable->setColumnWidth(0, 24);
75 m_optionsUi->inkTable->verticalHeader()->hide();
76 m_optionsUi->inkTable->setFocusPolicy(Qt::NoFocus);
77 m_optionsUi->inkTable->setSizeAdjustPolicy(QTableWidget::AdjustToContentsOnFirstShow);
78
79 m_optionsUi->inkTable->setItem(0, 1, new QTableWidgetItem( tr("Cyan")));
80 QCheckBox *cp = new QCheckBox(this);
81 cp->setFocusPolicy(Qt::NoFocus);
82 cp->setChecked(true);
83 connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
84 m_optionsUi->inkTable->setCellWidget(0, 0, cp);
85 m_inkVisibilities.insert("Cyan", cp);
86
87 m_optionsUi->inkTable->setItem(1, 1, new QTableWidgetItem( tr("Magenta")));
88 cp = new QCheckBox(this);
89 cp->setFocusPolicy(Qt::NoFocus);
90 cp->setChecked(true);
91 connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
92 m_optionsUi->inkTable->setCellWidget(1, 0, cp);
93 m_inkVisibilities.insert("Magenta", cp);
94
95 m_optionsUi->inkTable->setItem(2, 1, new QTableWidgetItem( tr("Yellow")));
96 cp = new QCheckBox(this);
97 cp->setFocusPolicy(Qt::NoFocus);
98 cp->setChecked(true);
99 connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
100 m_optionsUi->inkTable->setCellWidget(2, 0, cp);
101 m_inkVisibilities.insert("Yellow", cp);
102
103 m_optionsUi->inkTable->setItem(3, 1, new QTableWidgetItem( tr("Black")));
104 cp = new QCheckBox(this);
105 cp->setFocusPolicy(Qt::NoFocus);
106 cp->setChecked(true);
107 connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
108 m_optionsUi->inkTable->setCellWidget(3, 0, cp);
109 m_inkVisibilities.insert("Black", cp);
110
111 for (int sp = 0; sp < spots.count(); ++sp)
112 {
113 const QString& spotName = spots.at(sp);
114 m_optionsUi->inkTable->setItem(sp + 4, 1, new QTableWidgetItem(spotName));
115 cp = new QCheckBox(this);
116 cp->setFocusPolicy(Qt::NoFocus);
117 cp->setChecked(true);
118 connect(cp, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
119 m_optionsUi->inkTable->setCellWidget(sp + 4, 0, cp);
120 m_inkVisibilities.insert(spotName, cp);
121 }
122
123 inkTableWidth = m_optionsUi->inkTable->columnWidth(1);
124
125 bool inkCoverageEnabled = (m_optionsUi->enableCMYK->isChecked()) && (m_optionsUi->displayInkCoverage->isChecked());
126 m_optionsUi->coverThresholdLabel->setEnabled(inkCoverageEnabled);
127 m_optionsUi->coverThresholdValue->setEnabled(inkCoverageEnabled);
128 m_optionsUi->coverThresholdValue->setSuffix( tr(" %"));
129
130 connect(header, SIGNAL(sectionClicked(int)), this, SLOT(toggleAllFromHeader()));
131 connect(m_optionsUi->enableCMYK, SIGNAL(clicked()), this, SLOT(toggleCMYK()));
132 connect(m_optionsUi->displayInkCoverage, SIGNAL(clicked()), this, SLOT(toggleCMYK_Colour()));
133 connect(m_optionsUi->inkTable, SIGNAL(cellDoubleClicked(int, int)), this, SLOT(onInkTableCellDoubleClicked(int)));
134 }
135 else
136 {
137 m_optionsUi->enableCMYK->setChecked(false);
138 m_optionsUi->enableCMYK->setVisible(false);
139 m_optionsUi->inkTable->setVisible(false);
140 m_optionsUi->displayInkCoverage->setChecked(false);
141 m_optionsUi->displayInkCoverage->setVisible(false);
142 m_optionsUi->coverThresholdLabel->setVisible(false);
143 m_optionsUi->coverThresholdValue->setVisible(false);
144 }
145
146 bool cmykEnabled = m_optionsUi->enableCMYK->isChecked();
147 m_optionsUi->inkTable->setEnabled(cmykEnabled);
148 m_optionsUi->displayInkCoverage->setEnabled(cmykEnabled);
149 bool isInkCoverageEnabled = m_optionsUi->displayInkCoverage->isChecked();
150 m_optionsUi->coverThresholdLabel->setEnabled(cmykEnabled && isInkCoverageEnabled);
151 m_optionsUi->coverThresholdValue->setEnabled(cmykEnabled && isInkCoverageEnabled);
152
153 if (m_optionsUi->inkTable->isVisible())
154 m_optionsUi->inkTable->setEnabled(m_optionsUi->enableCMYK->isChecked());
155
156 // Restore display settings from preferences
157 m_optionsUi->antiAliasing->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.enableAntiAliasing);
158 m_optionsUi->showTransparency->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.showTransparency);
159 if (m_optionsUi->inkTable->isVisible() && m_optionsUi->inkTable->isEnabled())
160 {
161 m_optionsUi->enableCMYK->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.cmykPreviewMode);
162 m_inkVisibilities["Cyan"]->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.isCyanVisible);
163 m_inkVisibilities["Magenta"]->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.isMagentaVisible);
164 m_inkVisibilities["Magenta"]->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.isYellowVisible);
165 m_inkVisibilities["Yellow"]->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.isBlackVisible);
166 }
167 m_optionsUi->displayInkCoverage->setChecked(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.displayInkCoverage);
168 m_optionsUi->coverThresholdValue->setValue(m_prefsManager.appPrefs.pdfOutputPreviewPrefs.inkCoverageThreshold);
169
170 // Generate a template name for temporary files
171 QTemporaryFile *tempFile = new QTemporaryFile(ScPaths::tempFileDir() + "/scpreview_XXXXXX.pdf");
172 if (tempFile->open())
173 {
174 QString tempFileBase = tempFile->fileName();
175 tempFile->setAutoRemove(false);
176 tempFile->close();
177 m_tempBaseName = QFileInfo(tempFileBase).completeBaseName();
178 }
179 if (m_tempBaseName.isEmpty())
180 m_tempBaseName = "scpreview";
181 delete tempFile;
182
183 setPDFOptionsToUi(m_pdfOptions);
184
185 // Display preview
186 QPixmap previewPix = createPreview(m_doc->currentPageNumber(), qRound(72 * m_scaleFactor));
187 m_previewLabel->setPixmap(previewPix);
188 m_previewLabel->resize(previewPix.size());
189
190 m_uiBase->pageSelector->setGUIForPage(m_doc->currentPage()->pageNr());
191
192 int w = m_previewLabel->width() + inkTableWidth + 50;
193 resize(qMin(QApplication::desktop()->width() - 30, w), 500);
194
195 //signals and slots
196 connect(m_uiBase->pageSelector, SIGNAL(pageChanged(int)), this, SLOT(jumpToPage(int)));
197 connect(m_uiBase->closeButton, SIGNAL(clicked()), this, SLOT(close()));
198 connect(m_uiBase->exportButton, SIGNAL(clicked()), this, SIGNAL(doExport()));
199 connect(m_uiBase->scaleBox, SIGNAL(activated(int)), this, SLOT(onScaleBoxValueChanged(int)));
200
201 connect(m_optionsUi->pdfVersionCombo, SIGNAL(activated(int)), this, SLOT(onPdfVersionChanged(int)));
202 connect(m_optionsUi->outputModeCombo, SIGNAL(activated(int)), this, SLOT(onPdfOutputModeChanged(int)));
203 connect(m_optionsUi->mirrorH, SIGNAL(clicked()), this, SLOT(redisplay()));
204 connect(m_optionsUi->mirrorV, SIGNAL(clicked()), this, SLOT(redisplay()));
205 connect(m_optionsUi->clipToMargins, SIGNAL(clicked()), this, SLOT(redisplay()));
206 connect(m_optionsUi->convertSpots, SIGNAL(clicked()), this, SLOT(redisplay()));
207
208 connect(m_optionsUi->antiAliasing, SIGNAL(clicked()), this, SLOT(redisplay()));
209 connect(m_optionsUi->showTransparency, SIGNAL(clicked()), this, SLOT(redisplay()));
210
211 connect(m_optionsUi->coverThresholdValue, SIGNAL(valueChanged(double)), this, SLOT(toggleCMYK_Colour()));
212 }
213
~OutputPreview_PDF()214 OutputPreview_PDF::~OutputPreview_PDF()
215 {
216 cleanupTemporaryFiles();
217 delete m_optionsUi;
218 }
219
isCMYKPreviewEnabled() const220 bool OutputPreview_PDF::isCMYKPreviewEnabled() const
221 {
222 return m_optionsUi->enableCMYK->isChecked();
223 }
224
isAntialiasingEnabled() const225 bool OutputPreview_PDF::isAntialiasingEnabled() const
226 {
227 return m_optionsUi->antiAliasing->isChecked();
228 }
229
isTransparencyEnabled() const230 bool OutputPreview_PDF::isTransparencyEnabled() const
231 {
232 return m_optionsUi->showTransparency->isChecked();
233 }
234
isInkChannelVisible(const QString & ink)235 bool OutputPreview_PDF::isInkChannelVisible(const QString& ink)
236 {
237 if (m_inkVisibilities.contains(ink))
238 return m_inkVisibilities[ink]->isChecked();
239 return false;
240 }
241
isInkCoverageEnabled() const242 bool OutputPreview_PDF::isInkCoverageEnabled() const
243 {
244 return m_optionsUi->displayInkCoverage->isChecked();
245 }
246
inkCoverageThreshold() const247 double OutputPreview_PDF::inkCoverageThreshold() const
248 {
249 return m_optionsUi->coverThresholdValue->value();
250 }
251
cleanupTemporaryFiles()252 void OutputPreview_PDF::cleanupTemporaryFiles()
253 {
254 QString tempFileDir = ScPaths::tempFileDir();
255 QFile::remove(tempFileDir + "/" + m_tempBaseName + ".pdf");
256 QFile::remove(tempFileDir + "/" + m_tempBaseName + ".png");
257 QDir d(tempFileDir + "/", m_tempBaseName + "*", QDir::Name, QDir::Files | QDir::NoSymLinks);
258 if ((d.exists()) && (d.count() != 0))
259 {
260 for (uint i = 0; i < d.count(); i++)
261 QFile::remove(tempFileDir + "/" + d[i]);
262 }
263 }
264
createPreview(int pageIndex,int res)265 QPixmap OutputPreview_PDF::createPreview(int pageIndex, int res)
266 {
267 int ret = -1;
268 int gsRes = qRound(res * devicePixelRatioF());
269 int w = qRound(m_doc->Pages->at(pageIndex)->width() * gsRes / 72.0);
270 int h = qRound(m_doc->Pages->at(pageIndex)->height() * gsRes / 72.0);
271
272 qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
273
274 QPixmap pixmap;
275 if (pdfOptionsHaveChanged(pageIndex))
276 {
277 bool success = createPreviewFile(pageIndex);
278 if (!success)
279 {
280 imageLoadError(pixmap);
281 return pixmap;
282 }
283 }
284
285 if (optionsHaveChanged(pageIndex))
286 {
287 if (m_optionsUi->enableCMYK->isChecked() && m_haveTiffSep)
288 ret = renderPreviewSep(pageIndex, gsRes);
289 else
290 ret = renderPreview(pageIndex, gsRes);
291 if (ret > 0)
292 {
293 imageLoadError(pixmap);
294 return pixmap;
295 }
296 }
297
298 QImage image;
299 if (m_optionsUi->enableCMYK->isChecked() && m_haveTiffSep)
300 {
301 bool loadError;
302 int cyan, magenta, yellow, black;
303
304 ScImage im;
305 bool mode;
306 int w2 = w;
307 int h2 = h;
308 image = QImage(w2, h2, QImage::Format_ARGB32);
309 image.fill(qRgba(0, 0, 0, 0));
310
311 QStringList separationNames { "Cyan", "Magenta", "Yellow" };
312 CMSettings cms(m_doc, "", Intent_Perceptual);
313 cms.allowColorManagement(false);
314 for (int i = 0; i < separationNames.count(); ++i)
315 {
316 QString separationName = separationNames.at(i);
317 if (!m_inkVisibilities[separationName]->isChecked())
318 continue;
319 if (m_gsVersion < 854)
320 loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif." + separationName + ".tif", 1, cms, ScImage::RGBData, 72, &mode);
321 else if (m_gsVersion <= 905)
322 loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + "." + separationName + ".tif", 1, cms, ScImage::RGBData, 72, &mode);
323 else
324 loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + "(" + separationName + ").tif", 1, cms, ScImage::RGBData, 72, &mode);
325 if (!loadError)
326 {
327 imageLoadError(pixmap);
328 return pixmap;
329 }
330 if (m_optionsUi->displayInkCoverage->isChecked())
331 blendImagesSumUp(image, im);
332 else
333 {
334 int c = (i == 0) ? 255 : 0;
335 int m = (i == 1) ? 255 : 0;
336 int j = (i == 2) ? 255 : 0;
337 blendImages(image, im, ScColor(c, m, j, 0));
338 }
339 }
340
341 for (auto sepit = m_sepsToFileNum.begin(); sepit != m_sepsToFileNum.end(); ++sepit)
342 {
343 const QCheckBox* checkBox = m_inkVisibilities.value(sepit.key(), nullptr);
344 if (!checkBox || !checkBox->isChecked())
345 continue;
346 QString sepFileName;
347 if (m_gsVersion < 854)
348 sepFileName = QString(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif.s%1.tif").arg(sepit.value());
349 else if (m_gsVersion <= 905)
350 sepFileName = QString(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".s%1.tif").arg(sepit.value());
351 else
352 sepFileName = QString(ScPaths::tempFileDir() + "/" + m_tempBaseName + "(%1).tif").arg(sepit.key());
353 if (!im.loadPicture(sepFileName, 1, cms, ScImage::RGBData, 72, &mode))
354 {
355 imageLoadError(pixmap);
356 return pixmap;
357 }
358 if (m_optionsUi->displayInkCoverage->isChecked())
359 blendImagesSumUp(image, im);
360 else
361 blendImages(image, im, m_doc->PageColors[sepit.key()]);
362 }
363
364 if (m_inkVisibilities["Black"]->isChecked())
365 {
366 CMSettings cms(m_doc, "", Intent_Perceptual);
367 cms.allowColorManagement(false);
368 if (m_gsVersion < 854)
369 loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif.Black.tif", 1, cms, ScImage::RGBData, 72, &mode);
370 else if (m_gsVersion <= 905)
371 loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".Black.tif", 1, cms, ScImage::RGBData, 72, &mode);
372 else
373 loadError = im.loadPicture(ScPaths::tempFileDir() + "/" + m_tempBaseName + "(Black).tif", 1, cms, ScImage::RGBData, 72, &mode);
374 if (!loadError)
375 {
376 imageLoadError(pixmap);
377 return pixmap;
378 }
379 if (m_optionsUi->displayInkCoverage->isChecked())
380 blendImagesSumUp(image, im);
381 else
382 blendImages(image, im, ScColor(0, 0, 0, 255));
383 }
384
385 if (m_optionsUi->displayInkCoverage->isChecked())
386 {
387 uint limitVal = (m_optionsUi->coverThresholdValue->value() * 255) / 100;
388 for (int yi = 0; yi < h2; ++yi)
389 {
390 QRgb *q = (QRgb*) image.scanLine(yi);
391 for (int xi = 0; xi < w2; ++xi)
392 {
393 uint greyVal = *q;
394 if (greyVal != 0)
395 {
396 if (limitVal == 0)
397 {
398 QColor tmpC;
399 tmpC.setHsv((greyVal * 359) / m_inkMax, 255, 255);
400 *q = tmpC.rgba();
401 }
402 else
403 {
404 int col = qMin(255 - static_cast<int>(((greyVal * 128) / m_inkMax) * 2), 255);
405 if ((*q > 0) && (*q < limitVal))
406 *q = qRgba(col, col, col, 255);
407 else
408 *q = qRgba(col, 0, 0, 255);
409 }
410 }
411 else
412 {
413 if (!m_optionsUi->showTransparency->isChecked())
414 *q = qRgba(255, 255, 255, 255);
415 }
416 q++;
417 }
418 }
419 }
420 else if (m_doc->HasCMS || ScCore->haveCMS())
421 {
422 QRgb alphaFF = qRgba(0,0,0,255);
423 QRgb alphaOO = qRgba(255,255,255,0);
424 ScColorMgmtEngine engine = m_doc->colorEngine;
425 ScColorProfile cmykProfile = m_doc->HasCMS ? m_doc->DocPrinterProf : ScCore->defaultCMYKProfile;
426 ScColorProfile rgbProfile = m_doc->HasCMS ? m_doc->DocDisplayProf : ScCore->defaultRGBProfile;
427 ScColorTransform transCMYK = engine.createTransform(cmykProfile, Format_YMCK_8, rgbProfile, Format_BGRA_8, Intent_Relative_Colorimetric, 0);
428 for (int yi = 0; yi < h2; ++yi)
429 {
430 uchar* ptr = image.scanLine( yi );
431 transCMYK.apply(ptr, ptr, image.width());
432 QRgb *q = (QRgb *) ptr;
433 for (int xi = 0; xi < image.width(); xi++, q++)
434 {
435 if (m_optionsUi->showTransparency->isChecked())
436 {
437 cyan = qRed(*q);
438 magenta = qGreen(*q);
439 yellow = qBlue(*q);
440 if ((cyan == 255) && (magenta == 255) && (yellow == 255))
441 *q = alphaOO;
442 else
443 *q |= alphaFF;
444 }
445 else
446 *q |= alphaFF;
447 }
448 }
449 }
450 else
451 {
452 for (int yi = 0; yi < h2; ++yi)
453 {
454 QRgb *q = (QRgb*) image.scanLine(yi);
455 for (int xi = 0; xi < w2; ++xi)
456 {
457 cyan = qRed(*q);
458 magenta = qGreen(*q);
459 yellow = qBlue(*q);
460 black = qAlpha(*q);
461 if ((cyan != 0) || (magenta != 0) || (yellow != 0 ) || (black != 0))
462 *q = qRgba(255 - qMin(255, cyan + black), 255 - qMin(255, magenta + black), 255 - qMin(255, yellow + black), 255);
463 else
464 {
465 if (!m_optionsUi->showTransparency->isChecked())
466 *q = qRgba(255, 255, 255, 255);
467 }
468 q++;
469 }
470 }
471 }
472 }
473 else
474 {
475 QString previewFile;
476 if (m_optionsUi->showTransparency->isChecked() && m_havePngAlpha)
477 previewFile = ScPaths::tempFileDir() + "/" + m_tempBaseName + ".png";
478 else
479 previewFile = ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif";
480 if (!image.load(previewFile))
481 {
482 imageLoadError(pixmap);
483 return pixmap;
484 }
485 image = image.convertToFormat(QImage::Format_ARGB32);
486 if (m_optionsUi->showTransparency->isChecked() && m_havePngAlpha)
487 {
488 int wi = image.width();
489 int hi = image.height();
490 for (int yi = 0; yi < hi; ++yi)
491 {
492 QRgb *s = (QRgb*) image.scanLine(yi);
493 for (int xi = 0; xi < wi; ++xi)
494 {
495 if ((*s) == 0xffffffff)
496 (*s) &= 0x00ffffff;
497 s++;
498 }
499 }
500 }
501 }
502
503 image.setDevicePixelRatio(devicePixelRatioF());
504 if (m_optionsUi->showTransparency->isChecked())
505 {
506 pixmap = QPixmap(image.width(), image.height());
507 pixmap.setDevicePixelRatio(devicePixelRatioF());
508 QPainter p;
509 QBrush b(QColor(205,205,205), IconManager::instance().loadPixmap("testfill.png"));
510 p.begin(&pixmap);
511 p.fillRect(0, 0, image.width(), image.height(), b);
512 p.drawImage(0, 0, image);
513 p.end();
514 }
515 else
516 pixmap = QPixmap::fromImage(image);
517 pixmap.setDevicePixelRatio(devicePixelRatioF());
518
519 qApp->restoreOverrideCursor();
520 updateOptionsFromUI();
521 return pixmap;
522 }
523
createPreviewFile(int pageIndex)524 bool OutputPreview_PDF::createPreviewFile(int pageIndex)
525 {
526 if (!m_fontEmbeddingWasSet)
527 {
528 setupFontEmbedding(m_pdfOptions);
529 m_fontEmbeddingWasSet = true;
530 }
531
532 std::vector<int> pageNumbers { pageIndex + 1 };
533
534 setUiOptionsToPDFOptions(m_pdfOptions);
535 m_pdfOptions.Encrypt = false; // Disable PDF encryption for preview
536 m_pdfOptions.Thumbnails = false; //Disable thumbnails too
537
538 QString profileDescription;
539 if ((m_pdfOptions.Version == PDFVersion::PDF_X3) || (m_pdfOptions.Version == PDFVersion::PDF_X1a) || (m_pdfOptions.Version == PDFVersion::PDF_X4))
540 {
541 if (m_pdfOptions.Info.isEmpty())
542 {
543 auto& printerProfiles = ScCore->PrinterProfiles;
544 ScColorProfile outputProfile = m_doc->colorEngine.openProfileFromFile( printerProfiles[m_pdfOptions.PrintProf] );
545 profileDescription = outputProfile.productDescription();
546 m_pdfOptions.Info = profileDescription;
547 }
548 m_pdfOptions.MirrorH = false;
549 m_pdfOptions.MirrorV = false;
550 m_pdfOptions.PresentMode = false;
551 }
552
553 // Disable crop marks
554 m_pdfOptions.cropMarks = false;
555 m_pdfOptions.bleedMarks = false;
556 m_pdfOptions.registrationMarks = false;
557 m_pdfOptions.colorMarks = false;
558 m_pdfOptions.markLength = 20.0;
559 m_pdfOptions.markOffset = 0.0;
560 m_pdfOptions.bleeds.set(0, 0, 0, 0);
561
562 // Generate PDF
563 // QString errorString;
564 QString pdfFileName = ScPaths::tempFileDir() + "/" + m_tempBaseName + ".pdf";
565
566 ScCore->fileWatcher->forceScan();
567 ScCore->fileWatcher->stop();
568 PDFlib pdflib(*m_doc, m_pdfOptions);
569 bool success = pdflib.doExport(pdfFileName, pageNumbers, QMap<int, QImage>());
570 success &= !pdflib.exportAborted();
571 ScCore->fileWatcher->start();
572
573 return success;
574 }
575
renderPreview(int pageIndex,int res)576 int OutputPreview_PDF::renderPreview(int pageIndex, int res)
577 {
578 int ret = -1;
579 QString cmd1;
580
581 QStringList args;
582 QString tmp, tmp2, tmp3;
583 int w = qRound(m_doc->Pages->at(pageIndex)->width() * res / 72.0);
584 int h = qRound(m_doc->Pages->at(pageIndex)->height() * res / 72.0);
585
586 args.append( "-q" );
587 args.append( "-dNOPAUSE" );
588 args.append( "-dPARANOIDSAFER" );
589 args.append( QString("-r%1").arg(tmp.setNum(res)) );
590 args.append( QString("-g%1x%2").arg(tmp2.setNum(w), tmp3.setNum(h)) );
591 if (m_optionsUi->enableCMYK->isChecked())
592 {
593 if (!m_haveTiffSep)
594 return 1;
595 args.append("-sDEVICE=tiffsep");
596 }
597 else
598 {
599 if (m_optionsUi->showTransparency->isChecked() && m_havePngAlpha)
600 args.append("-sDEVICE=pngalpha");
601 else
602 args.append("-sDEVICE=tiff24nc");
603 }
604 if (m_optionsUi->antiAliasing->isChecked())
605 {
606 args.append("-dTextAlphaBits=4");
607 args.append("-dGraphicsAlphaBits=4");
608 }
609 if ((m_doc->HasCMS) && (m_gsVersion >= 900))
610 {
611 args.append("-sDefaultCMYKProfile=" + QDir::toNativeSeparators(m_doc->DocPrinterProf.profilePath()));
612 if (m_optionsUi->enableCMYK->isChecked())
613 args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(m_doc->DocPrinterProf.profilePath()));
614 else
615 args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(m_doc->DocDisplayProf.profilePath()));
616 }
617 else if (ScCore->haveCMS() && (m_gsVersion >= 900))
618 {
619 args.append("-sDefaultCMYKProfile=" + QDir::toNativeSeparators(ScCore->defaultCMYKProfile.profilePath()));
620 if (m_optionsUi->enableCMYK->isChecked())
621 args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(ScCore->defaultCMYKProfile.profilePath()));
622 else
623 args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(ScCore->defaultRGBProfile.profilePath()));
624 }
625
626 // Add any extra font paths being used by Scribus to gs's font search path
627 PrefsContext *pc = m_prefsManager.prefsFile->getContext("Fonts");
628 PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
629 const char sep = ScPaths::envPathSeparator;
630 if (extraFonts->getRowCount() >= 1)
631 cmd1 = QString("-sFONTPATH=%1").arg(QDir::toNativeSeparators(extraFonts->get(0,0)));
632 for (int i = 1; i < extraFonts->getRowCount(); ++i)
633 cmd1 += QString("%1%2").arg(sep).arg(QDir::toNativeSeparators(extraFonts->get(i,0)));
634 if (!cmd1.isEmpty())
635 args.append( cmd1 );
636
637 // then add any final args and call gs
638 QString tempFileDir = ScPaths::tempFileDir() ;
639 if (m_optionsUi->enableCMYK->isChecked())
640 args.append( QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(tempFileDir + "/" + m_tempBaseName + ".tif")) );
641 else if (m_optionsUi->showTransparency->isChecked() && m_havePngAlpha)
642 args.append( QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(tempFileDir + "/" + m_tempBaseName + ".png")) );
643 else
644 args.append(QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(tempFileDir + "/" + m_tempBaseName + ".tif")));
645 args.append( QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".pdf") );
646 args.append( "-c" );
647 args.append( "showpage" );
648 args.append( "-c" );
649 args.append( "quit" );
650 ret = System(m_prefsManager.ghostscriptExecutable(), args);
651 return ret;
652 }
653
renderPreviewSep(int pageIndex,int res)654 int OutputPreview_PDF::renderPreviewSep(int pageIndex, int res)
655 {
656 int ret = -1;
657 QString cmd;
658 QStringList args, args1, args2, args3;
659
660 QString tmp, tmp2, tmp3;
661 int w = qRound(m_doc->Pages->at(pageIndex)->width() * res / 72.0);
662 int h = qRound(m_doc->Pages->at(pageIndex)->height() * res / 72.0);
663
664 args1.append( "-q" );
665 args1.append( "-dNOPAUSE" );
666 args1.append( "-dPARANOIDSAFER" );
667 args1.append( QString("-r%1").arg(tmp.setNum(res)) );
668 args1.append( QString("-g%1x%2").arg(tmp2.setNum(w), tmp3.setNum(h)) );
669 if (m_optionsUi->antiAliasing->isChecked())
670 {
671 args1.append("-dTextAlphaBits=4");
672 args1.append("-dGraphicsAlphaBits=4");
673 }
674 if ((m_doc->HasCMS) && (m_gsVersion >= 900))
675 {
676 args1.append("-sDefaultCMYKProfile=" + QDir::toNativeSeparators(m_doc->DocPrinterProf.profilePath()));
677 args1.append("-sOutputICCProfile=" + QDir::toNativeSeparators(m_doc->DocPrinterProf.profilePath()));
678 }
679 else if (ScCore->haveCMS() && (m_gsVersion >= 900))
680 {
681 args.append("-sDefaultCMYKProfile=" + QDir::toNativeSeparators(ScCore->defaultCMYKProfile.profilePath()));
682 args.append("-sOutputICCProfile=" + QDir::toNativeSeparators(ScCore->defaultCMYKProfile.profilePath()));
683 }
684
685 // Add any extra font paths being used by Scribus to gs's font search path
686 PrefsContext *pc = m_prefsManager.prefsFile->getContext("Fonts");
687 PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
688 const char sep = ScPaths::envPathSeparator;
689 if (extraFonts->getRowCount() >= 1)
690 cmd = QString("-sFONTPATH=%1").arg(QDir::toNativeSeparators(extraFonts->get(0,0)));
691 for (int i = 1; i < extraFonts->getRowCount(); ++i)
692 cmd += QString("%1%2").arg(sep).arg(QDir::toNativeSeparators(extraFonts->get(i,0)));
693 if (!cmd.isEmpty())
694 args1.append(cmd);
695 args1.append( QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif")) );
696
697 args2.append( QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".pdf") );
698 args2.append("-c");
699 args2.append("quit");
700
701 ColorList usedSpots;
702 m_doc->getUsedColors(usedSpots, true);
703 QStringList spots = usedSpots.keys();
704 args3.append( "-sDEVICE=tiffsep" );
705
706 // args3.append( "-c" );
707 cmd = "<< /SeparationColorNames ";
708 QString allSeps ="[ /Cyan /Magenta /Yellow /Black ";
709 for (int sp = 0; sp < spots.count(); ++sp)
710 {
711 allSeps += "(" + spots[sp] + ") ";
712 }
713 allSeps += "]";
714 cmd += allSeps + " /SeparationOrder [ /Cyan /Magenta /Yellow /Black] >> setpagedevice";
715 QFile fx(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".sep.ps"));
716 if (fx.open(QIODevice::WriteOnly))
717 {
718 QTextStream tsx(&fx);
719 tsx << cmd;
720 fx.close();
721 }
722
723 QString gsExe(getShortPathName(m_prefsManager.ghostscriptExecutable()));
724 ret = System(gsExe, args1 + args3 + args2, ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif.txt" );
725
726 QFile sepInfo(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".tif.txt"));
727 m_sepsToFileNum.clear();
728 if (sepInfo.open(QIODevice::ReadOnly))
729 {
730 QString Sname;
731 QTextStream tsC(&sepInfo);
732 int counter = 0;
733 while (!tsC.atEnd())
734 {
735 Sname = tsC.readLine();
736 QString tt = Sname.remove("%%SeparationName:").trimmed();
737 if (!tt.isEmpty())
738 {
739 m_sepsToFileNum.insert(tt, counter);
740 counter++;
741 }
742 }
743 }
744 sepInfo.close();
745 QString currSeps = "";
746 uint spc = 0;
747 for (int sp = 0; sp < spots.count(); ++sp)
748 {
749 currSeps += "(" + spots[sp] + ") ";
750 spc++;
751 if (sp > 6)
752 {
753 args3.clear();
754 args3.append("-sDEVICE=tiffsep");
755 QFile fx(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".sep.ps"));
756 if (fx.open(QIODevice::WriteOnly))
757 {
758 QTextStream tsx(&fx);
759 tsx << QString("<< /SeparationColorNames " + allSeps + " /SeparationOrder [ " + currSeps + " ] >> setpagedevice");
760 fx.close();
761 }
762 args3.append("-f");
763 args3.append(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".sep.ps"));
764 ret = System(gsExe, args1 + args3 + args2);
765 currSeps = "";
766 spc = 0;
767 }
768 }
769 if (spc != 0)
770 {
771 args3.clear();
772 args3.append("-sDEVICE=tiffsep");
773 QFile fx(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".sep.ps"));
774 if (fx.open(QIODevice::WriteOnly))
775 {
776 QTextStream tsx(&fx);
777 tsx << QString("<< /SeparationColorNames " + allSeps + " /SeparationOrder [ " + currSeps + " ] >> setpagedevice");
778 fx.close();
779 }
780 args3.append("-f");
781 args3.append(QDir::toNativeSeparators(ScPaths::tempFileDir() + "/" + m_tempBaseName + ".sep.ps"));
782 ret = System(gsExe, args1 + args3 + args2);
783 }
784 return ret;
785 }
786
setupFontEmbedding(PDFOptions & options)787 void OutputPreview_PDF::setupFontEmbedding(PDFOptions& options)
788 {
789 QMap<QString, int> usedFonts = m_doc->reorganiseFonts();
790 QStringList docFonts = usedFonts.keys();
791
792 // Simple case: no font embedding
793 if (m_pdfOptions.FontEmbedding == PDFOptions::DontEmbed)
794 {
795 m_pdfOptions.OutlineList.clear();
796 m_pdfOptions.EmbedList.clear();
797 m_pdfOptions.SubsetList.clear();
798 return;
799 }
800
801 // Simple case: all fonts are outlined
802 if (m_pdfOptions.FontEmbedding == PDFOptions::OutlineFonts)
803 {
804 m_pdfOptions.OutlineList = docFonts;
805 m_pdfOptions.EmbedList.clear();
806 m_pdfOptions.SubsetList.clear();
807 return;
808 }
809
810 if (m_pdfOptions.EmbedList.count() != 0)
811 {
812 QList<QString> tmpEm;
813 for (auto itef = m_pdfOptions.EmbedList.begin(); itef != m_pdfOptions.EmbedList.end(); ++itef)
814 {
815 if (usedFonts.contains((*itef)))
816 tmpEm.append((*itef));
817 }
818 m_pdfOptions.EmbedList = tmpEm;
819 }
820 if (m_pdfOptions.SubsetList.count() != 0)
821 {
822 QList<QString> tmpEm;
823 for (auto itef = m_pdfOptions.SubsetList.begin(); itef != m_pdfOptions.SubsetList.end(); ++itef)
824 {
825 if (usedFonts.contains((*itef)))
826 tmpEm.append((*itef));
827 }
828 m_pdfOptions.SubsetList = tmpEm;
829 }
830
831 // Build a list of all fonts used in Annotations
832 QMap<QString, QString> annotationFonts;
833
834 int pageItOptions = PageItemIterator::IterateInGroups | PageItemIterator::IterateInDocItems | PageItemIterator::IterateInMasterItems | PageItemIterator::IterateInFrameItems;
835 for (PageItemIterator it(m_doc, pageItOptions); *it; ++it)
836 {
837 PageItem *currItem = *it;
838 if (((currItem->itemType() == PageItem::TextFrame) || (currItem->itemType() == PageItem::PathText)) && (currItem->isAnnotation()))
839 {
840 int annotType = currItem->annotation().Type();
841 bool mustEmbed = ((annotType >= Annotation::Button) && (annotType <= Annotation::Listbox) && (annotType != Annotation::Checkbox));
842 if (currItem->itemText.length() > 0 || mustEmbed)
843 annotationFonts.insert(currItem->itemText.defaultStyle().charStyle().font().replacementName(), QString());
844 }
845 }
846
847 const auto& allFonts = m_prefsManager.appPrefs.fontPrefs.AvailFonts;
848 PDFVersion pdfVer = m_pdfOptions.Version;
849
850 if ((m_pdfOptions.EmbedList.count() == 0) && (m_pdfOptions.SubsetList.count() == 0) && (m_pdfOptions.firstUse))
851 {
852 for (int i = 0; i < docFonts.count(); ++i)
853 {
854 QString fontName = docFonts.at(i);
855 const ScFace fontFace = allFonts[fontName];
856 if (!fontFace.subset() && (!fontFace.isOTF() || pdfVer.supportsEmbeddedOpenTypeFonts()))
857 m_pdfOptions.EmbedList.append(fontName);
858 else if (annotationFonts.contains(fontName))
859 m_pdfOptions.EmbedList.append(fontName);
860 else
861 m_pdfOptions.SubsetList.append(fontName);
862 }
863 }
864 else
865 {
866 for (int i = 0; i < docFonts.count(); ++i)
867 {
868 QString fontName = docFonts.at(i);
869 const ScFace fontFace = allFonts[fontName];
870 if (m_pdfOptions.EmbedList.contains(fontName) && (!fontFace.isOTF() || m_pdfOptions.supportsEmbeddedOpenTypeFonts()) && !fontFace.subset())
871 continue;
872 if (!m_pdfOptions.SubsetList.contains(fontName))
873 m_pdfOptions.SubsetList.append(fontName);
874 }
875
876 for (auto itAnn = annotationFonts.begin(); itAnn != annotationFonts.end(); ++itAnn)
877 {
878 QString annotFont = itAnn.key();
879 if (!m_pdfOptions.EmbedList.contains(annotFont))
880 m_pdfOptions.EmbedList.append(annotFont);
881 int subsetIndex = m_pdfOptions.SubsetList.indexOf(annotFont);
882 if (subsetIndex >= 0)
883 m_pdfOptions.SubsetList.removeAll(annotFont);
884 }
885 }
886 }
887
optionsHaveChanged(int pageIndex) const888 bool OutputPreview_PDF::optionsHaveChanged(int pageIndex) const
889 {
890 if (m_currentPage != pageIndex)
891 return true;
892 if (m_scaleMode != m_uiBase->scaleBox->currentIndex())
893 return true;
894 if (m_cmykPreviewMode != m_optionsUi->enableCMYK->isChecked())
895 return true;
896 if (m_useAntialiasing != m_optionsUi->antiAliasing->isChecked())
897 return true;
898 if (m_showTransparency != m_optionsUi->showTransparency->isChecked())
899 return true;
900
901 if (m_pdfVersion != m_optionsUi->pdfVersionCombo->version())
902 return true;
903 if (m_pdfOutputMode != m_optionsUi->outputModeCombo->currentIndex())
904 return true;
905 if (m_mirrorH != m_optionsUi->mirrorH->isChecked())
906 return true;
907 if (m_mirrorV != m_optionsUi->mirrorV->isChecked())
908 return true;
909 if (m_clipToMargins != m_optionsUi->clipToMargins->isChecked())
910 return true;
911 if (m_convertSpots != m_optionsUi->convertSpots->isChecked())
912 return true;
913
914 return false;
915 }
916
pdfOptionsHaveChanged(int pageIndex) const917 bool OutputPreview_PDF::pdfOptionsHaveChanged(int pageIndex) const
918 {
919 if (m_currentPage != pageIndex)
920 return true;
921
922 if (m_pdfVersion != m_optionsUi->pdfVersionCombo->version())
923 return true;
924 if (m_pdfOutputMode != m_optionsUi->outputModeCombo->currentIndex())
925 return true;
926 if (m_mirrorH != m_optionsUi->mirrorH->isChecked())
927 return true;
928 if (m_mirrorV != m_optionsUi->mirrorV->isChecked())
929 return true;
930 if (m_clipToMargins != m_optionsUi->clipToMargins->isChecked())
931 return true;
932 if (m_convertSpots != m_optionsUi->convertSpots->isChecked())
933 return true;
934
935 return false;
936 }
937
setPDFOptionsToOptions(PDFOptions & pdfOptions)938 void OutputPreview_PDF::setPDFOptionsToOptions(PDFOptions& pdfOptions)
939 {
940 m_pdfVersion = pdfOptions.Version;
941
942 if (pdfOptions.UseRGB)
943 m_pdfOutputMode = 0;
944 else if (pdfOptions.isGrayscale)
945 m_pdfOutputMode = 2;
946 else
947 m_pdfOutputMode = 1;
948
949 m_mirrorH = pdfOptions.MirrorH;
950 m_mirrorV = pdfOptions.MirrorV;
951 m_clipToMargins = pdfOptions.doClip;
952 m_convertSpots = !pdfOptions.UseSpotColors;
953 }
954
setPDFOptionsToUi(PDFOptions & pdfOptions)955 void OutputPreview_PDF::setPDFOptionsToUi(PDFOptions& pdfOptions)
956 {
957 m_optionsUi->pdfVersionCombo->setPDFXEnabled(m_doc->HasCMS && !ScCore->PDFXProfiles.isEmpty());
958 m_optionsUi->pdfVersionCombo->setVersion(pdfOptions.Version);
959
960 if (pdfOptions.UseRGB)
961 m_optionsUi->outputModeCombo->setCurrentIndex(0);
962 else if (pdfOptions.isGrayscale)
963 m_optionsUi->outputModeCombo->setCurrentIndex(2);
964 else
965 m_optionsUi->outputModeCombo->setCurrentIndex(1);
966
967 m_optionsUi->mirrorH->setChecked(pdfOptions.MirrorH);
968 m_optionsUi->mirrorV->setChecked(pdfOptions.MirrorV);
969 m_optionsUi->clipToMargins->setChecked(pdfOptions.doClip);
970 m_optionsUi->convertSpots->setChecked(!pdfOptions.UseSpotColors);
971
972 bool cmykEnabled = (m_optionsUi->outputModeCombo->currentIndex() > 0);
973 bool cmykUserEnabled = m_optionsUi->enableCMYK->isChecked();
974
975 m_optionsUi->enableCMYK->setEnabled(cmykEnabled);
976 m_optionsUi->enableCMYK->setChecked(cmykEnabled && cmykUserEnabled);
977 m_optionsUi->inkTable->setEnabled(cmykEnabled && cmykUserEnabled);
978 m_optionsUi->displayInkCoverage->setEnabled(cmykEnabled && cmykUserEnabled);
979 bool isInkCoverageEnabled = m_optionsUi->displayInkCoverage->isChecked();
980 m_optionsUi->coverThresholdLabel->setEnabled(cmykEnabled && cmykUserEnabled && isInkCoverageEnabled);
981 m_optionsUi->coverThresholdValue->setEnabled(cmykEnabled && cmykUserEnabled && isInkCoverageEnabled);
982 }
983
setUiOptionsToPDFOptions(PDFOptions & pdfOptions)984 void OutputPreview_PDF::setUiOptionsToPDFOptions(PDFOptions& pdfOptions)
985 {
986 pdfOptions.Version = m_optionsUi->pdfVersionCombo->version();
987 if (!pdfOptions.Version.supportsOCGs())
988 pdfOptions.useLayers = false;
989
990 if (m_optionsUi->outputModeCombo->currentIndex() == 0)
991 {
992 pdfOptions.isGrayscale = false;
993 pdfOptions.UseRGB = true;
994 pdfOptions.UseProfiles = false;
995 pdfOptions.UseProfiles2 = false;
996 }
997 else if (m_optionsUi->outputModeCombo->currentIndex() == 2)
998 {
999 pdfOptions.isGrayscale = true;
1000 pdfOptions.UseRGB = false;
1001 pdfOptions.UseProfiles = false;
1002 pdfOptions.UseProfiles2 = false;
1003 }
1004 else
1005 {
1006 pdfOptions.isGrayscale = false;
1007 pdfOptions.UseRGB = false;
1008 /*if (ScCore->haveCMS())
1009 {
1010 pdfOptions.UseProfiles = EmbedProfs->isChecked();
1011 pdfOptions.UseProfiles2 = EmbedProfs2->isChecked();
1012 pdfOptions.Intent = IntendS->currentIndex();
1013 pdfOptions.Intent2 = IntendI->currentIndex();
1014 pdfOptions.EmbeddedI = NoEmbedded->isChecked();
1015 pdfOptions.SolidProf = SolidPr->currentText();
1016 pdfOptions.ImageProf = ImageP->currentText();
1017 pdfOptions.PrintProf = PrintProfC->currentText();
1018 }*/
1019 }
1020
1021 // Force font embedding for PDF-X/1
1022 if (pdfOptions.Version.isPDFX() && (pdfOptions.FontEmbedding == PDFOptions::DontEmbed))
1023 {
1024 m_fontEmbeddingWasSet = false;
1025 pdfOptions.EmbedList.clear();
1026 pdfOptions.SubsetList.clear();
1027 pdfOptions.FontEmbedding = PDFOptions::EmbedFonts;
1028 setupFontEmbedding(m_pdfOptions);
1029 m_fontEmbeddingWasSet = true;
1030 }
1031
1032 // PDF/X-1, no profile embedding
1033 if (pdfOptions.Version == PDFVersion::PDF_X1a)
1034 {
1035 pdfOptions.UseProfiles = false;
1036 pdfOptions.UseProfiles2 = false;
1037 }
1038 // PDF/X-3 or PDF/X-4, enforcing color profiles on images
1039 if (pdfOptions.Version == PDFVersion::PDF_X3 || pdfOptions.Version == PDFVersion::PDF_X4)
1040 pdfOptions.UseProfiles2 = true;
1041
1042 pdfOptions.MirrorH = m_optionsUi->mirrorH->isChecked();
1043 pdfOptions.MirrorV = m_optionsUi->mirrorV->isChecked();
1044 pdfOptions.doClip = m_optionsUi->clipToMargins->isChecked();
1045 pdfOptions.UseSpotColors = !m_optionsUi->convertSpots->isChecked();
1046 }
1047
updateOptionsFromUI()1048 void OutputPreview_PDF::updateOptionsFromUI()
1049 {
1050 m_pdfVersion = m_optionsUi->pdfVersionCombo->version();
1051 m_pdfOutputMode = m_optionsUi->outputModeCombo->currentIndex();
1052 m_mirrorH = m_optionsUi->mirrorH->isChecked();
1053 m_mirrorV = m_optionsUi->mirrorV->isChecked();
1054 m_clipToMargins = m_optionsUi->clipToMargins->isChecked();
1055 m_convertSpots = m_optionsUi->convertSpots->isChecked();
1056
1057 m_currentPage = m_uiBase->pageSelector->getCurrentPage() - 1;
1058 m_scaleMode = m_uiBase->scaleBox->currentIndex();
1059 m_cmykPreviewMode = m_optionsUi->enableCMYK->isChecked();
1060 m_useAntialiasing = m_optionsUi->antiAliasing->isChecked();
1061 m_showTransparency = m_optionsUi->showTransparency->isChecked();
1062 }
1063
onPdfVersionChanged(int index)1064 void OutputPreview_PDF::onPdfVersionChanged(int index)
1065 {
1066 bool isPDFX = m_optionsUi->pdfVersionCombo->versionIsPDFX();
1067 m_optionsUi->outputModeCombo->setEnabled(!isPDFX);
1068
1069 if (isPDFX)
1070 {
1071 m_optionsUi->outputModeCombo->setCurrentIndex(1);
1072 m_optionsUi->outputModeCombo->setEnabled(false);
1073 onPdfOutputModeChanged(1);
1074 }
1075
1076 redisplay();
1077 }
1078
onPdfOutputModeChanged(int)1079 void OutputPreview_PDF::onPdfOutputModeChanged(int /*index*/)
1080 {
1081 bool cmykEnabled = (m_optionsUi->outputModeCombo->currentIndex() > 0);
1082 bool cmykUserEnabled = m_optionsUi->enableCMYK->isChecked();
1083
1084 m_optionsUi->enableCMYK->setEnabled(cmykEnabled);
1085 m_optionsUi->enableCMYK->setChecked(cmykEnabled && cmykUserEnabled);
1086 m_optionsUi->inkTable->setEnabled(cmykEnabled && cmykUserEnabled);
1087 m_optionsUi->displayInkCoverage->setEnabled(cmykEnabled && cmykUserEnabled);
1088 bool isInkCoverageEnabled = m_optionsUi->displayInkCoverage->isChecked();
1089 m_optionsUi->coverThresholdLabel->setEnabled(cmykEnabled && cmykUserEnabled && isInkCoverageEnabled);
1090 m_optionsUi->coverThresholdValue->setEnabled(cmykEnabled && cmykUserEnabled && isInkCoverageEnabled);
1091
1092 redisplay();
1093 }
1094
onInkTableCellDoubleClicked(int row)1095 void OutputPreview_PDF::onInkTableCellDoubleClicked(int row)
1096 {
1097 if (!m_haveTiffSep)
1098 return;
1099
1100 for (auto sepIt = m_inkVisibilities.begin(); sepIt != m_inkVisibilities.end(); ++sepIt)
1101 sepIt.value()->setChecked(false);
1102 ((QCheckBox*)(m_optionsUi->inkTable->cellWidget(row, 0)))->setChecked(true);
1103
1104 if (m_optionsUi->enableCMYK->isChecked())
1105 m_previewLabel->setPixmap(createPreview(m_currentPage, qRound(72 * m_scaleFactor)));
1106 m_previewLabel->resize(m_previewLabel->pixmap()->size());
1107 }
1108
toggleAllFromHeader()1109 void OutputPreview_PDF::toggleAllFromHeader()
1110 {
1111 if (!m_haveTiffSep)
1112 return;
1113
1114 for (auto sepIt = m_inkVisibilities.begin(); sepIt != m_inkVisibilities.end(); ++sepIt)
1115 sepIt.value()->setChecked(true);
1116
1117 if (m_optionsUi->enableCMYK->isChecked())
1118 m_previewLabel->setPixmap(createPreview(m_currentPage, qRound(72 * m_scaleFactor)));
1119 m_previewLabel->resize(m_previewLabel->pixmap()->size());
1120 }
1121
toggleCMYK()1122 void OutputPreview_PDF::toggleCMYK()
1123 {
1124 if (!m_haveTiffSep)
1125 return;
1126
1127 bool cmykEnabled = m_optionsUi->enableCMYK->isChecked();
1128 m_optionsUi->inkTable->setEnabled(cmykEnabled);
1129 m_optionsUi->displayInkCoverage->setEnabled(cmykEnabled);
1130 bool isInkCoverageEnabled = m_optionsUi->displayInkCoverage->isChecked();
1131 m_optionsUi->coverThresholdLabel->setEnabled(cmykEnabled && isInkCoverageEnabled);
1132 m_optionsUi->coverThresholdValue->setEnabled(cmykEnabled && isInkCoverageEnabled);
1133
1134 redisplay();
1135 }
1136
toggleCMYK_Colour()1137 void OutputPreview_PDF::toggleCMYK_Colour()
1138 {
1139 if (m_haveTiffSep)
1140 {
1141 bool inkCoverageEnabled = (m_optionsUi->enableCMYK->isChecked()) && (m_optionsUi->displayInkCoverage->isChecked());
1142 m_optionsUi->coverThresholdLabel->setEnabled(inkCoverageEnabled);
1143 m_optionsUi->coverThresholdValue->setEnabled(inkCoverageEnabled);
1144 }
1145 if (m_optionsUi->enableCMYK->isChecked())
1146 m_previewLabel->setPixmap(createPreview(m_currentPage, qRound(72 * m_scaleFactor)));
1147 m_previewLabel->resize(m_previewLabel->pixmap()->size());
1148 }
1149
imageLoadError(QPixmap & pixmap)1150 void OutputPreview_PDF::imageLoadError(QPixmap &pixmap)
1151 {
1152 pixmap = QPixmap(1, 1);
1153 qApp->restoreOverrideCursor();
1154 updateOptionsFromUI();
1155 }
1156