Subversion Repositories Scribus

Rev

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