Subversion Repositories Scribus

Rev

Rev 19672 | Rev 20086 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

<
Rev Author Line No. Line
4430 cbradney 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
*/
3133 fschmid 7
/***************************************************************************
10601 mrdocs 8
                          pdflib_core.cpp  -  description
3133 fschmid 9
                             -------------------
10
    begin                : Sat Jan 19 2002
11
    copyright            : (C) 2002 by Franz Schmid
12
    email                : Franz.Schmid@altmuehlnet.de
13
 ***************************************************************************/
14
 
15
/***************************************************************************
16
 *                                                                         *
17
 *   This program is free software; you can redistribute it and/or modify  *
18
 *   it under the terms of the GNU General Public License as published by  *
19
 *   the Free Software Foundation; either version 2 of the License, or     *
20
 *   (at your option) any later version.                                   *
21
 *                                                                         *
22
 ***************************************************************************/
23
 
17538 jghali 24
#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
15706 jghali 25
#define _USE_MATH_DEFINES
26
#endif
27
 
10054 craig 28
#include "pdflib_core.h"
3133 fschmid 29
 
30
#include "scconfig.h"
31
 
12080 avox 32
#include <cmath>
33
#include <cstdlib>
4229 craig 34
#include <string>
12080 avox 35
#ifdef HAVE_UNISTD_H
36
#include <unistd.h>
37
#endif
38
 
39
#include "rc4.h"
40
 
41
#include <QByteArray>
10223 cbradney 42
#include <QDateTime>
10004 fschmid 43
#include <QDataStream>
12080 avox 44
#include <QDebug>
10223 cbradney 45
#include <QDir>
12080 avox 46
#include <QFileInfo>
47
#include <QImage>
9803 fschmid 48
#include <QList>
11453 fschmid 49
#include <QPainterPath>
8501 cbradney 50
#include <QPixmap>
12080 avox 51
#include <QRect>
52
#include <QRegExp>
53
#include <QStack>
54
#include <QString>
10614 cbradney 55
#include <QTextCodec>
19672 jghali 56
#include <QScopedPointer>
3133 fschmid 57
 
10212 cbradney 58
#include "bookmwin.h"
10862 cbradney 59
#include "bookmarkpalette.h"
10601 mrdocs 60
#include "cmsettings.h"
4028 cbradney 61
#include "commonstrings.h"
10212 cbradney 62
#include "multiprogressdialog.h"
3670 cbradney 63
#include "page.h"
3133 fschmid 64
#include "pageitem.h"
10601 mrdocs 65
#include "pageitem_textframe.h"
10212 cbradney 66
#include "pdfoptions.h"
67
#include "prefscontext.h"
68
#include "prefsmanager.h"
69
#include "sccolor.h"
70
#include "sccolorengine.h"
71
#include "scfonts.h"
5917 jghali 72
#include "scpaths.h"
10212 cbradney 73
#include "scpattern.h"
3133 fschmid 74
#include "scribus.h"
5243 cbradney 75
#include "scribuscore.h"
3699 cbradney 76
#include "scribusdoc.h"
11599 jghali 77
#include "scstreamfilter_flate.h"
78
#include "scstreamfilter_rc4.h"
10212 cbradney 79
#include "text/nlsconfig.h"
3133 fschmid 80
#include "util.h"
11605 jghali 81
#include "util_file.h"
10212 cbradney 82
#include "util_formats.h"
10203 cbradney 83
#include "util_math.h"
12517 fschmid 84
#include "util_ghostscript.h"
3133 fschmid 85
 
86
using namespace std;
87
 
12096 jghali 88
#if defined(_WIN32)
89
#undef GetObject
90
#endif
3133 fschmid 91
 
6562 fschmid 92
 
10054 craig 93
PDFLibCore::PDFLibCore(ScribusDoc & docu)
4264 craig 94
        : QObject(&docu),
4223 craig 95
        doc(docu),
96
        ActPageP(0),
4264 craig 97
        Options(doc.PDF_Options),
4223 craig 98
        Bvie(0),
13765 jghali 99
        ucs2Codec(0),
4223 craig 100
        ObjCounter(7),
101
        ResNam("RE"),
102
        ResCount(0),
103
        NDnam("LI"),
104
        NDnum(0),
10553 fschmid 105
        KeyGen(""),
106
        OwnerKey(""),
107
        UserKey(""),
108
        FileID(""),
109
        EncryKey(""),
4223 craig 110
        Encrypt(0),
111
        KeyLen(5),
112
        colorsToUse(),
113
        spotNam("Spot"),
114
        spotCount(0),
4225 craig 115
        progressDialog(0),
4223 craig 116
        abortExport(false),
5243 cbradney 117
        usingGUI(ScCore->usingGUI())
3133 fschmid 118
{
10553 fschmid 119
        KeyGen.resize(32);
120
        OwnerKey.resize(32);
121
        UserKey.resize(32);
122
        FileID.resize(16);
123
        EncryKey.resize(5);
3133 fschmid 124
        Catalog.Outlines = 2;
125
        Catalog.PageTree = 3;
126
        Catalog.Dest = 4;
127
        PageTree.Count = 0;
128
        Outlines.First = 0;
129
        Outlines.Last = 0;
130
        Outlines.Count = 0;
131
        Seite.ObjNum = 0;
132
        Seite.Thumb = 0;
133
        int kg_array[] = {0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa,
134
                          0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe,
135
                          0x64, 0x53, 0x69, 0x7a};
136
        for (int a = 0; a < 32; ++a)
137
                KeyGen[a] = kg_array[a];
4028 cbradney 138
        if (usingGUI)
139
        {
10508 cbradney 140
                progressDialog = new MultiProgressDialog( tr("Saving PDF"), CommonStrings::tr_Cancel, doc.scMW());
4224 craig 141
                Q_CHECK_PTR(progressDialog);
142
                QStringList barNames, barTexts;
143
                barNames << "EMP" << "EP" << "ECPI";
5370 cbradney 144
                barTexts << tr("Exporting Master Page:") << tr("Exporting Page:") << tr("Exporting Items on Current Page:");
9803 fschmid 145
                QList<bool> barsNumeric;
5370 cbradney 146
                barsNumeric << true << true << false;
147
                progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
8559 subik 148
                connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
4028 cbradney 149
        }
3133 fschmid 150
}
151
 
10054 craig 152
PDFLibCore::~PDFLibCore()
4224 craig 153
{
154
        delete progressDialog;
155
}
156
 
4229 craig 157
static inline QString FToStr(double c)
158
{
159
        return QString::number(c, 'f', 5);
160
};
161
 
19033 jghali 162
bool PDFLibCore::PDF_IsPDFX()
163
{
164
        if (Options.Version == PDFOptions::PDFVersion_X1a)
165
                return true;
166
        if (Options.Version == PDFOptions::PDFVersion_X3)
167
                return true;
168
        return false;
169
}
170
 
171
bool PDFLibCore::PDF_IsPDFX(PDFOptions::PDFVersion ver)
172
{
173
        if (ver == PDFOptions::PDFVersion_X1a)
174
                return true;
175
        if (ver == PDFOptions::PDFVersion_X3)
176
                return true;
177
        return false;
178
}
179
 
10054 craig 180
bool PDFLibCore::doExport(const QString& fn, const QString& nam, int Components,
4264 craig 181
                                          const std::vector<int> & pageNs, const QMap<int,QPixmap> & thumbs)
3133 fschmid 182
{
183
        QPixmap pm;
11060 jghali 184
        bool ret = false, error = false;
185
        int  pc_exportpages=0;
186
        int  pc_exportmasterpages=0;
4224 craig 187
        if (usingGUI)
188
                progressDialog->show();
5387 avox 189
        QMap<QString, QMap<uint, FPointArray> > usedFonts;
190
        usedFonts.clear();
191
        doc.getUsedFonts(usedFonts);
13792 pierre 192
        ucs2Codec = QTextCodec::codecForName("UTF-16");
13765 jghali 193
        if (!ucs2Codec)
194
        {
195
                // FIXME : Replace by PDF_Error() after 1.3.5 release
13792 pierre 196
                qDebug() << "Qt build miss UTF-16 text codec, pdf export is not possible";
13765 jghali 197
                return false;
198
        }
5781 cbradney 199
        if (PDF_Begin_Doc(fn, PrefsManager::instance()->appPrefs.AvailFonts, usedFonts, doc.scMW()->bookmarkPalette->BView))
3133 fschmid 200
        {
201
                QMap<int, int> pageNsMpa;
202
                for (uint a = 0; a < pageNs.size(); ++a)
203
                {
14652 jghali 204
                        pageNsMpa.insert(doc.MasterNames[doc.DocPages.at(pageNs[a]-1)->MPageNam], 0);
3133 fschmid 205
                }
4028 cbradney 206
                if (usingGUI)
3133 fschmid 207
                {
4028 cbradney 208
                        progressDialog->setOverallTotalSteps(pageNsMpa.count()+pageNs.size());
209
                        progressDialog->setTotalSteps("EMP", pageNsMpa.count());
210
                        progressDialog->setTotalSteps("EP", pageNs.size());
211
                        progressDialog->setOverallProgress(0);
212
                        progressDialog->setProgress("EMP", 0);
213
                        progressDialog->setProgress("EP", 0);
214
                }
10018 fschmid 215
                for (int ap = 0; ap < doc.MasterPages.count() && !abortExport; ++ap)
4028 cbradney 216
                {
4264 craig 217
                        if (doc.MasterItems.count() != 0)
3133 fschmid 218
                        {
219
                                if (pageNsMpa.contains(ap))
220
                                {
5243 cbradney 221
                                        qApp->processEvents();
11060 jghali 222
                                        if (!PDF_TemplatePage(doc.MasterPages.at(ap)))
223
                                                error = abortExport = true;
4028 cbradney 224
                                        ++pc_exportmasterpages;
3133 fschmid 225
                                }
226
                        }
4546 subik 227
                        if (usingGUI)
228
                        {
4028 cbradney 229
                                progressDialog->setProgress("EMP", pc_exportmasterpages);
230
                                progressDialog->setOverallProgress(pc_exportmasterpages+pc_exportpages);
231
                        }
3133 fschmid 232
                }
4028 cbradney 233
                for (uint a = 0; a < pageNs.size() && !abortExport; ++a)
3133 fschmid 234
                {
4264 craig 235
                        if (doc.PDF_Options.Thumbnails)
3133 fschmid 236
                                pm = thumbs[pageNs[a]];
5243 cbradney 237
                        qApp->processEvents();
4028 cbradney 238
                        if (abortExport) break;
11060 jghali 239
 
14652 jghali 240
                        PDF_Begin_Page(doc.DocPages.at(pageNs[a]-1), pm);
5243 cbradney 241
                        qApp->processEvents();
4028 cbradney 242
                        if (abortExport) break;
11060 jghali 243
 
14652 jghali 244
                        if (!PDF_ProcessPage(doc.DocPages.at(pageNs[a]-1), pageNs[a]-1, doc.PDF_Options.doClip))
11060 jghali 245
                                error = abortExport = true;
5243 cbradney 246
                        qApp->processEvents();
4028 cbradney 247
                        if (abortExport) break;
11060 jghali 248
 
15445 craig 249
                        PDF_End_Page(a);
4028 cbradney 250
                        pc_exportpages++;
251
                        if (usingGUI)
252
                        {
253
                                progressDialog->setProgress("EP", pc_exportpages);
254
                                progressDialog->setOverallProgress(pc_exportmasterpages+pc_exportpages);
255
                        }
3133 fschmid 256
                }
4028 cbradney 257
                ret = true;//Even when aborting we return true. Dont want that "couldnt write msg"
258
                if (!abortExport)
259
                {
19033 jghali 260
                        if (PDF_IsPDFX(doc.PDF_Options.Version))
12387 jghali 261
                                ret = PDF_End_Doc(ScCore->PrinterProfiles[doc.PDF_Options.PrintProf], nam, Components);
4028 cbradney 262
                        else
12387 jghali 263
                                ret = PDF_End_Doc();
4028 cbradney 264
                }
3133 fschmid 265
                else
4028 cbradney 266
                        closeAndCleanup();
3133 fschmid 267
        }
4029 cbradney 268
        if (usingGUI)
269
                progressDialog->close();
11060 jghali 270
        return (ret && !error);
3133 fschmid 271
}
272
 
