Subversion Repositories Scribus

Rev

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