11060 jghali 273
const QString& PDFLibCore::errorMessage(void) const
274
{
275
        return ErrorMessage;
276
}
277
 
11441 jghali 278
bool PDFLibCore::exportAborted(void) const
279
{
280
        return abortExport;
281
}
282
 
10054 craig 283
void PDFLibCore::StartObj(int nr)
3133 fschmid 284
{
12080 avox 285
        for (int i=XRef.size(); i < nr; ++i)
286
                XRef.append(0);
287
        XRef[nr-1] = bytesWritten();
4229 craig 288
        PutDoc(QString::number(nr)+ " 0 obj\n");
3133 fschmid 289
}
290
 
4229 craig 291
// Encode a string for inclusion in a
292
// PDF (literal) .
12080 avox 293
static QString PDFEncode(const QString & in)
3133 fschmid 294
{
4229 craig 295
        QString tmp("");
8559 subik 296
        for (int d = 0; d < in.length(); ++d)
3133 fschmid 297
        {
4229 craig 298
                QChar cc(in.at(d));
4230 craig 299
                if ((cc == '(') || (cc == ')') || (cc == '\\'))
300
                        tmp += '\\';
17440 jghali 301
                else if ((cc == '\r') || (cc == '\n'))
302
                {
303
                        tmp += (cc == '\r') ? "\\r" : "\\n";
304
                        continue;
305
                }
3133 fschmid 306
                tmp += cc;
307
        }
308
        return tmp;
309
}
310
 
12080 avox 311
static QString blendMode(int code)
312
{
313
        switch (code)
314
        {
315
                case 0:
316
                        return("Normal");
317
                        break;
318
                case 1:
319
                        return("Darken");
320
                        break;
321
                case 2:
322
                        return("Lighten");
323
                        break;
324
                case 3:
325
                        return("Multiply");
326
                        break;
327
                case 4:
328
                        return("Screen");
329
                        break;
330
                case 5:
331
                        return("Overlay");
332
                        break;
333
                case 6:
334
                        return("HardLight");
335
                        break;
336
                case 7:
337
                        return("SoftLight");
338
                        break;
339
                case 8:
340
                        return("Difference");
341
                        break;
342
                case 9:
343
                        return("Exclusion");
344
                        break;
345
                case 10:
346
                        return("ColorDodge");
347
                        break;
348
                case 11:
349
                        return("ColorBurn");
350
                        break;
351
                case 12:
352
                        return("Hue");
353
                        break;
354
                case 13:
355
                        return("Saturation");
356
                        break;
357
                case 14:
358
                        return("Color");
359
                        break;
360
                case 15:
361
                        return("Luminosity");
362
                        break;
363
                default:
364
                        return "";
365
        }
366
}      
367
 
10054 craig 368
QByteArray PDFLibCore::EncodeUTF16(const QString &in)
7328 fschmid 369
{
14899 fschmid 370
//      QString tmp("");
371
//      for (int d = 0; d < in.length(); ++d)
372
//      {
373
//              QChar cc(in.at(d));
374
//              if ((cc == '(') || (cc == ')') || (cc == '\\'))
375
//                      tmp += '\\';
376
//              tmp += cc;
377
//      }
378
        QString tmp = in;
13765 jghali 379
        QByteArray cres = ucs2Codec->fromUnicode( tmp );
11455 avox 380
#ifndef WORDS_BIGENDIAN
17351 jghali 381
        // on little endian systems we need to swap bytes:
7334 fschmid 382
        uchar sw;
8559 subik 383
        for(int d = 0; d < cres.size()-1; d += 2)
7334 fschmid 384
        {
385
                sw = cres[d];
386
                cres[d] = cres[d+1];
387
                cres[d+1] = sw;
388
        }
11455 avox 389
#endif
7334 fschmid 390
        return cres;
7328 fschmid 391
}
392
 
10054 craig 393
QString PDFLibCore::EncStream(const QString & in, int ObjNum)
3133 fschmid 394
{
4229 craig 395
        if (in.length() < 1)
396
                return QString("");
4264 craig 397
        else if (!Options.Encrypt)
4229 craig 398
                return in;
399
        rc4_context_t rc4;
400
        QString tmp(in);
10553 fschmid 401
        QByteArray us(tmp.length(), ' ');
402
        QByteArray ou(tmp.length(), ' ');
8559 subik 403
        for (int a = 0; a < tmp.length(); ++a)
8576 jghali 404
                us[a] = QChar(tmp.at(a)).cell();
11599 jghali 405
        QByteArray step1 = ComputeRC4Key(ObjNum);
8562 jghali 406
        rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), qMin(KeyLen+5, 16));
4229 craig 407
        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(us.data()), reinterpret_cast<uchar*>(ou.data()), tmp.length());
408
        QString uk = "";
8559 subik 409
        for (int cl = 0; cl < tmp.length(); ++cl)
4229 craig 410
                uk += QChar(ou[cl]);
411
        return uk;
3133 fschmid 412
}
413
 
10054 craig 414
QString PDFLibCore::EncString(const QString & in, int ObjNum)
3133 fschmid 415
{
17440 jghali 416
        QString tmp;
417
        if (in.length() < 1)
418
                return "<>";
4264 craig 419
        if (!Options.Encrypt)
17440 jghali 420
        {
421
                tmp = "(" + PDFEncode(in) + ")";
422
                return tmp;
423
        }
4229 craig 424
        rc4_context_t rc4;
17440 jghali 425
        QByteArray us(in.length(), ' ');
426
        QByteArray ou(in.length(), ' ');
427
        for (int a = 0; a < in.length(); ++a)
428
                us[a] = static_cast<uchar>(QChar(in.at(a)).cell());
11599 jghali 429
        QByteArray step1 = ComputeRC4Key(ObjNum);
8562 jghali 430
        rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), qMin(KeyLen+5, 16));
17440 jghali 431
        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(us.data()), reinterpret_cast<uchar*>(ou.data()), in.length());
4229 craig 432
        QString uk = "";
17440 jghali 433
        for (int cl = 0; cl < in.length(); ++cl)
4229 craig 434
                uk += QChar(ou[cl]);
435
        tmp = "<"+String2Hex(&uk, false)+">";
3133 fschmid 436
        return tmp;
437
}
438
 
10054 craig 439
QString PDFLibCore::EncStringUTF16(const QString & in, int ObjNum)
7328 fschmid 440
{
17440 jghali 441
        if (in.length() < 1)
7355 fschmid 442
                return "<>";
7328 fschmid 443
        if (!Options.Encrypt)
444
        {
17440 jghali 445
                QByteArray us = EncodeUTF16(in);
7328 fschmid 446
                QString uk = "";
8559 subik 447
                for (int cl = 0; cl < us.size(); ++cl)
7328 fschmid 448
                        uk += QChar(us[cl]);
449
                return "<"+String2Hex(&uk, false)+">";
450
        }
451
        rc4_context_t rc4;
17440 jghali 452
        QByteArray us = EncodeUTF16(in);
10553 fschmid 453
        QByteArray ou(us.size(), ' ');
11599 jghali 454
        QByteArray step1 = ComputeRC4Key(ObjNum);
8562 jghali 455
        rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), qMin(KeyLen+5, 16));
7328 fschmid 456
        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(us.data()), reinterpret_cast<uchar*>(ou.data()), ou.size());
457
        QString uk = "";
8559 subik 458
        for (int cl = 0; cl < ou.size(); ++cl)
7328 fschmid 459
                uk += QChar(ou[cl]);
17440 jghali 460
        QString tmp = "<"+String2Hex(&uk, false)+">";
7328 fschmid 461
        return tmp;
462
}
463
 
11445 jghali 464
bool PDFLibCore::EncodeArrayToStream(const QByteArray& in, int ObjNum)
465
{
466
        if (in.size() < 1)
467
                return true;
11599 jghali 468
        bool succeed = false;
11445 jghali 469
        if (Options.Encrypt)
470
        {
11599 jghali 471
                QByteArray step1 = ComputeRC4Key(ObjNum);
472
                ScRC4EncodeFilter rc4Encode(&outStream, step1.data(), qMin(KeyLen+5, 16));
473
                if (rc4Encode.openFilter())
11445 jghali 474
                {
11599 jghali 475
                        succeed  = rc4Encode.writeData(in.data(), in.size());
476
                        succeed &= rc4Encode.closeFilter();
11445 jghali 477
                }
11599 jghali 478
        }
479
        else
480
                outStream.writeRawData(in, in.size());
481
        return (outStream.status() == QDataStream::Ok);
482
}
11445 jghali 483
 
12732 fschmid 484
int PDFLibCore::WriteImageToStream(ScImage& image, int ObjNum, bool cmyk, bool gray, bool precal)
11599 jghali 485
{
486
        bool succeed = false;
487
        int  bytesWritten = 0;
488
        if (Options.Encrypt)
489
        {
490
                QByteArray step1 = ComputeRC4Key(ObjNum);
491
                ScRC4EncodeFilter rc4Encode(&outStream, step1.data(), qMin(KeyLen+5, 16));
492
                if (rc4Encode.openFilter())
11445 jghali 493
                {
11599 jghali 494
                        if (gray)
12732 fschmid 495
                                succeed = image.writeGrayDataToFilter(&rc4Encode, precal);
11599 jghali 496
                        else if (cmyk)
497
                                succeed = image.writeCMYKDataToFilter(&rc4Encode);
498
                        else
499
                                succeed = image.writeRGBDataToFilter(&rc4Encode);
500
                        succeed &= rc4Encode.closeFilter();
501
                        bytesWritten = rc4Encode.writtenToStream();
11445 jghali 502
                }
11599 jghali 503
        }
504
        else
505
        {
506
                ScNullEncodeFilter nullEncode(&outStream);
507
                if (nullEncode.openFilter())
11445 jghali 508
                {
11599 jghali 509
                        if (gray)
12732 fschmid 510
                                succeed = image.writeGrayDataToFilter(&nullEncode, precal);
11599 jghali 511
                        else if (cmyk)
512
                                succeed = image.writeCMYKDataToFilter(&nullEncode);
513
                        else
514
                                succeed = image.writeRGBDataToFilter(&nullEncode);
515
                        succeed &= nullEncode.closeFilter();
516
                        bytesWritten = nullEncode.writtenToStream();
11445 jghali 517
                }
518
        }
11599 jghali 519
        return (succeed ? bytesWritten : 0);
520
}
521
 
522
int PDFLibCore::WriteJPEGImageToStream(ScImage& image, const QString& fn, int ObjNum, bool cmyk,
12732 fschmid 523
                                                                                bool gray, bool sameFile, bool precal)
11599 jghali 524
{
525
        bool succeed = true;
526
        int  bytesWritten = 0;
527
        QFileInfo fInfo(fn);
528
        QString   ext = fInfo.suffix().toLower();
529
        QString   jpgFileName, tmpFile;
530
        if (extensionIndicatesJPEG(ext) && sameFile)
531
                jpgFileName = fn;
11445 jghali 532
        else
11599 jghali 533
        {
16576 craig 534
                tmpFile  = QDir::toNativeSeparators(ScPaths::getTempFileDir() + "sc.jpg");
12732 fschmid 535
                if ((gray) && (!precal))
11599 jghali 536
                        image.convertToGray();
537
                if (image.Convert2JPG(tmpFile, Options.Quality, cmyk, gray))
538
                        jpgFileName = tmpFile;
539
        }
540
        if (jpgFileName.isEmpty())
11792 fschmid 541
                return 0;
11599 jghali 542
        if (Options.Encrypt)
543
        {
544
                succeed = false;
545
                QByteArray step1 = ComputeRC4Key(ObjNum);
546
                ScRC4EncodeFilter rc4Encode(&outStream, step1.data(), qMin(KeyLen+5, 16));
547
                if (rc4Encode.openFilter())
548
                {
549
                        succeed  = copyFileToFilter(jpgFileName, rc4Encode);
550
                        succeed &= rc4Encode.closeFilter();
551
                        bytesWritten = rc4Encode.writtenToStream();
552
                }
553
        }
554
        else
555
        {
556
                succeed &= copyFileToStream(jpgFileName, outStream);
557
                QFileInfo jpgInfo(jpgFileName);
558
                bytesWritten = jpgInfo.size();
559
        }
560
        if (!tmpFile.isEmpty() && QFile::exists(tmpFile))
561
                QFile::remove(tmpFile);
562
        return (succeed ? bytesWritten : 0);
11445 jghali 563
}
564
 
12732 fschmid 565
int PDFLibCore::WriteFlateImageToStream(ScImage& image, int ObjNum, bool cmyk, bool gray, bool precal)
11599 jghali 566
{
567
        bool succeed = false;
568
        int  bytesWritten = 0;
569
        if (Options.Encrypt)
570
        {
571
                QByteArray step1 = ComputeRC4Key(ObjNum);
572
                ScRC4EncodeFilter   rc4Encode(&outStream, step1.data(), qMin(KeyLen+5, 16));
573
                ScFlateEncodeFilter flateEncode(&rc4Encode);
574
                if (flateEncode.openFilter())
575
                {
576
                        if (gray)
12732 fschmid 577
                                succeed = image.writeGrayDataToFilter(&flateEncode, precal);
11599 jghali 578
                        else if (cmyk)
579
                                succeed = image.writeCMYKDataToFilter(&flateEncode);
580
                        else
581
                                succeed = image.writeRGBDataToFilter(&flateEncode);
582
                        succeed &= flateEncode.closeFilter();
583
                        bytesWritten = flateEncode.writtenToStream();
584
                }
585
        }
586
        else
587
        {
588
                ScFlateEncodeFilter flateEncode(&outStream);
589
                if (flateEncode.openFilter())
590
                {
591
                        if (gray)
12732 fschmid 592
                                succeed = image.writeGrayDataToFilter(&flateEncode, precal);
11599 jghali 593
                        else if (cmyk)
594
                                succeed = image.writeCMYKDataToFilter(&flateEncode);
595
                        else
596
                                succeed = image.writeRGBDataToFilter(&flateEncode);
597
                        succeed &= flateEncode.closeFilter();
598
                        bytesWritten = flateEncode.writtenToStream();
599
                }
600
        }
11792 fschmid 601
        return (succeed ? bytesWritten : 0);
11599 jghali 602
}
603
 
10054 craig 604
QString PDFLibCore::FitKey(const QString & pass)
3133 fschmid 605
{
4229 craig 606
        QString pw(pass);
3133 fschmid 607
        if (pw.length() < 32)
608
        {
609
                uint l = pw.length();
610
                for (uint a = 0; a < 32 - l; ++a)
611
                        pw += QChar(KeyGen[a]);
612
        }
613
        else
614
                pw = pw.left(32);
615
        return pw;
616
}
617
 
10054 craig 618
void PDFLibCore::CalcOwnerKey(const QString & Owner, const QString & User)
3133 fschmid 619
{
4229 craig 620
        rc4_context_t rc4;
621
        QString pw(FitKey(User));
622
        QString pw2(FitKey(Owner.isEmpty() ? User : Owner));
10553 fschmid 623
        QByteArray step1(16, ' ');
3133 fschmid 624
        step1 = ComputeMD5(pw2);
625
        if (KeyLen > 5)
626
        {
627
                for (int kl = 0; kl < 50; ++kl)
628
                        step1 = ComputeMD5Sum(&step1);
629
        }
10553 fschmid 630
        QByteArray us(32, ' ');
631
        QByteArray enk(16, ' ');
3133 fschmid 632
        if (KeyLen > 5)
633
        {
634
                for (uint a2 = 0; a2 < 32; ++a2)
8576 jghali 635
                        OwnerKey[a2] = QChar(pw.at(a2)).cell();
3133 fschmid 636
                for (int rl = 0; rl < 20; rl++)
637
                {
4229 craig 638
                        for (int j = 0; j < 16; j ++)
639
                                enk[j] = step1[j] ^ rl;
3133 fschmid 640
                        rc4_init(&rc4, reinterpret_cast<uchar*>(enk.data()), 16);
4229 craig 641
                        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(OwnerKey.data()),
3133 fschmid 642
                                         reinterpret_cast<uchar*>(OwnerKey.data()), 32);
643
                }
644
        }
645
        else
646
        {
647
                for (uint a = 0; a < 32; ++a)
8576 jghali 648
                        us[a] = static_cast<uchar>(QChar(pw.at(a)).cell());
3133 fschmid 649
                rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), 5);
4546 subik 650
                rc4_encrypt(&rc4, reinterpret_cast<uchar*>(us.data()),
3133 fschmid 651
                                        reinterpret_cast<uchar*>(OwnerKey.data()), 32);
652
        }
653
}
654
 
10054 craig 655
void PDFLibCore::CalcUserKey(const QString & User, int Permission)
3133 fschmid 656
{
657
        rc4_context_t   rc4;
4229 craig 658
        QString pw(FitKey(User));
10553 fschmid 659
        QByteArray step1(16, ' ');
660
        QByteArray perm(4, ' ');
3133 fschmid 661
        uint perm_value = static_cast<uint>(Permission);
662
        perm[0] = perm_value;
663
        perm[1] = perm_value >> 8;
664
        perm[2] = perm_value >> 16;
665
        perm[3] = perm_value >> 24;
666
        for (uint a = 0; a < 32; ++a)
667
                pw += QChar(OwnerKey[a]);
668
        for (uint a1 = 0; a1 < 4; ++a1)
669
                pw += QChar(perm[a1]);
670
        for (uint a3 = 0; a3 < 16; ++a3)
671
                pw += QChar(FileID[a3]);
672
        step1 = ComputeMD5(pw);
673
        if (KeyLen > 5)
674
        {
675
                for (int kl = 0; kl < 50; ++kl)
676
                        step1 = ComputeMD5Sum(&step1);
677
                EncryKey.resize(16);
678
        }
679
        for (int a2 = 0; a2 < KeyLen; ++a2)
680
                EncryKey[a2] = step1[a2];
681
        if (KeyLen > 5)
682
        {
4229 craig 683
                QString pr2("");
3133 fschmid 684
                for (int kl3 = 0; kl3 < 32; ++kl3)
685
                        pr2 += QChar(KeyGen[kl3]);
686
                for (uint a4 = 0; a4 < 16; ++a4)
687
                        pr2 += QChar(FileID[a4]);
688
                step1 = ComputeMD5(pr2);
10553 fschmid 689
                QByteArray enk(16, ' ');
3133 fschmid 690
                for (uint a3 = 0; a3 < 16; ++a3)
691
                        UserKey[a3] = step1[a3];
692
                for (int rl = 0; rl < 20; rl++)
693
                {
4229 craig 694
                        for (int j = 0; j < 16; j ++)
695
                                enk[j] = EncryKey[j] ^ rl;
3133 fschmid 696
                        rc4_init(&rc4, reinterpret_cast<uchar*>(enk.data()), 16);
4229 craig 697
                        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(UserKey.data()), reinterpret_cast<uchar*>(UserKey.data()), 16);
3133 fschmid 698
                }
699
        }
700
        else
701
        {
702
                rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), 5);
4229 craig 703
                rc4_encrypt(&rc4, reinterpret_cast<uchar*>(KeyGen.data()), reinterpret_cast<uchar*>(UserKey.data()), 32);
3133 fschmid 704
        }
705
}
706
 
10054 craig 707
QByteArray PDFLibCore::ComputeMD5(const QString& in)
3133 fschmid 708
{
3829 cbradney 709
        uint inlen=in.length();
10553 fschmid 710
        QByteArray TBytes(inlen, ' ');
3829 cbradney 711
        for (uint a = 0; a < inlen; ++a)
8576 jghali 712
                TBytes[a] = static_cast<uchar>(QChar(in.at(a)).cell());
3133 fschmid 713
        return ComputeMD5Sum(&TBytes);
714
}
715
 
11599 jghali 716
QByteArray PDFLibCore::ComputeRC4Key(int ObjNum)
717
{
718
        int dlen = 0;
719
        QByteArray data(10, ' ');
720
        if (KeyLen > 5)
721
                data.resize(21);
722
        for (int cd = 0; cd < KeyLen; ++cd)
723
        {
724
                data[cd] = EncryKey[cd];
725
                dlen++;
726
        }
727
        data[dlen++] = ObjNum;
728
        data[dlen++] = ObjNum >> 8;
729
        data[dlen++] = ObjNum >> 16;
730
        data[dlen++] = 0;
731
        data[dlen++] = 0;
732
        QByteArray rc4Key(16, ' ');
733
        rc4Key = ComputeMD5Sum(&data);
734
        rc4Key.resize(qMin(KeyLen+5, 16));
735
        return rc4Key;
736
}
737
 
10054 craig 738
bool PDFLibCore::PDF_Begin_Doc(const QString& fn, SCFonts &AllFonts, QMap<QString, QMap<uint, FPointArray> > DocFonts, BookMView* vi)
3133 fschmid 739
{
10553 fschmid 740
        Spool.setFileName(fn);
8501 cbradney 741
        if (!Spool.open(QIODevice::WriteOnly))
3133 fschmid 742
                return false;
4229 craig 743
        outStream.setDevice(&Spool);
3133 fschmid 744
        QString tmp;
745
        QString ok = "";
746
        QString uk = "";
747
        QFileInfo fd;
748
        QString fext;
749
        int a;
6407 fschmid 750
        inPattern = 0;
3133 fschmid 751
        Bvie = vi;
752
        BookMinUse = false;
753
        UsedFontsP.clear();
8454 fschmid 754
        UsedFontsF.clear();
12884 jghali 755
        if ((Options.Version == PDFOptions::PDFVersion_15) && (Options.useLayers))
3133 fschmid 756
                ObjCounter = 10;
757
        else
758
                ObjCounter = 9;
4264 craig 759
        switch (Options.Version)
3133 fschmid 760
        {
19033 jghali 761
                case PDFOptions::PDFVersion_X1a:
12884 jghali 762
                case PDFOptions::PDFVersion_X3:
763
                case PDFOptions::PDFVersion_13:
4229 craig 764
                        PutDoc("%PDF-1.3\n");
3133 fschmid 765
                        break;
12884 jghali 766
                case PDFOptions::PDFVersion_14:
3133 fschmid 767
                        PutDoc("%PDF-1.4\n");
768
                        break;
12884 jghali 769
                case PDFOptions::PDFVersion_15:
3133 fschmid 770
                        PutDoc("%PDF-1.5\n");
771
                        break;
772
        }
19033 jghali 773
        if ((Options.Version == PDFOptions::PDFVersion_X1a) || (Options.Version == PDFOptions::PDFVersion_X3))
3133 fschmid 774
                ObjCounter++;
4229 craig 775
        PutDoc("%\xc7\xec\x8f\xa2\n");
3133 fschmid 776
        StartObj(1);
777
        PutDoc("<<\n/Type /Catalog\n/Outlines 3 0 R\n/Pages 4 0 R\n/Dests 5 0 R\n/AcroForm 6 0 R\n/Names 7 0 R\n/Threads 8 0 R\n");
12884 jghali 778
        if ((Options.Version == PDFOptions::PDFVersion_15) && (Options.useLayers))
3133 fschmid 779
                PutDoc("/OCProperties 9 0 R\n");
19033 jghali 780
        if ((Options.Version == PDFOptions::PDFVersion_X1a) || (Options.Version == PDFOptions::PDFVersion_X3))
4229 craig 781
                PutDoc("/OutputIntents [ "+QString::number(ObjCounter-1)+" 0 R ]\n");
4197 fschmid 782
        PutDoc("/PageLayout ");
4264 craig 783
        switch (Options.PageLayout)
3133 fschmid 784
        {
4197 fschmid 785
                case PDFOptions::SinglePage:
786
                        PutDoc("/SinglePage\n");
787
                        break;
788
                case PDFOptions::OneColumn:
789
                        PutDoc("/OneColumn\n");
790
                        break;
791
                case PDFOptions::TwoColumnLeft:
792
                        PutDoc("/TwoColumnLeft\n");
793
                        break;
794
                case PDFOptions::TwoColumnRight:
795
                        PutDoc("/TwoColumnRight\n");
796
                        break;
797
        }
4264 craig 798
        if (Options.displayBookmarks)
4197 fschmid 799
                PutDoc("/PageMode /UseOutlines\n");
4264 craig 800
        else if (Options.displayFullscreen)
4197 fschmid 801
                PutDoc("/PageMode /FullScreen\n");
4264 craig 802
        else if (Options.displayThumbs)
4197 fschmid 803
                PutDoc("/PageMode /UseThumbs\n");
12884 jghali 804
        else if ((Options.Version == PDFOptions::PDFVersion_15) && (Options.displayLayers))
4197 fschmid 805
                        PutDoc("/PageMode /UseOC\n");
4264 craig 806
        if (!Options.openAction.isEmpty())
4197 fschmid 807
        {
4264 craig 808
                PutDoc("/OpenAction << /S /JavaScript /JS (this."+Options.openAction+"\\(\\)) >>\n");
3133 fschmid 809
        }
12429 fschmid 810
 
11593 fschmid 811
        QDate d = QDate::currentDate();
812
        Datum = "D:";
813
        tmp.sprintf("%4d", d.year());
814
        tmp.replace(QRegExp(" "), "0");
815
        Datum += tmp;
816
        tmp.sprintf("%2d", d.month());
817
        tmp.replace(QRegExp(" "), "0");
818
        Datum += tmp;
819
        tmp.sprintf("%2d", d.day());
820
        tmp.replace(QRegExp(" "), "0");
821
        Datum += tmp;
822
        tmp = QTime::currentTime().toString();
823
        tmp.replace(QRegExp(":"), "");
824
        Datum += tmp;
12429 fschmid 825
 
826
/* The following code makes the resulting PDF "Reader enabled" in Acrobat Reader 8
827
   but sadly it doesn't work with newer version, because its based on a bug in AR 8
828
        PutDoc("/Perms\n");
829
        PutDoc("<<\n");
830
        PutDoc("/UR3\n");
831
        PutDoc("<<\n");
832
        PutDoc("/M ("+Datum+")\n");
833
        PutDoc("/Name (Scribus "+QString(VERSION)+")\n");
834
        PutDoc("/Reference [\n");
835
        PutDoc("<<\n");
836
        PutDoc("/TransformParams\n");
837
        PutDoc("<<\n");
838
        PutDoc("/Type /TransformParams\n");
839
        PutDoc("/V /2.2\n");
840
        PutDoc("/Document [/FullSave]\n");
841
        PutDoc("/Annots [/Create/Delete/Modify/Copy/Import/Export]\n");
842
        PutDoc("/Form [/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate]\n");
843
        PutDoc("/Signature [/Modify]\n");
844
        PutDoc(">>\n");
845
        PutDoc("/TransformMethod /UR3\n");
846
        PutDoc("/Type /SigRef\n");
847
        PutDoc(">>\n");
848
        PutDoc("]\n");
849
        PutDoc("/Type /Sig\n");
850
        PutDoc(">>\n");
851
        PutDoc(">>\n");
852
*/
853
 
854
        PutDoc("/ViewerPreferences\n<<\n/PageDirection ");
855
        PutDoc( Options.Binding == 0 ? "/L2R\n" : "/R2L\n");
856
        if (Options.hideToolBar)
857
                PutDoc("/HideToolbar true\n");
858
        if (Options.hideMenuBar)
859
                PutDoc("/HideMenubar true\n");
860
        if (Options.fitWindow)
861
                PutDoc("/FitWindow true\n");
862
        PutDoc(" >>\n>>\nendobj\n");
3829 cbradney 863
        QString IDg(Datum);
11948 jghali 864
        IDg += Options.fileName;
3133 fschmid 865
        IDg += "Scribus "+QString(VERSION);
6878 fschmid 866
        IDg += "Scribus PDF Library "+QString(VERSION);
4264 craig 867
        IDg += doc.documentInfo.getTitle();
868
        IDg += doc.documentInfo.getAuthor();
3133 fschmid 869
        IDg += "/False";
870
        FileID = ComputeMD5(IDg);
4264 craig 871
        if (Options.Encrypt)
3133 fschmid 872
        {
12884 jghali 873
                if ((Options.Version == PDFOptions::PDFVersion_14) || (Options.Version == PDFOptions::PDFVersion_15))
6166 fschmid 874
                        KeyLen = 16;
875
                else
876
                        KeyLen = 5;
4264 craig 877
                CalcOwnerKey(Options.PassOwner, Options.PassUser);
878
                CalcUserKey(Options.PassUser, Options.Permissions);
3133 fschmid 879
                for (uint cl2 = 0; cl2 < 32; ++cl2)
880
                        ok += QChar(OwnerKey[cl2]);
881
                if (KeyLen > 5)
882
                {
883
                        for (uint cl3 = 0; cl3 < 16; ++cl3)
884
                                uk += QChar(UserKey[cl3]);
885
                        for (uint cl3r = 0; cl3r < 16; ++cl3r)
886
                                uk += QChar(KeyGen[cl3r]);
887
                }
888
                else
889
                {
890
                        for (uint cl = 0; cl < 32; ++cl)
891
                                uk += QChar(UserKey[cl]);
892
                }
893
        }
894
        StartObj(2);
17440 jghali 895
        PutDoc("<<\n/Creator " + EncString("Scribus "+QString(VERSION), 2) + "\n");
896
        PutDoc("/Producer " + EncString("Scribus PDF Library "+QString(VERSION), 2) + "\n");
4718 fschmid 897
        QString docTitle = doc.documentInfo.getTitle();
19033 jghali 898
        if ((PDF_IsPDFX()) && (docTitle.isEmpty()))
17440 jghali 899
                PutDoc("/Title " + EncStringUTF16(doc.DocName, 2) + "\n");
4718 fschmid 900
        else
17440 jghali 901
                PutDoc("/Title " + EncStringUTF16(doc.documentInfo.getTitle(), 2) + "\n");
902
        PutDoc("/Author " + EncStringUTF16(doc.documentInfo.getAuthor(), 2) + "\n");
903
        PutDoc("/Subject " + EncStringUTF16(doc.documentInfo.getSubject(), 2) + "\n");
904
        PutDoc("/Keywords " + EncStringUTF16(doc.documentInfo.getKeywords(), 2) + "\n");
905
        PutDoc("/CreationDate " + EncString(Datum, 2) + "\n");
906
        PutDoc("/ModDate " + EncString(Datum, 2) + "\n");
19033 jghali 907
        if (Options.Version == PDFOptions::PDFVersion_X1a)
908
        {
909
                PutDoc("/GTS_PDFXVersion (PDF/X-1:2001)\n");
910
                PutDoc("/GTS_PDFXConformance (PDF/X-1a:2001)\n");
911
        }
12884 jghali 912
        if (Options.Version == PDFOptions::PDFVersion_X3)
3133 fschmid 913
                PutDoc("/GTS_PDFXVersion (PDF/X-3:2002)\n");
914
        PutDoc("/Trapped /False\n>>\nendobj\n");
4229 craig 915
        for (int t = 0; t < 6; ++t)
916
                XRef.append(bytesWritten());
12884 jghali 917
        if ((Options.Version == PDFOptions::PDFVersion_15) && (Options.useLayers))
4229 craig 918
                XRef.append(bytesWritten());
19033 jghali 919
        if ((Options.Version == PDFOptions::PDFVersion_X1a) || (Options.Version == PDFOptions::PDFVersion_X3))
4229 craig 920
                XRef.append(bytesWritten());
4264 craig 921
        if (Options.Encrypt)
3133 fschmid 922
        {
12080 avox 923
                Encrypt = newObject();
924
                StartObj(Encrypt);
3133 fschmid 925
                PutDoc("<<\n/Filter /Standard\n");
926
                PutDoc( KeyLen > 5 ? "/R 3\n/V 2\n/Length 128\n" : "/R 2\n/V 1\n");
927
                PutDoc("/O <"+String2Hex(&ok)+">\n");
928
                PutDoc("/U <"+String2Hex(&uk)+">\n");
4264 craig 929
                PutDoc("/P "+QString::number(Options.Permissions)+"\n>>\nendobj\n");
3133 fschmid 930
        }
5387 avox 931
        QMap<QString, QMap<uint, FPointArray> > ReallyUsed;
3133 fschmid 932
        ReallyUsed.clear();
933
        PageItem* pgit;
4017 fschmid 934
        QMap<int, QString> ind2PDFabr;
4546 subik 935
        const QString tmpf[] = {"/Courier", "/Courier-Bold", "/Courier-Oblique", "/Courier-BoldOblique",
4017 fschmid 936
                                                                                                "/Helvetica", "/Helvetica-Bold", "/Helvetica-Oblique", "/Helvetica-BoldOblique",
4546 subik 937
                                                                                                "/Times-Roman", "/Times-Bold", "/Times-Italic", "/Times-BoldItalic",
4017 fschmid 938
                                                                                                "/ZapfDingbats", "/Symbol"};
939
        size_t ar = sizeof(tmpf) / sizeof(*tmpf);
940
        for (uint ax = 0; ax < ar; ++ax)
941
                ind2PDFabr[ax] = tmpf[ax];
9856 fschmid 942
        for (int c = 0; c < doc.FrameItems.count(); ++c)
3133 fschmid 943
        {
4264 craig 944
                pgit = doc.FrameItems.at(c);
3133 fschmid 945
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
946
                {
4084 cbradney 947
                        if (pgit->isAnnotation())
8092 fschmid 948
                        {
14593 jghali 949
                                int annotType  = pgit->annotation().Type();
950
                                bool mustEmbed = ((annotType >= 2) && (annotType <= 6) && (annotType != 4));
8351 fschmid 951
                                if (pgit->annotation().Type() == 4)
952
                                        StdFonts.insert("/ZapfDingbats", "");
14593 jghali 953
                                if (pgit->itemText.length() > 0 || mustEmbed)
12763 fschmid 954
                                {
12900 fschmid 955
                                        if (Options.Version < PDFOptions::PDFVersion_14)
956
                                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
12763 fschmid 957
                                        ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
958
                                }
8092 fschmid 959
                        }
17750 jghali 960
                        uint start = pgit->isTextFrame() ? (uint) pgit->firstInFrame() : 0;
961
                        uint stop  = pgit->isTextFrame() ? (uint) pgit->lastInFrame() + 1 : (uint) pgit->itemText.length();
962
                        for (uint e = start; e < stop; ++e)
3133 fschmid 963
                        {
7210 avox 964
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
3133 fschmid 965
                        }
966
                }
967
        }
9856 fschmid 968
        for (int c = 0; c < doc.MasterItems.count(); ++c)
3133 fschmid 969
        {
4264 craig 970
                pgit = doc.MasterItems.at(c);
3133 fschmid 971
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
972
                {
4084 cbradney 973
                        if (pgit->isAnnotation())
8092 fschmid 974
                        {
14593 jghali 975
                                int annotType  = pgit->annotation().Type();
976
                                bool mustEmbed = ((annotType >= 2) && (annotType <= 6) && (annotType != 4));
8351 fschmid 977
                                if (pgit->annotation().Type() == 4)
978
                                        StdFonts.insert("/ZapfDingbats", "");
14593 jghali 979
                                if (pgit->itemText.length() > 0 || mustEmbed)
12763 fschmid 980
                                {
12900 fschmid 981
                                        if (Options.Version < PDFOptions::PDFVersion_14)
982
                                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
12763 fschmid 983
                                        ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
984
                                }
8092 fschmid 985
                        }
17750 jghali 986
                        uint start = pgit->isTextFrame() ? (uint) pgit->firstInFrame() : 0;
987
                        uint stop  = pgit->isTextFrame() ? (uint) pgit->lastInFrame() + 1 : (uint) pgit->itemText.length();
988
                        for (uint e = start; e < stop; ++e)
3133 fschmid 989
                        {
7210 avox 990
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
3133 fschmid 991
                        }
992
                }
993
        }
14652 jghali 994
        for (int d = 0; d < doc.DocItems.count(); ++d)
3133 fschmid 995
        {
14652 jghali 996
                pgit = doc.DocItems.at(d);
3133 fschmid 997
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
998
                {
4084 cbradney 999
                        if (pgit->isAnnotation())
8092 fschmid 1000
                        {
14593 jghali 1001
                                int annotType  = pgit->annotation().Type();
1002
                                bool mustEmbed = ((annotType >= 2) && (annotType <= 6) && (annotType != 4));
8351 fschmid 1003
                                if (pgit->annotation().Type() == 4)
1004
                                        StdFonts.insert("/ZapfDingbats", "");
14593 jghali 1005
                                if (pgit->itemText.length() > 0 || mustEmbed)
12763 fschmid 1006
                                {
12900 fschmid 1007
                                        if (Options.Version < PDFOptions::PDFVersion_14)
1008
                                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
12763 fschmid 1009
                                        ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
1010
                                }
8092 fschmid 1011
                        }
17750 jghali 1012
                        uint start = pgit->isTextFrame() ? (uint) pgit->firstInFrame() : 0;
1013
                        uint stop  = pgit->isTextFrame() ? (uint) pgit->lastInFrame() + 1 : (uint) pgit->itemText.length();
1014
                        for (uint e = start; e < stop; ++e)
3133 fschmid 1015
                        {
7210 avox 1016
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
3133 fschmid 1017
                        }
1018
                }
1019
        }
11453 fschmid 1020
/*      if (Options.docInfoMarks)
6943 fschmid 1021
        {
1022
                StdFonts.insert("/Helvetica", "");
11453 fschmid 1023
        } */
6407 fschmid 1024
        QStringList patterns = doc.getUsedPatterns();
8559 subik 1025
        for (int c = 0; c < patterns.count(); ++c)
6407 fschmid 1026
        {
1027
                ScPattern pa = doc.docPatterns[patterns[c]];
9856 fschmid 1028
                for (int o = 0; o < pa.items.count(); o++)
6407 fschmid 1029
                {
1030
                        pgit = pa.items.at(o);
1031
                        if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
1032
                        {
1033
                                if (pgit->isAnnotation())
8351 fschmid 1034
                                {
1035
                                        if (pgit->annotation().Type() == 4)
1036
                                                StdFonts.insert("/ZapfDingbats", "");
12763 fschmid 1037
                                        if (pgit->itemText.length() > 0)
1038
                                        {
12900 fschmid 1039
                                                if (Options.Version < PDFOptions::PDFVersion_14)
1040
                                                        StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
12763 fschmid 1041
                                                ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
1042
                                        }
8351 fschmid 1043
                                }
17750 jghali 1044
                                uint start = pgit->isTextFrame() ? (uint) pgit->firstInFrame() : 0;
1045
                                uint stop  = pgit->isTextFrame() ? (uint) pgit->lastInFrame() + 1 : (uint) pgit->itemText.length();
1046
                                for (uint e = start; e < stop; ++e)
6407 fschmid 1047
                                {
7210 avox 1048
                                        ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
6407 fschmid 1049
                                }
1050
                        }
1051
                }
1052
        }
4017 fschmid 1053
        a = 0;
1054
        QMap<QString, QString>::Iterator itStd;
1055
        for (itStd = StdFonts.begin(); itStd != StdFonts.end(); ++itStd)
1056
        {
12080 avox 1057
                uint fontObject = newObject();
1058
                StartObj(fontObject);
4017 fschmid 1059
                PutDoc("<<\n/Type /Font\n/Subtype /Type1\n");
8392 fschmid 1060
                PutDoc("/Name /FoStd"+QString::number(a)+"\n");
4017 fschmid 1061
                PutDoc("/BaseFont "+itStd.key()+"\n");
8432 fschmid 1062
                if (itStd.key() != "/ZapfDingbats")
1063
                {
1064
                        PutDoc("/Encoding << \n");
1065
                        PutDoc("/Differences [ \n");
1066
                        PutDoc("24 /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde\n");
1067
                        PutDoc("39 /quotesingle 96 /grave 128 /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction /guilsinglleft /guilsinglright\n");
1068
                        PutDoc("/minus /perthousand /quotedblbase /quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron\n");
1069
                        PutDoc("/Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron 164 /currency 166 /brokenbar 168 /dieresis /copyright /ordfeminine 172 /logicalnot\n");
1070
                        PutDoc("/.notdef /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu 183 /periodcentered /cedilla /onesuperior /ordmasculine\n");
1071
                        PutDoc("188 /onequarter /onehalf /threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex\n");
1072
                        PutDoc("/Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n");
1073
                        PutDoc("/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n");
1074
                        PutDoc("/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis\n");
1075
                        PutDoc("/divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis\n");
1076
                        PutDoc("] >>\n");
1077
                }
4017 fschmid 1078
                PutDoc(">>\nendobj\n");
12080 avox 1079
                Seite.FObjects["FoStd"+QString::number(a)] = fontObject;
10469 cbradney 1080
                itStd.value() = "FoStd"+QString::number(a);
4017 fschmid 1081
                a++;
1082
        }
5387 avox 1083
        QMap<QString,QMap<uint, FPointArray> >::Iterator it;
3133 fschmid 1084
        a = 0;
1085
        for (it = ReallyUsed.begin(); it != ReallyUsed.end(); ++it)
1086
        {
16337 jghali 1087
                ScFace& face(AllFonts[it.key()]);
1088
                ScFace::FontFormat fformat = face.format();
1089
                if ((!face.hasNames()) || (Options.SubsetList.contains(it.key())))
3133 fschmid 1090
                {
16337 jghali 1091
                        if (face.hasNames())
3133 fschmid 1092
                        {
8469 fschmid 1093
                                UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
1094
                                uint SubFonts = 0;
8559 subik 1095
                                int glyphCount = 0;
8469 fschmid 1096
                                double minx = 99999.9;
1097
                                double miny = 99999.9;
1098
                                double maxx = -99999.9;
1099
                                double maxy = -99999.9;
9803 fschmid 1100
                                QList<uint> glyphWidths;
8469 fschmid 1101
                                QStringList charProcs;
1102
                                QString encoding = "<< /Type /Encoding\n/Differences [ 0\n";
1103
                                QString fon("");
1104
                                QMap<uint, uint> glyphMapping;
1105
                                QMap<uint,std::pair<QChar,QString> > gl;
16337 jghali 1106
                                face.glyphNames(gl);
10469 cbradney 1107
                                QMap<uint,FPointArray>& RealGlyphs(it.value());
8469 fschmid 1108
                                QMap<uint,FPointArray>::Iterator ig;
1109
                                for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
3133 fschmid 1110
                                {
8469 fschmid 1111
                                        FPoint np, np1, np2;
1112
                                        bool nPath = true;
1113
                                        fon = "";
10469 cbradney 1114
                                        if (ig.value().size() > 3)
3133 fschmid 1115
                                        {
10469 cbradney 1116
                                                FPointArray gly = ig.value();
8501 cbradney 1117
                                                QMatrix mat;
8469 fschmid 1118
                                                mat.scale(100.0, -100.0);
1119
                                                gly.map(mat);
1120
                                                gly.translate(0, 1000);
1121
                                                for (uint poi = 0; poi < gly.size()-3; poi += 4)
3133 fschmid 1122
                                                {
8469 fschmid 1123
                                                        if (gly.point(poi).x() > 900000)
1124
                                                        {
1125
                                                                fon += "h\n";
1126
                                                                nPath = true;
1127
                                                                continue;
1128
                                                        }
1129
                                                        if (nPath)
1130
                                                        {
1131
                                                                np = gly.point(poi);
1132
                                                                fon += FToStr(np.x())+" "+FToStr(np.y())+" m\n";
1133
                                                                nPath = false;
1134
                                                        }
1135
                                                        np = gly.point(poi+1);
1136
                                                        np1 = gly.point(poi+3);
1137
                                                        np2 = gly.point(poi+2);
1138
                                                        fon += FToStr(np.x()) + " " + FToStr(np.y()) + " " + FToStr(np1.x()) + " " + FToStr(np1.y()) + " " + FToStr(np2.x()) + " " + FToStr(np2.y()) + " c\n";
3133 fschmid 1139
                                                }
8469 fschmid 1140
                                                fon += "h f*\n";
1141
                                                np = getMinClipF(&gly);
1142
                                                np1 = getMaxClipF(&gly);
1143
                                        }
1144
                                        else
1145
                                        {
1146
                                                fon = "h";
1147
                                                np = FPoint(0, 0);
1148
                                                np1 = FPoint(0, 0);
1149
                                        }
1150
                                        fon.prepend(QString::number(qRound(np1.x())) + " 0 "+QString::number(qRound(np.x()))+" "+QString::number(qRound(np.y()))+" "+QString::number(qRound(np1.x()))+ " "+QString::number(qRound(np1.y()))+" d1\n");
8562 jghali 1151
                                        minx = qMin(minx, np.x());
1152
                                        miny = qMin(miny, np.y());
1153
                                        maxx = qMax(maxx, np1.x());
1154
                                        maxy = qMax(maxy, np1.y());
8469 fschmid 1155
                                        glyphWidths.append(qRound(np1.x()));
12080 avox 1156
                                        uint charProcObject = newObject();
1157
                                        charProcs.append("/"+gl[ig.key()].second+" "+QString::number(charProcObject)+" 0 R\n");
8469 fschmid 1158
                                        encoding += "/"+gl[ig.key()].second+" ";
1159
                                        glyphMapping.insert(ig.key(), glyphCount + SubFonts * 256);
12080 avox 1160
                                        StartObj(charProcObject);
11317 jghali 1161
                                        if (Options.Compress)
8469 fschmid 1162
                                                fon = CompressStr(&fon);
1163
                                        PutDoc("<< /Length "+QString::number(fon.length()+1));
11317 jghali 1164
                                        if (Options.Compress)
8469 fschmid 1165
                                                PutDoc("\n/Filter /FlateDecode");
12080 avox 1166
                                        PutDoc("\n>>\nstream\n"+EncStream(fon, charProcObject)+"\nendstream\nendobj\n");
8469 fschmid 1167
                                        glyphCount++;
13521 jghali 1168
                                        int glyphsLeft = RealGlyphs.count() - SubFonts * 256;
1169
                                        if ((glyphCount > 255) || (glyphCount == glyphsLeft))
8469 fschmid 1170
                                        {
12080 avox 1171
                                                uint fontWidths = newObject();
1172
                                                StartObj(fontWidths);
8469 fschmid 1173
                                                PutDoc("[ ");
8559 subik 1174
                                                for (int ww = 0; ww < glyphWidths.count(); ++ww)
3133 fschmid 1175
                                                {
8469 fschmid 1176
                                                        PutDoc(QString::number(qRound(glyphWidths[ww]))+" ");
3133 fschmid 1177
                                                }
8469 fschmid 1178
                                                PutDoc("]\nendobj\n");
12080 avox 1179
                                                uint fontCharProcs = newObject();
1180
                                                StartObj(fontCharProcs);
8469 fschmid 1181
                                                PutDoc("<<\n");
8559 subik 1182
                                                for (int ww = 0; ww < charProcs.count(); ++ww)
8469 fschmid 1183
                                                {
1184
                                                        PutDoc(charProcs[ww]);
1185
                                                }
1186
                                                PutDoc(">>\nendobj\n");
12080 avox 1187
                                                uint fontEncoding = newObject();
1188
                                                StartObj(fontEncoding);
8469 fschmid 1189
                                                PutDoc(encoding);
1190
                                                PutDoc("]\n");
1191
                                                PutDoc(">>\nendobj\n");
12080 avox 1192
                                                uint font3Object = newObject();
1193
                                                StartObj(font3Object);
8469 fschmid 1194
                                                PutDoc("<<\n/Type /Font\n/Subtype /Type3\n");
1195
                                                PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(SubFonts)+"\n");
1196
                                                PutDoc("/FirstChar 0\n");
1197
                                                PutDoc("/LastChar "+QString::number(glyphCount-1)+"\n");
12080 avox 1198
                                                PutDoc("/Widths "+QString::number(fontWidths)+" 0 R\n");
1199
                                                PutDoc("/CharProcs "+QString::number(fontCharProcs)+" 0 R\n");
8469 fschmid 1200
                                                PutDoc("/FontBBox ["+QString::number(qRound(minx))+" "+QString::number(qRound(miny))+" "+QString::number(qRound(maxx))+ " "+QString::number(qRound(maxy))+"]\n");
1201
                                                PutDoc("/FontMatrix [0.001 0 0 0.001 0 0]\n");
12080 avox 1202
                                                PutDoc("/Encoding "+QString::number(fontEncoding)+" 0 R\n");
8469 fschmid 1203
                                                PutDoc(">>\nendobj\n");
12080 avox 1204
                                                Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(SubFonts)] = font3Object;
8469 fschmid 1205
                                                charProcs.clear();
1206
                                                glyphWidths.clear();
1207
//                                              glyphMapping.clear();
1208
                                                glyphCount = 0;
13521 jghali 1209
                                                ++SubFonts;
8469 fschmid 1210
                                                minx = 99999.9;
1211
                                                miny = 99999.9;
1212
                                                maxx = -99999.9;
1213
                                                maxy = -99999.9;
1214
                                                encoding = "<< /Type /Encoding\n/Differences [ 0\n";
3133 fschmid 1215
                                        }
1216
                                }
8469 fschmid 1217
                                Type3Fonts.insert("/Fo"+QString::number(a), glyphMapping);
1218
                        }
1219
                        else
1220
                        {
1221
                                QString fon("");
10469 cbradney 1222
                                QMap<uint,FPointArray>& RealGlyphs(it.value());
8469 fschmid 1223
                                QMap<uint,FPointArray>::Iterator ig;
1224
                                for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
5606 fschmid 1225
                                {
8469 fschmid 1226
                                        FPoint np, np1, np2;
1227
                                        bool nPath = true;
1228
                                        fon = "";
10469 cbradney 1229
                                        if (ig.value().size() > 3)
8469 fschmid 1230
                                        {
10469 cbradney 1231
                                                FPointArray gly = ig.value();
8501 cbradney 1232
                                                QMatrix mat;
8469 fschmid 1233
                                                mat.scale(0.1, 0.1);
1234
                                                gly.map(mat);
1235
                                                for (uint poi = 0; poi < gly.size()-3; poi += 4)
1236
                                                {
1237
                                                        if (gly.point(poi).x() > 900000)
1238
                                                        {
1239
                                                                fon += "h\n";
1240
                                                                nPath = true;
1241
                                                                continue;
1242
                                                        }
1243
                                                        if (nPath)
1244
                                                        {
1245
                                                                np = gly.point(poi);
1246
                                                                fon += FToStr(np.x())+" "+FToStr(-np.y())+" m\n";
1247
                                                                nPath = false;
1248
                                                        }
1249
                                                        np = gly.point(poi+1);
1250
                                                        np1 = gly.point(poi+3);
1251
                                                        np2 = gly.point(poi+2);
1252
                                                        fon += FToStr(np.x()) + " " + FToStr(-np.y()) + " " +
1253
                                                                FToStr(np1.x()) + " " + FToStr(-np1.y()) + " " +
1254
                                                                FToStr(np2.x()) + " " + FToStr(-np2.y()) + " c\n";
1255
                                                }
1256
                                                fon += "h f*\n";
1257
                                                np = getMinClipF(&gly);
1258
                                                np1 = getMaxClipF(&gly);
1259
                                        }
1260
                                        else
1261
                                        {
1262
                                                fon = "h";
1263
                                                np = FPoint(0, 0);
1264
                                                np1 = FPoint(0, 0);
1265
                                        }
12080 avox 1266
                                        uint fontGlyphXForm = newObject();
1267
                                        StartObj(fontGlyphXForm);
8469 fschmid 1268
                                        PutDoc("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1\n");
1269
                                        PutDoc("/BBox [ "+FToStr(np.x())+" "+FToStr(-np.y())+" "+FToStr(np1.x())+ " "+FToStr(-np1.y())+" ]\n");
1270
                                        PutDoc("/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
1271
                                        PutDoc(">>\n");
11317 jghali 1272
                                        if (Options.Compress)
8469 fschmid 1273
                                                fon = CompressStr(&fon);
1274
                                        PutDoc("/Length "+QString::number(fon.length()+1));
11317 jghali 1275
                                        if (Options.Compress)
8469 fschmid 1276
                                                PutDoc("\n/Filter /FlateDecode");
12080 avox 1277
                                        PutDoc(" >>\nstream\n"+EncStream(fon, fontGlyphXForm)+"\nendstream\nendobj\n");
17629 jghali 1278
                                        Seite.XObjects[face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+QString::number(ig.key())] = fontGlyphXForm;
5606 fschmid 1279
                                }
3133 fschmid 1280
                        }
1281
                }
1282
                else
1283
                {
4229 craig 1284
                        UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
12080 avox 1285
                        uint embeddedFontObject = 0;
5980 avox 1286
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1287
                        {
3829 cbradney 1288
                                QString fon("");
17629 jghali 1289
                                QByteArray bb;
12080 avox 1290
                                embeddedFontObject = newObject();
1291
                                StartObj(embeddedFontObject);
17629 jghali 1292
                                face.RawData(bb);
8559 subik 1293
                                int posi;
3133 fschmid 1294
                                for (posi = 6; posi < bb.size(); ++posi)
1295
                                {
1296
                                        if ((bb[posi] == static_cast<char>(0x80)) && (static_cast<int>(bb[posi+1]) == 2))
1297
                                                break;
1298
                                        fon += QChar(bb[posi]);
1299
                                }
1300
                                int len1 = fon.length();
8559 subik 1301
                                int ulen;
3133 fschmid 1302
                                ulen = bb[posi+2] & 0xff;
1303
                                ulen |= (bb[posi+3] << 8) & 0xff00;
1304
                                ulen |= (bb[posi+4] << 16) & 0xff0000;
1305
                                ulen |= (bb[posi+5] << 24) & 0xff000000;
1306
                                if (ulen > bb.size())
1307
                                        ulen = bb.size()-7;
1308
                                posi += 6;
8559 subik 1309
                                for (int j = 0; j < ulen; ++j)
3133 fschmid 1310
                                        fon += QChar(bb[posi++]);
1311
                                posi += 6;
1312
                                int len2 = fon.length()-len1;
8559 subik 1313
                                for (int j = posi; j < bb.size(); ++j)
3133 fschmid 1314
                                {
1315
                                        if ((bb[j] == static_cast<char>(0x80)) && (static_cast<int>(bb[j+1]) == 3))
1316
                                                break;
1317
                                        if (bb[j] == '\r')
1318
                                                fon += "\n";
1319
                                        else
1320
                                                fon += QChar(bb[j]);
1321
                                }
1322
                                int len3 = fon.length()-len2-len1;
11317 jghali 1323
                                if (Options.Compress)
3133 fschmid 1324
                                        fon = CompressStr(&fon);
4229 craig 1325
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
1326
                                PutDoc("/Length1 "+QString::number(len1)+"\n");
1327
                                PutDoc("/Length2 "+QString::number(len2)+"\n");
1328
                                PutDoc("/Length3 "+QString::number(len3)+"\n");
11317 jghali 1329
                                if (Options.Compress)
3133 fschmid 1330
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1331
                                PutDoc(">>\nstream\n"+EncStream(fon,embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1332
                        }
5980 avox 1333
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1334
                        {
3829 cbradney 1335
                                QString fon("");
1336
                                QString fon2("");
1337
                                QString tm("");
3133 fschmid 1338
                                uint value;
1339
                                bool ok = true;
12080 avox 1340
                                embeddedFontObject = newObject();
1341
                                StartObj(embeddedFontObject);
17629 jghali 1342
                                face.EmbedFont(fon);
10469 cbradney 1343
                                int len1 = fon.indexOf("eexec")+5;
3133 fschmid 1344
                                fon2 = fon.left(len1)+"\n";
10469 cbradney 1345
                                int len2 = fon.indexOf("0000000000000000000000000");
3133 fschmid 1346
                                if (len2 == -1)
1347
                                        len2 = fon.length()+1;
1348
                                int count = 0;
1349
                                for (int xx = len1; xx < len2-1; ++xx)
1350
                                {
1351
                                        tm = fon.at(xx);
1352
                                        if ((tm == QChar(13)) || (tm == QChar(10)))
1353
                                                continue;
1354
                                        xx++;
1355
                                        count++;
1356
                                        tm += fon.at(xx);
1357
                                        value = tm.toUInt(&ok, 16);
1358
                                        fon2 += QChar(value);
1359
                                }
1360
                                fon2 += fon.mid(len2);
11317 jghali 1361
                                if (Options.Compress)
3133 fschmid 1362
                                        fon2 = CompressStr(&fon2);
4229 craig 1363
                                PutDoc("<<\n/Length "+QString::number(fon2.length()+1)+"\n");
1364
                                PutDoc("/Length1 "+QString::number(len1+1)+"\n");
1365
                                PutDoc("/Length2 "+QString::number(count)+"\n");
1366
                                PutDoc(static_cast<int>(fon.length()-len2) == -1 ? QString("/Length3 0\n") : "/Length3 "+QString::number(fon.length()-len2)+"\n");
11317 jghali 1367
                                if (Options.Compress)
3133 fschmid 1368
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1369
                                PutDoc(">>\nstream\n"+EncStream(fon2, embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1370
                        }
5980 avox 1371
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1372
                        {
3829 cbradney 1373
                                QString fon("");
17629 jghali 1374
                                QByteArray bb;
12080 avox 1375
                                embeddedFontObject = newObject();
1376
                                StartObj(embeddedFontObject);
17629 jghali 1377
                                face.RawData(bb);
3133 fschmid 1378
                                //AV: += and append() dont't work because they stop at '\0' :-(
8559 subik 1379
                                for (int i=0; i < bb.size(); i++)
3133 fschmid 1380
                                        fon += QChar(bb[i]);
1381
                                int len = fon.length();
11317 jghali 1382
                                if (Options.Compress)
3133 fschmid 1383
                                        fon = CompressStr(&fon);
13085 jghali 1384
                                //qDebug() << QString("sfnt data: size=%1 before=%2 compressed=%3").arg(bb.size()).arg(len).arg(fon.length());
4229 craig 1385
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
1386
                                PutDoc("/Length1 "+QString::number(len)+"\n");
11317 jghali 1387
                                if (Options.Compress)
3133 fschmid 1388
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1389
                                PutDoc(">>\nstream\n"+EncStream(fon, embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1390
                        }
12080 avox 1391
                        uint fontDescriptor = newObject();
1392
                        StartObj(fontDescriptor);
5387 avox 1393
                        // TODO: think about QByteArray ScFace::getFontDescriptor() -- AV
3133 fschmid 1394
                        PutDoc("<<\n/Type /FontDescriptor\n");
17777 jghali 1395
                        PutDoc("/FontName /"  + face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ) + "\n");
1396
                        PutDoc("/FontBBox [ " + face.pdfFontBBoxAsString()+" ]\n");
3133 fschmid 1397
                        PutDoc("/Flags ");
5980 avox 1398
                        //FIXME: isItalic() should be queried from ScFace, not from Qt -- AV
3544 avox 1399
                        //QFontInfo fo = QFontInfo(it.data());
3133 fschmid 1400
                        int pfl = 0;
17629 jghali 1401
                        if (face.isFixedPitch())
3133 fschmid 1402
                                pfl = pfl ^ 1;
3544 avox 1403
                        //if (fo.italic())
17629 jghali 1404
                        if (face.italicAngleAsString() != "0")
3133 fschmid 1405
                                pfl = pfl ^ 64;
1406
//                      pfl = pfl ^ 4;
1407
                        pfl = pfl ^ 32;
4229 craig 1408
                        PutDoc(QString::number(pfl)+"\n");
17777 jghali 1409
                        PutDoc("/Ascent "      + face.pdfAscentAsString()+"\n");
1410
                        PutDoc("/Descent "     + face.pdfDescentAsString()+"\n");
1411
                        PutDoc("/CapHeight "   + face.pdfCapHeightAsString()+"\n");
1412
                        PutDoc("/ItalicAngle " + face.italicAngleAsString()+"\n");
6213 fschmid 1413
                        PutDoc("/StemV 1\n");
5980 avox 1414
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
12080 avox 1415
                                PutDoc("/FontFile2 "+QString::number(embeddedFontObject)+" 0 R\n");
5980 avox 1416
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
12080 avox 1417
                                PutDoc("/FontFile "+QString::number(embeddedFontObject)+" 0 R\n");
5980 avox 1418
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
12080 avox 1419
                                PutDoc("/FontFile "+QString::number(embeddedFontObject)+" 0 R\n");
3133 fschmid 1420
                        PutDoc(">>\nendobj\n");
17629 jghali 1421
 
1422
                        QMap<uint,std::pair<QChar,QString> > gl;
1423
                        face.glyphNames(gl);
1424
                        int nglyphs = 0;
1425
                        QMap<uint,std::pair<QChar,QString> >::Iterator gli;
1426
                        for (gli = gl.begin(); gli != gl.end(); ++gli)
3133 fschmid 1427
                        {
17629 jghali 1428
                                if (gli.key() > static_cast<uint>(nglyphs))
1429
                                        nglyphs = gli.key();
1430
                        }
1431
                        ++nglyphs;
1432
//                      qDebug() << QString("pdflib: nglyphs %1 max %2").arg(nglyphs).arg(face.maxGlyph());
1433
                        uint FontDes = fontDescriptor;
1434
                        uint Fcc = nglyphs / 224;
1435
                        if ((nglyphs % 224) != 0)
1436
                                Fcc += 1;
1437
                        for (uint Fc = 0; Fc < Fcc; ++Fc)
1438
                        {
1439
                                uint fontWidths2 = newObject();
1440
                                StartObj(fontWidths2);
1441
                                int chCount = 32;
1442
                                PutDoc("[ 0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 ");
1443
                                for (int ww = 32; ww < 256; ++ww)
3133 fschmid 1444
                                {
17629 jghali 1445
                                        uint glyph = 224 * Fc + ww - 32;
1446
                                        if (gl.contains(glyph))
1447
                                                PutDoc(QString::number(static_cast<int>(face.glyphWidth(glyph)* 1000))+" ");
1448
                                        else
1449
                                                PutDoc("0 ");
1450
                                        chCount++;
1451
                                        if (signed(glyph) == nglyphs-1)
3133 fschmid 1452
                                                break;
1453
                                }
1454
                                PutDoc("]\nendobj\n");
17629 jghali 1455
                                uint fontEncoding2 = newObject();
1456
                                StartObj(fontEncoding2);
1457
                                QStringList toUnicodeMaps;
1458
                                QList<int> toUnicodeMapsCount;
1459
                                QString toUnicodeMap = "";
1460
                                int toUnicodeMapCounter = 0;
1461
                                PutDoc("<< /Type /Encoding\n");
1462
                                PutDoc("/Differences [ \n");
1463
                                int crc = 0;
1464
                                bool startOfSeq = true;
1465
                                for (int ww2 = 32; ww2 < 256; ++ww2)
8092 fschmid 1466
                                {
17629 jghali 1467
                                        uint glyph = 224 * Fc + ww2 - 32;
1468
                                        QMap<uint,std::pair<QChar,QString> >::Iterator glIt = gl.find(glyph);
1469
                                        if (glIt != gl.end() && !glIt.value().second.isEmpty())
3133 fschmid 1470
                                        {
17629 jghali 1471
                                                if (startOfSeq)
6213 fschmid 1472
                                                {
17629 jghali 1473
                                                        PutDoc(QString::number(ww2)+" ");
1474
                                                        startOfSeq = false;
6213 fschmid 1475
                                                }
17629 jghali 1476
                                                PutDoc("/"+glIt.value().second+" ");
1477
                                                QString tmp, tmp2;
1478
                                                tmp.sprintf("%02X", ww2);
1479
                                                tmp2.sprintf("%04X", glIt.value().first.unicode());
1480
                                                toUnicodeMap += QString("<%1> <%2>\n").arg(tmp).arg((tmp2));
1481
                                                toUnicodeMapCounter++;
1482
                                                if (toUnicodeMapCounter == 100)
8092 fschmid 1483
                                                {
17629 jghali 1484
                                                        toUnicodeMaps.append(toUnicodeMap);
1485
                                                        toUnicodeMapsCount.append(toUnicodeMapCounter);
1486
                                                        toUnicodeMap = "";
1487
                                                        toUnicodeMapCounter = 0;
6301 avox 1488
                                                }
17629 jghali 1489
                                                crc++;
3133 fschmid 1490
                                        }
17629 jghali 1491
                                        else
8147 fschmid 1492
                                        {
17629 jghali 1493
                                                startOfSeq = true;
8147 fschmid 1494
                                        }
17629 jghali 1495
                                        if (signed(glyph) == nglyphs-1)
1496
                                                break;
1497
                                        if (crc > 8)
8147 fschmid 1498
                                        {
17629 jghali 1499
                                                PutDoc("\n");
1500
                                                crc = 0;
8147 fschmid 1501
                                        }
17629 jghali 1502
                                }
1503
                                if (toUnicodeMapCounter != 0)
8101 fschmid 1504
                                {
17629 jghali 1505
                                        toUnicodeMaps.append(toUnicodeMap);
1506
                                        toUnicodeMapsCount.append(toUnicodeMapCounter);
8101 fschmid 1507
                                }
17629 jghali 1508
                                PutDoc("]\n");
1509
                                PutDoc(">>\nendobj\n");
1510
                                QString toUnicodeMapStream = "";
1511
                                toUnicodeMapStream += "/CIDInit /ProcSet findresource begin\n";
1512
                                toUnicodeMapStream += "12 dict begin\n";
1513
                                toUnicodeMapStream += "begincmap\n";
1514
                                toUnicodeMapStream += "/CIDSystemInfo <<\n";
1515
                                toUnicodeMapStream += "/Registry (Adobe)\n";
1516
                                toUnicodeMapStream += "/Ordering (UCS)\n";
1517
                                toUnicodeMapStream += "/Supplement 0\n";
1518
                                toUnicodeMapStream += ">> def\n";
1519
                                toUnicodeMapStream += "/CMapName /Adobe-Identity-UCS def\n";
1520
                                toUnicodeMapStream += "/CMapType 2 def\n";
1521
                                toUnicodeMapStream += "1 begincodespacerange\n";
1522
                                toUnicodeMapStream += "<0000> <FFFF>\n";
1523
                                toUnicodeMapStream += "endcodespacerange\n";
1524
                                for (int uniC = 0; uniC < toUnicodeMaps.count(); uniC++)
1525
                                {
1526
                                        toUnicodeMapStream += QString("%1 beginbfchar\n").arg(toUnicodeMapsCount[uniC]);
1527
                                        toUnicodeMapStream += toUnicodeMaps[uniC];
1528
                                        toUnicodeMapStream += "endbfchar\n";
1529
                                }
1530
                                toUnicodeMapStream += "endcmap\n";
1531
                                toUnicodeMapStream += "CMapName currentdict /CMap defineresource pop\n";
1532
                                toUnicodeMapStream += "end\n";
1533
                                toUnicodeMapStream += "end\n";
1534
                                uint fontToUnicode2 = WritePDFStream(toUnicodeMapStream);
1535
                                uint fontObject2 = newObject();
1536
                                StartObj(fontObject2);
8101 fschmid 1537
                                PutDoc("<<\n/Type /Font\n/Subtype ");
1538
                                PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
17629 jghali 1539
                                PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(Fc)+"\n");
1540
                                PutDoc("/BaseFont /"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
8101 fschmid 1541
                                PutDoc("/FirstChar 0\n");
17629 jghali 1542
                                PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
1543
                                PutDoc("/Widths "+QString::number(fontWidths2)+" 0 R\n");
1544
                                PutDoc("/Encoding "+QString::number(fontEncoding2)+" 0 R\n");
1545
                                PutDoc("/ToUnicode "+QString::number(fontToUnicode2)+" 0 R\n");
8101 fschmid 1546
                                PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
1547
                                PutDoc(">>\nendobj\n");
17629 jghali 1548
                                Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(Fc)] = fontObject2;
1549
                        } // for(Fc)
1550
                        uint fontWidthsForm = newObject();
1551
                        StartObj(fontWidthsForm);
1552
                        PutDoc("[ 0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 ");
1553
                        for (int ww = 32; ww < 256; ++ww)
1554
                        {
1555
                                uint glyph = face.char2CMap(QChar(ww));
1556
                                if (gl.contains(glyph))
1557
                                        PutDoc(QString::number(static_cast<int>(face.glyphWidth(glyph)* 1000))+" ");
1558
                                else
1559
                                        PutDoc("0 ");
1560
                        }
1561
                        PutDoc("]\nendobj\n");
1562
                        uint fontObjectForm = newObject();
1563
                        StartObj(fontObjectForm);
1564
                        PutDoc("<<\n/Type /Font\n/Subtype ");
1565
                        PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
1566
//                      if (fformat == ScFace::SFNT || fformat == ScFace::TTCF)
1567
//                      {
1568
//                              PutDoc("/TrueType\n");
1569
                                PutDoc("/Name /Fo"+QString::number(a)+"Form"+"\n");
1570
                                Seite.FObjects["Fo"+QString::number(a)+"Form"] = fontObjectForm;
1571
                                UsedFontsF.insert(it.key(), "/Fo"+QString::number(a)+"Form");
1572
/*                      }
1573
                        else
1574
                        {
1575
                                PutDoc("/Type1\n");
1576
                                PutDoc("/Name /"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1577
                                Seite.FObjects[face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )] = ObjCounter;
1578
                                UsedFontsF.insert(it.key(), "/"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ));
1579
                        } */
1580
                        PutDoc("/BaseFont /"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1581
                        PutDoc("/Encoding << \n");
1582
                        PutDoc("/Differences [ \n");
1583
                        PutDoc("24 /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde\n");
1584
                        PutDoc("39 /quotesingle 96 /grave 128 /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction /guilsinglleft /guilsinglright\n");
1585
                        PutDoc("/minus /perthousand /quotedblbase /quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron\n");
1586
                        PutDoc("/Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron 164 /currency 166 /brokenbar 168 /dieresis /copyright /ordfeminine 172 /logicalnot\n");
1587
                        PutDoc("/.notdef /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu 183 /periodcentered /cedilla /onesuperior /ordmasculine\n");
1588
                        PutDoc("188 /onequarter /onehalf /threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex\n");
1589
                        PutDoc("/Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n");
1590
                        PutDoc("/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n");
1591
                        PutDoc("/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis\n");
1592
                        PutDoc("/divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis\n");
1593
                        PutDoc("] >>\n");
1594
                        PutDoc("/FirstChar 0\n");
1595
                        PutDoc("/LastChar 255\n");
1596
                        PutDoc("/Widths "+QString::number(fontWidthsForm)+" 0 R\n");
1597
                        PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
1598
                        PutDoc(">>\nendobj\n");
3133 fschmid 1599
                }
1600
                a++;
1601
        }
4264 craig 1602
        if (Options.UseLPI)
3133 fschmid 1603
        {
12080 avox 1604
                uint halftones = newObject();
1605
                StartObj(halftones);
3133 fschmid 1606
                PutDoc("<<\n/Type /Halftone\n/HalftoneType 5\n");
4264 craig 1607
                QMap<QString,LPIData>::const_iterator itlp;
1608
                for (itlp = Options.LPISettings.constBegin(); itlp != Options.LPISettings.constEnd(); ++itlp)
3133 fschmid 1609
                {
1610
                        PutDoc("/"+itlp.key()+"\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency ");
10469 cbradney 1611
                        PutDoc(QString::number(itlp.value().Frequency)+"\n/Angle "+QString::number(itlp.value().Angle)+"\n/SpotFunction ");
3829 cbradney 1612
                        QString func ("");
10469 cbradney 1613
                        switch (itlp.value().SpotFunc)
3133 fschmid 1614
                        {
1615
                                case 0:
1616
                                        func = "/SimpleDot";
1617
                                        break;
1618
                                case 1:
1619
                                        func = "/Line";
1620
                                        break;
1621
                                case 2:
1622
                                        func = "/Round";
1623
                                        break;
1624
                                case 3:
1625
                                        func = "/Ellipse";
1626
                                        break;
1627
                                default:
1628
                                        func = "/SimpleDot";
1629
                                        break;
1630
                        }
1631
                        PutDoc(func+"\n>>\n");
1632
                }
1633
                PutDoc("/Default\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency 50\n/Angle 45\n/SpotFunction /Round\n>>\n");
1634
                PutDoc(">>\nendobj\n");
4229 craig 1635
                HTName = ResNam+QString::number(ResCount);
12080 avox 1636
                Transpar[HTName] = writeGState("/HT "+QString::number(halftones)+" 0 R\n");
3133 fschmid 1637
                ResCount++;
1638
        }
19033 jghali 1639
        if ((doc.HasCMS) && (Options.UseProfiles) && (Options.Version != PDFOptions::PDFVersion_X1a))
3133 fschmid 1640
        {
12080 avox 1641
                uint iccProfileObject = newObject();
1642
                StartObj(iccProfileObject);
7144 jghali 1643
                QByteArray dataP;
3133 fschmid 1644
                struct ICCD dataD;
7144 jghali 1645
                loadRawBytes(ScCore->InputProfiles[Options.SolidProf], dataP);
3133 fschmid 1646
                PutDoc("<<\n");
11317 jghali 1647
                if (Options.Compress)
3133 fschmid 1648
                {
11317 jghali 1649
                        QByteArray compData = CompressArray(dataP);
1650
                        if (compData.size() > 0)
1651
                        {
1652
                                PutDoc("/Filter /FlateDecode\n");
1653
                                dataP = compData;
1654
                        }
3133 fschmid 1655
                }
7144 jghali 1656
                PutDoc("/Length "+QString::number(dataP.size()+1)+"\n");
4264 craig 1657
                PutDoc("/N "+QString::number(Options.SComp)+"\n");
7144 jghali 1658
                PutDoc(">>\nstream\n");
12080 avox 1659
                EncodeArrayToStream(dataP, iccProfileObject);
7144 jghali 1660
                PutDoc("\nendstream\nendobj\n");
12080 avox 1661
                uint iccColorspace = newObject();
1662
                StartObj(iccColorspace);
4229 craig 1663
                dataD.ResName = ResNam+QString::number(ResCount);
12080 avox 1664
                dataD.ICCArray = "[ /ICCBased "+QString::number(iccProfileObject)+" 0 R ]";
1665
                dataD.ResNum = iccColorspace;
12732 fschmid 1666
                dataD.components = Options.SComp;
4264 craig 1667
                ICCProfiles[Options.SolidProf] = dataD;
12080 avox 1668
                PutDoc("[ /ICCBased "+QString::number(iccProfileObject)+" 0 R ]\n");
3133 fschmid 1669
                PutDoc("endobj\n");
1670
                ResCount++;
1671
        }
4264 craig 1672
        if (((Options.isGrayscale == false) && (Options.UseRGB == false)) && (Options.UseSpotColors))
3133 fschmid 1673
        {
4264 craig 1674
                doc.getUsedColors(colorsToUse);
3133 fschmid 1675
                ColorList::Iterator itf;
1676
                for (itf = colorsToUse.begin(); itf != colorsToUse.end(); ++itf)
1677
                {
1678
                        if ((colorsToUse[itf.key()].isSpotColor()) || (colorsToUse[itf.key()].isRegistrationColor()))
1679
                        {
9619 jghali 1680
                                CMYKColor cmykValues;
3133 fschmid 1681
                                int cc, cm, cy, ck;
1682
                                struct SpotC spotD;
9619 jghali 1683
                                ScColorEngine::getCMYKValues(colorsToUse[itf.key()], &doc, cmykValues);
1684
                                cmykValues.getValues(cc, cm, cy, ck);
3133 fschmid 1685
                                QString colorDesc = "{\ndup "+FToStr(static_cast<double>(cc) / 255)+"\nmul exch dup ";
1686
                                colorDesc += FToStr(static_cast<double>(cm) / 255)+"\nmul exch dup ";
1687
                                colorDesc += FToStr(static_cast<double>(cy) / 255)+"\nmul exch ";
1688
                                colorDesc += FToStr(static_cast<double>(ck) / 255)+" mul }";
12080 avox 1689
                                uint separationFunction = newObject();
1690
                                StartObj(separationFunction);
3133 fschmid 1691
                                PutDoc("<<\n/FunctionType 4\n");
1692
                                PutDoc("/Domain [0.0 1.0]\n");
1693
                                PutDoc("/Range [0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]\n");
4229 craig 1694
                                PutDoc("/Length "+QString::number(colorDesc.length()+1)+"\n");
12080 avox 1695
                                PutDoc(">>\nstream\n"+EncStream(colorDesc, separationFunction)+"\nendstream\nendobj\n");
1696
                                uint separationColorspace= newObject();
1697
                                StartObj(separationColorspace);
3133 fschmid 1698
                                PutDoc("[ /Separation /");
1699
                                if (colorsToUse[itf.key()].isRegistrationColor())
1700
                                        PutDoc("All");
1701
                                else
10394 cbradney 1702
                                        PutDoc(itf.key().simplified().replace("#", "#23").replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "#20" ));
12080 avox 1703
                                PutDoc(" /DeviceCMYK "+QString::number(separationFunction)+" 0 R ]\nendobj\n");
4229 craig 1704
                                spotD.ResName = spotNam+QString::number(spotCount);
12080 avox 1705
                                spotD.ResNum = separationColorspace;
3133 fschmid 1706
                                spotMap.insert(itf.key(), spotD);
1707
                                spotCount++;
1708
                        }
1709
                }
1710
        }
6925 fschmid 1711
        if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks) || (Options.docInfoMarks))
1712
        {
1713
                struct SpotC spotD;
12080 avox 1714
                uint registrationColorspace = newObject();
1715
                StartObj(registrationColorspace);
6925 fschmid 1716
                PutDoc("[ /Separation /All /DeviceCMYK\n");
1717
                PutDoc("<<\n/FunctionType 2\n");
1718
                PutDoc("/Domain [0.0 1.0]\n");
1719
                PutDoc("/Range [0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]\n");
1720
                PutDoc("/C0 [0 0 0 0] \n");
1721
                PutDoc("/C1 [1 1 1 1] \n");
1722
                PutDoc("/N 1\n");
1723
                PutDoc(">>\n]\nendobj\n");
1724
                spotD.ResName = spotNam+QString::number(spotCount);
12080 avox 1725
                spotD.ResNum = registrationColorspace;
6925 fschmid 1726
                spotMapReg.insert("Register", spotD);
1727
                spotCount++;
1728
        }
12884 jghali 1729
        if ((Options.Version == PDFOptions::PDFVersion_15) && (Options.useLayers))
3133 fschmid 1730
        {
10140 jghali 1731
                ScLayer ll;
3133 fschmid 1732
                struct OCGInfo ocg;
1733
                ll.isPrintable = false;
1734
                ll.LNr = 0;
1735
                int Lnr = 0;
3829 cbradney 1736
                QString ocgNam("oc");
4264 craig 1737
                uint docLayersCount=doc.Layers.count();
3829 cbradney 1738
                for (uint la = 0; la < docLayersCount; ++la)
3133 fschmid 1739
                {
12080 avox 1740
                        uint optionalContent = newObject();
3829 cbradney 1741
                        QString tmp("");
10140 jghali 1742
                        doc.Layers.levelToLayer(ll, Lnr);
3133 fschmid 1743
                        ocg.Name = ocgNam+tmp.setNum(ll.LNr);
12080 avox 1744
                        ocg.ObjNum = optionalContent;
3133 fschmid 1745
                        ocg.visible = ll.isViewable;
1746
                        OCGEntries.insert(ll.Name, ocg);
12080 avox 1747
                        StartObj(optionalContent);
3133 fschmid 1748
                        PutDoc("<<\n");
1749
                        PutDoc("/Type /OCG\n");
7328 fschmid 1750
                        PutDoc("/Name ");
17440 jghali 1751
                        PutDoc(EncStringUTF16(ll.Name, optionalContent));
7328 fschmid 1752
                        PutDoc("\n");
11908 fschmid 1753
                        PutDoc("/Usage <</Print <</PrintState ");
1754
                        if (ll.isPrintable)
1755
                                PutDoc("/ON");
1756
                        else
1757
                                PutDoc("/OFF");
1758
                        PutDoc(">> /View <</ViewState ");
1759
                        if (ll.isViewable)
1760
                                PutDoc("/ON");
1761
                        else
1762
                                PutDoc("/OFF");
19211 jghali 1763
                        PutDoc(">>>>");
11908 fschmid 1764
                        PutDoc("\n");
3133 fschmid 1765
                        PutDoc(">>\nendobj\n");
1766
                        Lnr++;
1767
                }
1768
        }
1769
        return true;
1770
}
1771
 
11060 jghali 1772
bool PDFLibCore::PDF_TemplatePage(const Page* pag, bool )
3133 fschmid 1773
{
11060 jghali 1774
        QString tmp, tmpOut;
3133 fschmid 1775
        ActPageP = pag;
1776
        PageItem* ite;
9856 fschmid 1777
        QList<PageItem*> PItems;
3133 fschmid 1778
        int Lnr = 0;
10140 jghali 1779
        ScLayer ll;
3133 fschmid 1780
        ll.isPrintable = false;
1781
        ll.LNr = 0;
11060 jghali 1782
        Content = "";
3133 fschmid 1783
        Seite.AObjects.clear();
8559 subik 1784
        for (int la = 0; la < doc.Layers.count(); ++la)
3133 fschmid 1785
        {
10140 jghali 1786
                doc.Layers.levelToLayer(ll, Lnr);
4264 craig 1787
                PItems = doc.MasterItems;
12884 jghali 1788
                if ((ll.isPrintable) || ((Options.Version == PDFOptions::PDFVersion_15) && (Options.useLayers)))
3133 fschmid 1789
                {
12884 jghali 1790
                        if ((Options.Version == PDFOptions::PDFVersion_15) && (Options.useLayers))
3133 fschmid 1791
                                PutPage("/OC /"+OCGEntries[ll.Name].Name+" BDC\n");
9856 fschmid 1792
                        for (int a = 0; a < PItems.count(); ++a)
3133 fschmid 1793
                        {
11060 jghali 1794
                                Content = "";
3133 fschmid 1795
                                ite =PItems.at(a);
1796
                                if (ite->LayerNr != ll.LNr)
1797
                                        continue;
13815 jghali 1798
                                double bLeft, bRight, bBottom, bTop;
1799
                                getBleeds(pag, bLeft, bRight, bBottom, bTop);
1800
                                double x  = pag->xOffset() - bLeft;
1801
                                double y  = pag->yOffset() - bTop;
1802
                                double w  = pag->width() + bLeft + bRight;
1803
                                double h1 = pag->height() + bBottom + bTop;
1804
                                double ilw= ite->lineWidth();
4726 fschmid 1805
                                double x2 = ite->BoundingX - ilw / 2.0;
1806
                                double y2 = ite->BoundingY - ilw / 2.0;
1807
                                double w2 = ite->BoundingW + ilw;
1808
                                double h2 = ite->BoundingH + ilw;
8562 jghali 1809
                                if (!( qMax( x, x2 ) <= qMin( x+w, x2+w2 ) && qMax( y, y2 ) <= qMin( y+h1, y2+h2 )))
3133 fschmid 1810
                                        continue;
1811
                                if (ite->ChangedMasterItem)
1812
                                        continue;