Subversion Repositories Scribus

Rev

Rev 13544 | Rev 13576 | 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"
13551 cbradney 55
#include "ui/bookmarkpalette.h"
10601 mrdocs 56
#include "cmsettings.h"
4028 cbradney 57
#include "commonstrings.h"
13544 cbradney 58
#include "ui/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
                                {
12900 fschmid 911
                                        if (Options.Version < PDFOptions::PDFVersion_14)
912
                                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
12763 fschmid 913
                                        ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
914
                                }
8092 fschmid 915
                        }
5292 fschmid 916
                        for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
3133 fschmid 917
                        {
7210 avox 918
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
3133 fschmid 919
                        }
920
                }
921
        }
9856 fschmid 922
        for (int c = 0; c < doc.MasterItems.count(); ++c)
3133 fschmid 923
        {
4264 craig 924
                pgit = doc.MasterItems.at(c);
3133 fschmid 925
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
926
                {
4084 cbradney 927
                        if (pgit->isAnnotation())
8092 fschmid 928
                        {
8351 fschmid 929
                                if (pgit->annotation().Type() == 4)
930
                                        StdFonts.insert("/ZapfDingbats", "");
12763 fschmid 931
                                if (pgit->itemText.length() > 0)
932
                                {
12900 fschmid 933
                                        if (Options.Version < PDFOptions::PDFVersion_14)
934
                                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
12763 fschmid 935
                                        ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
936
                                }
8092 fschmid 937
                        }
5292 fschmid 938
                        for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
3133 fschmid 939
                        {
7210 avox 940
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
3133 fschmid 941
                        }
942
                }
943
        }
9856 fschmid 944
        for (int d = 0; d < doc.Items->count(); ++d)
3133 fschmid 945
        {
4264 craig 946
                pgit = doc.Items->at(d);
3133 fschmid 947
                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
948
                {
4084 cbradney 949
                        if (pgit->isAnnotation())
8092 fschmid 950
                        {
8351 fschmid 951
                                if (pgit->annotation().Type() == 4)
952
                                        StdFonts.insert("/ZapfDingbats", "");
12763 fschmid 953
                                if (pgit->itemText.length() > 0)
954
                                {
12900 fschmid 955
                                        if (Options.Version < PDFOptions::PDFVersion_14)
956
                                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
12763 fschmid 957
                                        ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
958
                                }
8092 fschmid 959
                        }
5292 fschmid 960
                        for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
3133 fschmid 961
                        {
7210 avox 962
                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
3133 fschmid 963
                        }
964
                }
965
        }
11453 fschmid 966
/*      if (Options.docInfoMarks)
6943 fschmid 967
        {
968
                StdFonts.insert("/Helvetica", "");
11453 fschmid 969
        } */
6407 fschmid 970
        QStringList patterns = doc.getUsedPatterns();
8559 subik 971
        for (int c = 0; c < patterns.count(); ++c)
6407 fschmid 972
        {
973
                ScPattern pa = doc.docPatterns[patterns[c]];
9856 fschmid 974
                for (int o = 0; o < pa.items.count(); o++)
6407 fschmid 975
                {
976
                        pgit = pa.items.at(o);
977
                        if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
978
                        {
979
                                if (pgit->isAnnotation())
8351 fschmid 980
                                {
981
                                        if (pgit->annotation().Type() == 4)
982
                                                StdFonts.insert("/ZapfDingbats", "");
12763 fschmid 983
                                        if (pgit->itemText.length() > 0)
984
                                        {
12900 fschmid 985
                                                if (Options.Version < PDFOptions::PDFVersion_14)
986
                                                        StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
12763 fschmid 987
                                                ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
988
                                        }
8351 fschmid 989
                                }
6407 fschmid 990
                                for (uint e = 0; e < static_cast<uint>(pgit->itemText.length()); ++e)
991
                                {
7210 avox 992
                                        ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
6407 fschmid 993
                                }
994
                        }
995
                }
996
        }
4017 fschmid 997
        a = 0;
998
        QMap<QString, QString>::Iterator itStd;
999
        for (itStd = StdFonts.begin(); itStd != StdFonts.end(); ++itStd)
1000
        {
12080 avox 1001
                uint fontObject = newObject();
1002
                StartObj(fontObject);
4017 fschmid 1003
                PutDoc("<<\n/Type /Font\n/Subtype /Type1\n");
8392 fschmid 1004
                PutDoc("/Name /FoStd"+QString::number(a)+"\n");
4017 fschmid 1005
                PutDoc("/BaseFont "+itStd.key()+"\n");
8432 fschmid 1006
                if (itStd.key() != "/ZapfDingbats")
1007
                {
1008
                        PutDoc("/Encoding << \n");
1009
                        PutDoc("/Differences [ \n");
1010
                        PutDoc("24 /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde\n");
1011
                        PutDoc("39 /quotesingle 96 /grave 128 /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction /guilsinglleft /guilsinglright\n");
1012
                        PutDoc("/minus /perthousand /quotedblbase /quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron\n");
1013
                        PutDoc("/Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron 164 /currency 166 /brokenbar 168 /dieresis /copyright /ordfeminine 172 /logicalnot\n");
1014
                        PutDoc("/.notdef /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu 183 /periodcentered /cedilla /onesuperior /ordmasculine\n");
1015
                        PutDoc("188 /onequarter /onehalf /threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex\n");
1016
                        PutDoc("/Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n");
1017
                        PutDoc("/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n");
1018
                        PutDoc("/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis\n");
1019
                        PutDoc("/divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis\n");
1020
                        PutDoc("] >>\n");
1021
                }
4017 fschmid 1022
                PutDoc(">>\nendobj\n");
12080 avox 1023
                Seite.FObjects["FoStd"+QString::number(a)] = fontObject;
10469 cbradney 1024
                itStd.value() = "FoStd"+QString::number(a);
4017 fschmid 1025
                a++;
1026
        }
5387 avox 1027
        QMap<QString,QMap<uint, FPointArray> >::Iterator it;
3133 fschmid 1028
        a = 0;
1029
        for (it = ReallyUsed.begin(); it != ReallyUsed.end(); ++it)
1030
        {
5980 avox 1031
                ScFace::FontFormat fformat = AllFonts[it.key()].format();
7089 fschmid 1032
                if ((!AllFonts[it.key()].hasNames()) || (Options.SubsetList.contains(it.key())))
3133 fschmid 1033
                {
8469 fschmid 1034
                        if (AllFonts[it.key()].hasNames())
3133 fschmid 1035
                        {
8469 fschmid 1036
                                UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
1037
                                uint SubFonts = 0;
8559 subik 1038
                                int glyphCount = 0;
8469 fschmid 1039
                                double minx = 99999.9;
1040
                                double miny = 99999.9;
1041
                                double maxx = -99999.9;
1042
                                double maxy = -99999.9;
9803 fschmid 1043
                                QList<uint> glyphWidths;
8469 fschmid 1044
                                QStringList charProcs;
1045
                                QString encoding = "<< /Type /Encoding\n/Differences [ 0\n";
1046
                                QString fon("");
1047
                                QMap<uint, uint> glyphMapping;
1048
                                QMap<uint,std::pair<QChar,QString> > gl;
1049
                                AllFonts[it.key()].glyphNames(gl);
10469 cbradney 1050
                                QMap<uint,FPointArray>& RealGlyphs(it.value());
8469 fschmid 1051
                                QMap<uint,FPointArray>::Iterator ig;
1052
                                for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
3133 fschmid 1053
                                {
8469 fschmid 1054
                                        FPoint np, np1, np2;
1055
                                        bool nPath = true;
1056
                                        fon = "";
10469 cbradney 1057
                                        if (ig.value().size() > 3)
3133 fschmid 1058
                                        {
10469 cbradney 1059
                                                FPointArray gly = ig.value();
8501 cbradney 1060
                                                QMatrix mat;
8469 fschmid 1061
                                                mat.scale(100.0, -100.0);
1062
                                                gly.map(mat);
1063
                                                gly.translate(0, 1000);
1064
                                                for (uint poi = 0; poi < gly.size()-3; poi += 4)
3133 fschmid 1065
                                                {
8469 fschmid 1066
                                                        if (gly.point(poi).x() > 900000)
1067
                                                        {
1068
                                                                fon += "h\n";
1069
                                                                nPath = true;
1070
                                                                continue;
1071
                                                        }
1072
                                                        if (nPath)
1073
                                                        {
1074
                                                                np = gly.point(poi);
1075
                                                                fon += FToStr(np.x())+" "+FToStr(np.y())+" m\n";
1076
                                                                nPath = false;
1077
                                                        }
1078
                                                        np = gly.point(poi+1);
1079
                                                        np1 = gly.point(poi+3);
1080
                                                        np2 = gly.point(poi+2);
1081
                                                        fon += FToStr(np.x()) + " " + FToStr(np.y()) + " " + FToStr(np1.x()) + " " + FToStr(np1.y()) + " " + FToStr(np2.x()) + " " + FToStr(np2.y()) + " c\n";
3133 fschmid 1082
                                                }
8469 fschmid 1083
                                                fon += "h f*\n";
1084
                                                np = getMinClipF(&gly);
1085
                                                np1 = getMaxClipF(&gly);
1086
                                        }
1087
                                        else
1088
                                        {
1089
                                                fon = "h";
1090
                                                np = FPoint(0, 0);
1091
                                                np1 = FPoint(0, 0);
1092
                                        }
1093
                                        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 1094
                                        minx = qMin(minx, np.x());
1095
                                        miny = qMin(miny, np.y());
1096
                                        maxx = qMax(maxx, np1.x());
1097
                                        maxy = qMax(maxy, np1.y());
8469 fschmid 1098
                                        glyphWidths.append(qRound(np1.x()));
12080 avox 1099
                                        uint charProcObject = newObject();
1100
                                        charProcs.append("/"+gl[ig.key()].second+" "+QString::number(charProcObject)+" 0 R\n");
8469 fschmid 1101
                                        encoding += "/"+gl[ig.key()].second+" ";
1102
                                        glyphMapping.insert(ig.key(), glyphCount + SubFonts * 256);
12080 avox 1103
                                        StartObj(charProcObject);
11317 jghali 1104
                                        if (Options.Compress)
8469 fschmid 1105
                                                fon = CompressStr(&fon);
1106
                                        PutDoc("<< /Length "+QString::number(fon.length()+1));
11317 jghali 1107
                                        if (Options.Compress)
8469 fschmid 1108
                                                PutDoc("\n/Filter /FlateDecode");
12080 avox 1109
                                        PutDoc("\n>>\nstream\n"+EncStream(fon, charProcObject)+"\nendstream\nendobj\n");
8469 fschmid 1110
                                        glyphCount++;
13522 jghali 1111
                                        int glyphsLeft = RealGlyphs.count() - SubFonts * 256;
1112
                                        if ((glyphCount > 255) || (glyphCount == glyphsLeft))
8469 fschmid 1113
                                        {
12080 avox 1114
                                                uint fontWidths = newObject();
1115
                                                StartObj(fontWidths);
8469 fschmid 1116
                                                PutDoc("[ ");
8559 subik 1117
                                                for (int ww = 0; ww < glyphWidths.count(); ++ww)
3133 fschmid 1118
                                                {
8469 fschmid 1119
                                                        PutDoc(QString::number(qRound(glyphWidths[ww]))+" ");
3133 fschmid 1120
                                                }
8469 fschmid 1121
                                                PutDoc("]\nendobj\n");
12080 avox 1122
                                                uint fontCharProcs = newObject();
1123
                                                StartObj(fontCharProcs);
8469 fschmid 1124
                                                PutDoc("<<\n");
8559 subik 1125
                                                for (int ww = 0; ww < charProcs.count(); ++ww)
8469 fschmid 1126
                                                {
1127
                                                        PutDoc(charProcs[ww]);
1128
                                                }
1129
                                                PutDoc(">>\nendobj\n");
12080 avox 1130
                                                uint fontEncoding = newObject();
1131
                                                StartObj(fontEncoding);
8469 fschmid 1132
                                                PutDoc(encoding);
1133
                                                PutDoc("]\n");
1134
                                                PutDoc(">>\nendobj\n");
12080 avox 1135
                                                uint font3Object = newObject();
1136
                                                StartObj(font3Object);
8469 fschmid 1137
                                                PutDoc("<<\n/Type /Font\n/Subtype /Type3\n");
1138
                                                PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(SubFonts)+"\n");
1139
                                                PutDoc("/FirstChar 0\n");
1140
                                                PutDoc("/LastChar "+QString::number(glyphCount-1)+"\n");
12080 avox 1141
                                                PutDoc("/Widths "+QString::number(fontWidths)+" 0 R\n");
1142
                                                PutDoc("/CharProcs "+QString::number(fontCharProcs)+" 0 R\n");
8469 fschmid 1143
                                                PutDoc("/FontBBox ["+QString::number(qRound(minx))+" "+QString::number(qRound(miny))+" "+QString::number(qRound(maxx))+ " "+QString::number(qRound(maxy))+"]\n");
1144
                                                PutDoc("/FontMatrix [0.001 0 0 0.001 0 0]\n");
12080 avox 1145
                                                PutDoc("/Encoding "+QString::number(fontEncoding)+" 0 R\n");
8469 fschmid 1146
                                                PutDoc(">>\nendobj\n");
12080 avox 1147
                                                Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(SubFonts)] = font3Object;
8469 fschmid 1148
                                                charProcs.clear();
1149
                                                glyphWidths.clear();
1150
//                                              glyphMapping.clear();
1151
                                                glyphCount = 0;
13522 jghali 1152
                                                ++SubFonts;
8469 fschmid 1153
                                                minx = 99999.9;
1154
                                                miny = 99999.9;
1155
                                                maxx = -99999.9;
1156
                                                maxy = -99999.9;
1157
                                                encoding = "<< /Type /Encoding\n/Differences [ 0\n";
3133 fschmid 1158
                                        }
1159
                                }
8469 fschmid 1160
                                Type3Fonts.insert("/Fo"+QString::number(a), glyphMapping);
1161
                        }
1162
                        else
1163
                        {
1164
                                QString fon("");
10469 cbradney 1165
                                QMap<uint,FPointArray>& RealGlyphs(it.value());
8469 fschmid 1166
                                QMap<uint,FPointArray>::Iterator ig;
1167
                                for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
5606 fschmid 1168
                                {
8469 fschmid 1169
                                        FPoint np, np1, np2;
1170
                                        bool nPath = true;
1171
                                        fon = "";
10469 cbradney 1172
                                        if (ig.value().size() > 3)
8469 fschmid 1173
                                        {
10469 cbradney 1174
                                                FPointArray gly = ig.value();
8501 cbradney 1175
                                                QMatrix mat;
8469 fschmid 1176
                                                mat.scale(0.1, 0.1);
1177
                                                gly.map(mat);
1178
                                                for (uint poi = 0; poi < gly.size()-3; poi += 4)
1179
                                                {
1180
                                                        if (gly.point(poi).x() > 900000)
1181
                                                        {
1182
                                                                fon += "h\n";
1183
                                                                nPath = true;
1184
                                                                continue;
1185
                                                        }
1186
                                                        if (nPath)
1187
                                                        {
1188
                                                                np = gly.point(poi);
1189
                                                                fon += FToStr(np.x())+" "+FToStr(-np.y())+" m\n";
1190
                                                                nPath = false;
1191
                                                        }
1192
                                                        np = gly.point(poi+1);
1193
                                                        np1 = gly.point(poi+3);
1194
                                                        np2 = gly.point(poi+2);
1195
                                                        fon += FToStr(np.x()) + " " + FToStr(-np.y()) + " " +
1196
                                                                FToStr(np1.x()) + " " + FToStr(-np1.y()) + " " +
1197
                                                                FToStr(np2.x()) + " " + FToStr(-np2.y()) + " c\n";
1198
                                                }
1199
                                                fon += "h f*\n";
1200
                                                np = getMinClipF(&gly);
1201
                                                np1 = getMaxClipF(&gly);
1202
                                        }
1203
                                        else
1204
                                        {
1205
                                                fon = "h";
1206
                                                np = FPoint(0, 0);
1207
                                                np1 = FPoint(0, 0);
1208
                                        }
12080 avox 1209
                                        uint fontGlyphXForm = newObject();
1210
                                        StartObj(fontGlyphXForm);
8469 fschmid 1211
                                        PutDoc("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1\n");
1212
                                        PutDoc("/BBox [ "+FToStr(np.x())+" "+FToStr(-np.y())+" "+FToStr(np1.x())+ " "+FToStr(-np1.y())+" ]\n");
1213
                                        PutDoc("/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
1214
                                        PutDoc(">>\n");
11317 jghali 1215
                                        if (Options.Compress)
8469 fschmid 1216
                                                fon = CompressStr(&fon);
1217
                                        PutDoc("/Length "+QString::number(fon.length()+1));
11317 jghali 1218
                                        if (Options.Compress)
8469 fschmid 1219
                                                PutDoc("\n/Filter /FlateDecode");
12080 avox 1220
                                        PutDoc(" >>\nstream\n"+EncStream(fon, fontGlyphXForm)+"\nendstream\nendobj\n");
1221
                                        Seite.XObjects[AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+QString::number(ig.key())] = fontGlyphXForm;
5606 fschmid 1222
                                }
3133 fschmid 1223
                        }
1224
                }
1225
                else
1226
                {
4229 craig 1227
                        UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
12080 avox 1228
                        uint embeddedFontObject = 0;
5980 avox 1229
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1230
                        {
3829 cbradney 1231
                                QString fon("");
12080 avox 1232
                                embeddedFontObject = newObject();
1233
                                StartObj(embeddedFontObject);
3133 fschmid 1234
                                QByteArray bb;
5980 avox 1235
                                AllFonts[it.key()].RawData(bb);
8559 subik 1236
                                int posi;
3133 fschmid 1237
                                for (posi = 6; posi < bb.size(); ++posi)
1238
                                {
1239
                                        if ((bb[posi] == static_cast<char>(0x80)) && (static_cast<int>(bb[posi+1]) == 2))
1240
                                                break;
1241
                                        fon += QChar(bb[posi]);
1242
                                }
1243
                                int len1 = fon.length();
8559 subik 1244
                                int ulen;
3133 fschmid 1245
                                ulen = bb[posi+2] & 0xff;
1246
                                ulen |= (bb[posi+3] << 8) & 0xff00;
1247
                                ulen |= (bb[posi+4] << 16) & 0xff0000;
1248
                                ulen |= (bb[posi+5] << 24) & 0xff000000;
1249
                                if (ulen > bb.size())
1250
                                        ulen = bb.size()-7;
1251
                                posi += 6;
8559 subik 1252
                                for (int j = 0; j < ulen; ++j)
3133 fschmid 1253
                                        fon += QChar(bb[posi++]);
1254
                                posi += 6;
1255
                                int len2 = fon.length()-len1;
8559 subik 1256
                                for (int j = posi; j < bb.size(); ++j)
3133 fschmid 1257
                                {
1258
                                        if ((bb[j] == static_cast<char>(0x80)) && (static_cast<int>(bb[j+1]) == 3))
1259
                                                break;
1260
                                        if (bb[j] == '\r')
1261
                                                fon += "\n";
1262
                                        else
1263
                                                fon += QChar(bb[j]);
1264
                                }
1265
                                int len3 = fon.length()-len2-len1;
11317 jghali 1266
                                if (Options.Compress)
3133 fschmid 1267
                                        fon = CompressStr(&fon);
4229 craig 1268
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
1269
                                PutDoc("/Length1 "+QString::number(len1)+"\n");
1270
                                PutDoc("/Length2 "+QString::number(len2)+"\n");
1271
                                PutDoc("/Length3 "+QString::number(len3)+"\n");
11317 jghali 1272
                                if (Options.Compress)
3133 fschmid 1273
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1274
                                PutDoc(">>\nstream\n"+EncStream(fon,embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1275
                        }
5980 avox 1276
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1277
                        {
3829 cbradney 1278
                                QString fon("");
1279
                                QString fon2("");
1280
                                QString tm("");
3133 fschmid 1281
                                uint value;
1282
                                bool ok = true;
12080 avox 1283
                                embeddedFontObject = newObject();
1284
                                StartObj(embeddedFontObject);
5980 avox 1285
                                AllFonts[it.key()].EmbedFont(fon);
10469 cbradney 1286
                                int len1 = fon.indexOf("eexec")+5;
3133 fschmid 1287
                                fon2 = fon.left(len1)+"\n";
10469 cbradney 1288
                                int len2 = fon.indexOf("0000000000000000000000000");
3133 fschmid 1289
                                if (len2 == -1)
1290
                                        len2 = fon.length()+1;
1291
                                int count = 0;
1292
                                for (int xx = len1; xx < len2-1; ++xx)
1293
                                {
1294
                                        tm = fon.at(xx);
1295
                                        if ((tm == QChar(13)) || (tm == QChar(10)))
1296
                                                continue;
1297
                                        xx++;
1298
                                        count++;
1299
                                        tm += fon.at(xx);
1300
                                        value = tm.toUInt(&ok, 16);
1301
                                        fon2 += QChar(value);
1302
                                }
1303
                                fon2 += fon.mid(len2);
11317 jghali 1304
                                if (Options.Compress)
3133 fschmid 1305
                                        fon2 = CompressStr(&fon2);
4229 craig 1306
                                PutDoc("<<\n/Length "+QString::number(fon2.length()+1)+"\n");
1307
                                PutDoc("/Length1 "+QString::number(len1+1)+"\n");
1308
                                PutDoc("/Length2 "+QString::number(count)+"\n");
1309
                                PutDoc(static_cast<int>(fon.length()-len2) == -1 ? QString("/Length3 0\n") : "/Length3 "+QString::number(fon.length()-len2)+"\n");
11317 jghali 1310
                                if (Options.Compress)
3133 fschmid 1311
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1312
                                PutDoc(">>\nstream\n"+EncStream(fon2, embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1313
                        }
5980 avox 1314
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1315
                        {
3829 cbradney 1316
                                QString fon("");
12080 avox 1317
                                embeddedFontObject = newObject();
1318
                                StartObj(embeddedFontObject);
3133 fschmid 1319
                                QByteArray bb;
5980 avox 1320
                                AllFonts[it.key()].RawData(bb);
3133 fschmid 1321
                                //AV: += and append() dont't work because they stop at '\0' :-(
8559 subik 1322
                                for (int i=0; i < bb.size(); i++)
3133 fschmid 1323
                                        fon += QChar(bb[i]);
1324
                                int len = fon.length();
11317 jghali 1325
                                if (Options.Compress)
3133 fschmid 1326
                                        fon = CompressStr(&fon);
13085 jghali 1327
                                //qDebug() << QString("sfnt data: size=%1 before=%2 compressed=%3").arg(bb.size()).arg(len).arg(fon.length());
4229 craig 1328
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
1329
                                PutDoc("/Length1 "+QString::number(len)+"\n");
11317 jghali 1330
                                if (Options.Compress)
3133 fschmid 1331
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1332
                                PutDoc(">>\nstream\n"+EncStream(fon, embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1333
                        }
12080 avox 1334
                        uint fontDescriptor = newObject();
1335
                        StartObj(fontDescriptor);
5387 avox 1336
                        // TODO: think about QByteArray ScFace::getFontDescriptor() -- AV
3133 fschmid 1337
                        PutDoc("<<\n/Type /FontDescriptor\n");
5980 avox 1338
                        PutDoc("/FontName /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
6213 fschmid 1339
                        PutDoc("/FontBBox [ "+AllFonts[it.key()].FontBBoxAsString()+" ]\n");
3133 fschmid 1340
                        PutDoc("/Flags ");
5980 avox 1341
                        //FIXME: isItalic() should be queried from ScFace, not from Qt -- AV
3544 avox 1342
                        //QFontInfo fo = QFontInfo(it.data());
3133 fschmid 1343
                        int pfl = 0;
5980 avox 1344
                        if (AllFonts[it.key()].isFixedPitch())
3133 fschmid 1345
                                pfl = pfl ^ 1;
3544 avox 1346
                        //if (fo.italic())
6213 fschmid 1347
                        if (AllFonts[it.key()].ItalicAngleAsString() != "0")
3133 fschmid 1348
                                pfl = pfl ^ 64;
1349
//                      pfl = pfl ^ 4;
1350
                        pfl = pfl ^ 32;
4229 craig 1351
                        PutDoc(QString::number(pfl)+"\n");
6213 fschmid 1352
                        PutDoc("/Ascent "+AllFonts[it.key()].ascentAsString()+"\n");
1353
                        PutDoc("/Descent "+AllFonts[it.key()].descentAsString()+"\n");
1354
                        PutDoc("/CapHeight "+AllFonts[it.key()].capHeightAsString()+"\n");
1355
                        PutDoc("/ItalicAngle "+AllFonts[it.key()].ItalicAngleAsString()+"\n");
1356
//                      PutDoc("/Ascent "+QString::number(static_cast<int>(AllFonts[it.key()].ascent()))+"\n");
1357
//                      PutDoc("/Descent "+QString::number(static_cast<int>(AllFonts[it.key()].descent()))+"\n");
1358
//                      PutDoc("/CapHeight "+QString::number(static_cast<int>(AllFonts[it.key()].capHeight()))+"\n");
1359
//                      PutDoc("/ItalicAngle "+AllFonts[it.key()].italicAngle()+"\n");
1360
//                      PutDoc("/StemV "+ AllFonts[it.key()].stemV() + "\n");
1361
                        PutDoc("/StemV 1\n");
5980 avox 1362
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
12080 avox 1363
                                PutDoc("/FontFile2 "+QString::number(embeddedFontObject)+" 0 R\n");
5980 avox 1364
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
12080 avox 1365
                                PutDoc("/FontFile "+QString::number(embeddedFontObject)+" 0 R\n");
5980 avox 1366
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
12080 avox 1367
                                PutDoc("/FontFile "+QString::number(embeddedFontObject)+" 0 R\n");
3133 fschmid 1368
                        PutDoc(">>\nendobj\n");
4546 subik 1369
/*                      if (!FT_Has_PS_Glyph_Names(AllFonts[it.key()])
3133 fschmid 1370
                        {
1371
                                StartObj(ObjCounter);
1372
                                int chCount = 31;
1373
                                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 ");
1374
                                for (int ww = 31; ww < 256; ++ww)
1375
                                {
4229 craig 1376
                                        PutDoc(QString::number(static_cast<int>(AllFonts[it.key()]->CharWidth[itg.key()]*
3133 fschmid 1377
                                                        1000))+" ");
1378
                                        if (itg == gl.end())
1379
                                                break;
1380
                                        ++itg;
1381
                                        chCount++;
1382
                                }
1383
                                PutDoc("]\nendobj\n");
1384
                                ObjCounter++;
1385
                                // put widths object
1386
                                // encoding dictionary w/ base encoding w/o differences
1387
                                StartObj(ObjCounter);
1388
                                PutDoc("<<\n/Type /Font\n/Subtype ");
5980 avox 1389
                                PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
4229 craig 1390
                                PutDoc("/Name /Fo"+QString::number(a)+"\n");
5980 avox 1391
                                PutDoc("/BaseFont /"+AllFonts[it.key()]->psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "" )+"\n");
3133 fschmid 1392
                                //cf. widths:
1393
                                PutDoc("/FirstChar 0\n");
4229 craig 1394
                                PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
1395
                                PutDoc("/Widths "+QString::number(ObjCounter-1)+" 0 R\n");
1396
                                PutDoc("/FontDescriptor "+QString::number(ObjCounter-2)+" 0 R\n");
3133 fschmid 1397
                                PutDoc(">>\nendobj\n");
4229 craig 1398
                                Seite.FObjects["Fo"+QString::number(a)] = ObjCounter;
3133 fschmid 1399
                                ObjCounter++;
1400
                        }
1401
                        else */
1402
//                      {
6301 avox 1403
                                QMap<uint,std::pair<QChar,QString> > gl;
1404
                                AllFonts[it.key()].glyphNames(gl);
1405
                                int nglyphs = 0;
1406
                                QMap<uint,std::pair<QChar,QString> >::Iterator gli;
8092 fschmid 1407
                                for (gli = gl.begin(); gli != gl.end(); ++gli)
1408
                                {
7328 fschmid 1409
                                        if (gli.key() > static_cast<uint>(nglyphs))
6301 avox 1410
                                                nglyphs = gli.key();
1411
                                }
1412
                                ++nglyphs;
13085 jghali 1413
//                              qDebug() << QString("pdflib: nglyphs %1 max %2").arg(nglyphs).arg(AllFonts[it.key()].maxGlyph());
12080 avox 1414
                                uint FontDes = fontDescriptor;
6301 avox 1415
                                uint Fcc = nglyphs / 224;
1416
                                if ((nglyphs % 224) != 0)
3133 fschmid 1417
                                        Fcc += 1;
1418
                                for (uint Fc = 0; Fc < Fcc; ++Fc)
1419
                                {
12080 avox 1420
                                        uint fontWidths2 = newObject();
1421
                                        StartObj(fontWidths2);
6301 avox 1422
                                        int chCount = 32;
1423
                                        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 ");
1424
                                        for (int ww = 32; ww < 256; ++ww)
3133 fschmid 1425
                                        {
6301 avox 1426
                                                uint glyph = 224 * Fc + ww - 32;
1427
                                                if (gl.contains(glyph))
1428
                                                        PutDoc(QString::number(static_cast<int>(AllFonts[it.key()].glyphWidth(glyph)* 1000))+" ");
1429
                                                else
1430
                                                        PutDoc("0 ");
6302 avox 1431
                                                chCount++;
6301 avox 1432
                                                if (signed(glyph) == nglyphs-1)
3133 fschmid 1433
                                                        break;
1434
                                        }
1435
                                        PutDoc("]\nendobj\n");
12080 avox 1436
                                        uint fontEncoding2 = newObject();
1437
                                        StartObj(fontEncoding2);
8147 fschmid 1438
                                        QStringList toUnicodeMaps;
9803 fschmid 1439
                                        QList<int> toUnicodeMapsCount;
8136 fschmid 1440
                                        QString toUnicodeMap = "";
1441
                                        int toUnicodeMapCounter = 0;
3133 fschmid 1442
                                        PutDoc("<< /Type /Encoding\n");
6301 avox 1443
                                        PutDoc("/Differences [ \n");
3133 fschmid 1444
                                        int crc = 0;
6301 avox 1445
                                        bool startOfSeq = true;
3133 fschmid 1446
                                        for (int ww2 = 32; ww2 < 256; ++ww2)
1447
                                        {
6301 avox 1448
                                                uint glyph = 224 * Fc + ww2 - 32;
11113 jghali 1449
                                                QMap<uint,std::pair<QChar,QString> >::Iterator glIt = gl.find(glyph);
1450
                                                if (glIt != gl.end() && !glIt.value().second.isEmpty())
6213 fschmid 1451
                                                {
8092 fschmid 1452
                                                        if (startOfSeq)
1453
                                                        {
6301 avox 1454
                                                                PutDoc(QString::number(ww2)+" ");
1455
                                                                startOfSeq = false;
1456
                                                        }
11113 jghali 1457
                                                        PutDoc("/"+glIt.value().second+" ");
8136 fschmid 1458
                                                        QString tmp, tmp2;
1459
                                                        tmp.sprintf("%02X", ww2);
11113 jghali 1460
                                                        tmp2.sprintf("%04X", glIt.value().first.unicode());
8136 fschmid 1461
                                                        toUnicodeMap += QString("<%1> <%2>\n").arg(tmp).arg((tmp2));
1462
                                                        toUnicodeMapCounter++;
8147 fschmid 1463
                                                        if (toUnicodeMapCounter == 100)
1464
                                                        {
1465
                                                                toUnicodeMaps.append(toUnicodeMap);
1466
                                                                toUnicodeMapsCount.append(toUnicodeMapCounter);
1467
                                                                toUnicodeMap = "";
1468
                                                                toUnicodeMapCounter = 0;
1469
                                                        }
6301 avox 1470
                                                        crc++;
6213 fschmid 1471
                                                }
8092 fschmid 1472
                                                else
1473
                                                {
6301 avox 1474
                                                        startOfSeq = true;
1475
                                                }
1476
                                                if (signed(glyph) == nglyphs-1)
3133 fschmid 1477
                                                        break;
1478
                                                if (crc > 8)
1479
                                                {
1480
                                                        PutDoc("\n");
1481
                                                        crc = 0;
1482
                                                }
1483
                                        }
8147 fschmid 1484
                                        if (toUnicodeMapCounter != 0)
1485
                                        {
1486
                                                toUnicodeMaps.append(toUnicodeMap);
1487
                                                toUnicodeMapsCount.append(toUnicodeMapCounter);
1488
                                        }
3133 fschmid 1489
                                        PutDoc("]\n");
1490
                                        PutDoc(">>\nendobj\n");
8136 fschmid 1491
                                        QString toUnicodeMapStream = "";
1492
                                        toUnicodeMapStream += "/CIDInit /ProcSet findresource begin\n";
1493
                                        toUnicodeMapStream += "12 dict begin\n";
1494
                                        toUnicodeMapStream += "begincmap\n";
1495
                                        toUnicodeMapStream += "/CIDSystemInfo <<\n";
1496
                                        toUnicodeMapStream += "/Registry (Adobe)\n";
1497
                                        toUnicodeMapStream += "/Ordering (UCS)\n";
1498
                                        toUnicodeMapStream += "/Supplement 0\n";
1499
                                        toUnicodeMapStream += ">> def\n";
1500
                                        toUnicodeMapStream += "/CMapName /Adobe-Identity-UCS def\n";
1501
                                        toUnicodeMapStream += "/CMapType 2 def\n";
1502
                                        toUnicodeMapStream += "1 begincodespacerange\n";
8147 fschmid 1503
                                        toUnicodeMapStream += "<0000> <FFFF>\n";
8136 fschmid 1504
                                        toUnicodeMapStream += "endcodespacerange\n";
8559 subik 1505
                                        for (int uniC = 0; uniC < toUnicodeMaps.count(); uniC++)
8147 fschmid 1506
                                        {
1507
                                                toUnicodeMapStream += QString("%1 beginbfchar\n").arg(toUnicodeMapsCount[uniC]);
1508
                                                toUnicodeMapStream += toUnicodeMaps[uniC];
1509
                                                toUnicodeMapStream += "endbfchar\n";
1510
                                        }
8136 fschmid 1511
                                        toUnicodeMapStream += "endcmap\n";
1512
                                        toUnicodeMapStream += "CMapName currentdict /CMap defineresource pop\n";
1513
                                        toUnicodeMapStream += "end\n";
1514
                                        toUnicodeMapStream += "end\n";
12906 jghali 1515
                                        uint fontToUnicode2 = WritePDFStream(toUnicodeMapStream);
12080 avox 1516
                                        uint fontObject2 = newObject();
1517
                                        StartObj(fontObject2);
3133 fschmid 1518
                                        PutDoc("<<\n/Type /Font\n/Subtype ");
5980 avox 1519
                                        PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
4229 craig 1520
                                        PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(Fc)+"\n");
5980 avox 1521
                                        PutDoc("/BaseFont /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
3133 fschmid 1522
                                        PutDoc("/FirstChar 0\n");
4229 craig 1523
                                        PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
12080 avox 1524
                                        PutDoc("/Widths "+QString::number(fontWidths2)+" 0 R\n");
1525
                                        PutDoc("/Encoding "+QString::number(fontEncoding2)+" 0 R\n");
1526
                                        PutDoc("/ToUnicode "+QString::number(fontToUnicode2)+" 0 R\n");
4229 craig 1527
                                        PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
3133 fschmid 1528
                                        PutDoc(">>\nendobj\n");
12080 avox 1529
                                        Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(Fc)] = fontObject2;
3133 fschmid 1530
                                } // for(Fc)
12080 avox 1531
                                uint fontWidthsForm = newObject();
1532
                                StartObj(fontWidthsForm);
8101 fschmid 1533
                                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 ");
1534
                                for (int ww = 32; ww < 256; ++ww)
1535
                                {
1536
                                        uint glyph = AllFonts[it.key()].char2CMap(QChar(ww));
1537
                                        if (gl.contains(glyph))
1538
                                                PutDoc(QString::number(static_cast<int>(AllFonts[it.key()].glyphWidth(glyph)* 1000))+" ");
1539
                                        else
1540
                                                PutDoc("0 ");
1541
                                }
1542
                                PutDoc("]\nendobj\n");
12080 avox 1543
                                uint fontObjectForm = newObject();
1544
                                StartObj(fontObjectForm);
8101 fschmid 1545
                                PutDoc("<<\n/Type /Font\n/Subtype ");
1546
                                PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
8454 fschmid 1547
//                              if (fformat == ScFace::SFNT || fformat == ScFace::TTCF)
1548
//                              {
1549
//                                      PutDoc("/TrueType\n");
1550
                                        PutDoc("/Name /Fo"+QString::number(a)+"Form"+"\n");
12080 avox 1551
                                        Seite.FObjects["Fo"+QString::number(a)+"Form"] = fontObjectForm;
8454 fschmid 1552
                                        UsedFontsF.insert(it.key(), "/Fo"+QString::number(a)+"Form");
1553
/*                              }
1554
                                else
1555
                                {
1556
                                        PutDoc("/Type1\n");
1557
                                        PutDoc("/Name /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1558
                                        Seite.FObjects[AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )] = ObjCounter;
1559
                                        UsedFontsF.insert(it.key(), "/"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ));
1560
                                } */
8101 fschmid 1561
                                PutDoc("/BaseFont /"+AllFonts[it.key()].psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
8432 fschmid 1562
                                PutDoc("/Encoding << \n");
1563
                                PutDoc("/Differences [ \n");
1564
                                PutDoc("24 /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde\n");
1565
                                PutDoc("39 /quotesingle 96 /grave 128 /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction /guilsinglleft /guilsinglright\n");
1566
                                PutDoc("/minus /perthousand /quotedblbase /quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron\n");
1567
                                PutDoc("/Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron 164 /currency 166 /brokenbar 168 /dieresis /copyright /ordfeminine 172 /logicalnot\n");
1568
                                PutDoc("/.notdef /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu 183 /periodcentered /cedilla /onesuperior /ordmasculine\n");
1569
                                PutDoc("188 /onequarter /onehalf /threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex\n");
1570
                                PutDoc("/Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n");
1571
                                PutDoc("/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n");
1572
                                PutDoc("/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis\n");
1573
                                PutDoc("/divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis\n");
1574
                                PutDoc("] >>\n");
8101 fschmid 1575
                                PutDoc("/FirstChar 0\n");
1576
                                PutDoc("/LastChar 255\n");
12080 avox 1577
                                PutDoc("/Widths "+QString::number(fontWidthsForm)+" 0 R\n");
8101 fschmid 1578
                                PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
1579
                                PutDoc(">>\nendobj\n");
3133 fschmid 1580
//                      } // FT_Has_PS_Glyph_Names
1581
                }
1582
                a++;
1583
        }
4264 craig 1584
        if (Options.UseLPI)
3133 fschmid 1585
        {
12080 avox 1586
                uint halftones = newObject();
1587
                StartObj(halftones);
3133 fschmid 1588
                PutDoc("<<\n/Type /Halftone\n/HalftoneType 5\n");
4264 craig 1589
                QMap<QString,LPIData>::const_iterator itlp;
1590
                for (itlp = Options.LPISettings.constBegin(); itlp != Options.LPISettings.constEnd(); ++itlp)
3133 fschmid 1591
                {
1592
                        PutDoc("/"+itlp.key()+"\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency ");
10469 cbradney 1593
                        PutDoc(QString::number(itlp.value().Frequency)+"\n/Angle "+QString::number(itlp.value().Angle)+"\n/SpotFunction ");
3829 cbradney 1594
                        QString func ("");
10469 cbradney 1595
                        switch (itlp.value().SpotFunc)
3133 fschmid 1596
                        {
1597
                                case 0:
1598
                                        func = "/SimpleDot";
1599
                                        break;
1600
                                case 1:
1601
                                        func = "/Line";
1602
                                        break;
1603
                                case 2:
1604
                                        func = "/Round";
1605
                                        break;
1606
                                case 3:
1607
                                        func = "/Ellipse";
1608
                                        break;
1609
                                default:
1610
                                        func = "/SimpleDot";
1611
                                        break;
1612
                        }
1613
                        PutDoc(func+"\n>>\n");
1614
                }
1615
                PutDoc("/Default\n<<\n/Type /Halftone\n/HalftoneType 1\n/Frequency 50\n/Angle 45\n/SpotFunction /Round\n>>\n");
1616
                PutDoc(">>\nendobj\n");
4229 craig 1617
                HTName = ResNam+QString::number(ResCount);
12080 avox 1618
                Transpar[HTName] = writeGState("/HT "+QString::number(halftones)+" 0 R\n");
3133 fschmid 1619
                ResCount++;
1620
        }
5880 jghali 1621
        if ((doc.HasCMS) && (Options.UseProfiles))
3133 fschmid 1622
        {
12080 avox 1623
                uint iccProfileObject = newObject();
1624
                StartObj(iccProfileObject);
7144 jghali 1625
                QByteArray dataP;
3133 fschmid 1626
                struct ICCD dataD;
7144 jghali 1627
                loadRawBytes(ScCore->InputProfiles[Options.SolidProf], dataP);
3133 fschmid 1628
                PutDoc("<<\n");
11317 jghali 1629
                if (Options.Compress)
3133 fschmid 1630
                {
11317 jghali 1631
                        QByteArray compData = CompressArray(dataP);
1632
                        if (compData.size() > 0)
1633
                        {
1634
                                PutDoc("/Filter /FlateDecode\n");
1635
                                dataP = compData;
1636
                        }
3133 fschmid 1637
                }
7144 jghali 1638
                PutDoc("/Length "+QString::number(dataP.size()+1)+"\n");
4264 craig 1639
                PutDoc("/N "+QString::number(Options.SComp)+"\n");
7144 jghali 1640
                PutDoc(">>\nstream\n");
12080 avox 1641
                EncodeArrayToStream(dataP, iccProfileObject);
7144 jghali 1642
                PutDoc("\nendstream\nendobj\n");
12080 avox 1643
                uint iccColorspace = newObject();
1644
                StartObj(iccColorspace);
4229 craig 1645
                dataD.ResName = ResNam+QString::number(ResCount);
12080 avox 1646
                dataD.ICCArray = "[ /ICCBased "+QString::number(iccProfileObject)+" 0 R ]";
1647
                dataD.ResNum = iccColorspace;
12732 fschmid 1648
                dataD.components = Options.SComp;
4264 craig 1649
                ICCProfiles[Options.SolidProf] = dataD;
12080 avox 1650
                PutDoc("[ /ICCBased "+QString::number(iccProfileObject)+" 0 R ]\n");
3133 fschmid 1651
                PutDoc("endobj\n");
1652
                ResCount++;
1653
        }
4264 craig 1654
        if (((Options.isGrayscale == false) && (Options.UseRGB == false)) && (Options.UseSpotColors))
3133 fschmid 1655
        {
4264 craig 1656
                doc.getUsedColors(colorsToUse);
3133 fschmid 1657
                ColorList::Iterator itf;
1658
                for (itf = colorsToUse.begin(); itf != colorsToUse.end(); ++itf)
1659
                {
1660
                        if ((colorsToUse[itf.key()].isSpotColor()) || (colorsToUse[itf.key()].isRegistrationColor()))
1661
                        {
9619 jghali 1662
                                CMYKColor cmykValues;
3133 fschmid 1663
                                int cc, cm, cy, ck;
1664
                                struct SpotC spotD;
9619 jghali 1665
                                ScColorEngine::getCMYKValues(colorsToUse[itf.key()], &doc, cmykValues);
1666
                                cmykValues.getValues(cc, cm, cy, ck);
3133 fschmid 1667
                                QString colorDesc = "{\ndup "+FToStr(static_cast<double>(cc) / 255)+"\nmul exch dup ";
1668
                                colorDesc += FToStr(static_cast<double>(cm) / 255)+"\nmul exch dup ";
1669
                                colorDesc += FToStr(static_cast<double>(cy) / 255)+"\nmul exch ";
1670
                                colorDesc += FToStr(static_cast<double>(ck) / 255)+" mul }";
12080 avox 1671
                                uint separationFunction = newObject();
1672
                                StartObj(separationFunction);
3133 fschmid 1673
                                PutDoc("<<\n/FunctionType 4\n");
1674
                                PutDoc("/Domain [0.0 1.0]\n");
1675
                                PutDoc("/Range [0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]\n");
4229 craig 1676
                                PutDoc("/Length "+QString::number(colorDesc.length()+1)+"\n");
12080 avox 1677
                                PutDoc(">>\nstream\n"+EncStream(colorDesc, separationFunction)+"\nendstream\nendobj\n");
1678
                                uint separationColorspace= newObject();
1679
                                StartObj(separationColorspace);
3133 fschmid 1680
                                PutDoc("[ /Separation /");
1681
                                if (colorsToUse[itf.key()].isRegistrationColor())
1682
                                        PutDoc("All");
1683
                                else
10394 cbradney 1684
                                        PutDoc(itf.key().simplified().replace("#", "#23").replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "#20" ));
12080 avox 1685
                                PutDoc(" /DeviceCMYK "+QString::number(separationFunction)+" 0 R ]\nendobj\n");
4229 craig 1686
                                spotD.ResName = spotNam+QString::number(spotCount);
12080 avox 1687
                                spotD.ResNum = separationColorspace;
3133 fschmid 1688
                                spotMap.insert(itf.key(), spotD);
1689
                                spotCount++;
1690
                        }
1691
                }
1692
        }
6925 fschmid 1693
        if ((Options.cropMarks) || (Options.bleedMarks) || (Options.registrationMarks) || (Options.colorMarks) || (Options.docInfoMarks))
1694
        {
1695
                struct SpotC spotD;
12080 avox 1696
                uint registrationColorspace = newObject();
1697
                StartObj(registrationColorspace);
6925 fschmid 1698
                PutDoc("[ /Separation /All /DeviceCMYK\n");
1699
                PutDoc("<<\n/FunctionType 2\n");
1700
                PutDoc("/Domain [0.0 1.0]\n");
1701
                PutDoc("/Range [0.0 1.0 0.0 1.0 0.0 1.0 0.0 1.0]\n");
1702
                PutDoc("/C0 [0 0 0 0] \n");
1703
                PutDoc("/C1 [1 1 1 1] \n");
1704
                PutDoc("/N 1\n");
1705
                PutDoc(">>\n]\nendobj\n");
1706
                spotD.ResName = spotNam+QString::number(spotCount);
12080 avox 1707
                spotD.ResNum = registrationColorspace;
6925 fschmid 1708
                spotMapReg.insert("Register", spotD);
1709
                spotCount++;
1710
        }
12884 jghali 1711
        if ((Options.Version == PDFOptions::PDFVersion_15) && (Options.useLayers))
3133 fschmid 1712
        {
10140 jghali 1713
                ScLayer ll;
3133 fschmid 1714
                struct OCGInfo ocg;
1715
                ll.isPrintable = false;
1716
                ll.LNr = 0;
1717
                int Lnr = 0;
3829 cbradney 1718
                QString ocgNam("oc");
4264 craig 1719
                uint docLayersCount=doc.Layers.count();
3829 cbradney 1720
                for (uint la = 0; la < docLayersCount; ++la)
3133 fschmid 1721
                {
12080 avox 1722
                        uint optionalContent = newObject();
3829 cbradney 1723
                        QString tmp("");
10140 jghali 1724
                        doc.Layers.levelToLayer(ll, Lnr);
3133 fschmid 1725
                        ocg.Name = ocgNam+tmp.setNum(ll.LNr);
12080 avox 1726
                        ocg.ObjNum = optionalContent;
3133 fschmid 1727
                        ocg.visible = ll.isViewable;
1728
                        OCGEntries.insert(ll.Name, ocg);
12080 avox 1729
                        StartObj(optionalContent);
3133 fschmid 1730
                        PutDoc("<<\n");
1731
                        PutDoc("/Type /OCG\n");
7328 fschmid 1732
                        PutDoc("/Name ");
12080 avox 1733
                        PutDoc(EncStringUTF16("("+ll.Name+")", optionalContent));
7328 fschmid 1734
                        PutDoc("\n");
11908 fschmid 1735
                        PutDoc("/Usage <</Print <</PrintState ");
1736
                        if (ll.isPrintable)
1737
                                PutDoc("/ON");
1738
                        else
1739
                                PutDoc("/OFF");
1740
                        PutDoc(">> /View <</ViewState ");
1741
                        if (ll.isViewable)
1742
                                PutDoc("/ON");
1743
                        else
1744
                                PutDoc("/OFF");
1745
                        PutDoc(">>>>>>");
1746
                        PutDoc("\n");
3133 fschmid 1747
                        PutDoc(">>\nendobj\n");
1748
                        Lnr++;
1749
                }
1750
        }
1751
        return true;
1752
}
1753
 
11060 jghali 1754
bool PDFLibCore::PDF_TemplatePage(const Page* pag, bool )
3133 fschmid 1755
{
11060 jghali 1756
        QString tmp, tmpOut;
3133 fschmid 1757
        ActPageP = pag;
1758
        PageItem* ite;
9856 fschmid 1759
        QList<PageItem*> PItems;
3133 fschmid 1760
        int Lnr = 0;
10140 jghali 1761
        ScLayer ll;
3133 fschmid 1762
        ll.isPrintable = false;
1763
        ll.LNr = 0;
11060 jghali 1764
        Content = "";
3133 fschmid 1765
        Seite.AObjects.clear();
8559 subik 1766
        for (int la = 0; la < doc.Layers.count(); ++la)
3133 fschmid 1767
        {
10140 jghali 1768
                doc.Layers.levelToLayer(ll, Lnr);
4264 craig 1769
                PItems = doc.MasterItems;
12884 jghali 1770
                if ((ll.isPrintable) || ((Options.Version == PDFOptions::PDFVersion_15) && (Options.useLayers)))
3133 fschmid 1771
                {
12884 jghali 1772
                        if ((Options.Version == PDFOptions::PDFVersion_15) && (Options.useLayers))
3133 fschmid 1773
                                PutPage("/OC /"+OCGEntries[ll.Name].Name+" BDC\n");
9856 fschmid 1774
                        for (int a = 0; a < PItems.count(); ++a)
3133 fschmid 1775
                        {
11060 jghali 1776
                                Content = "";
3133 fschmid 1777
                                ite =PItems.at(a);
1778
                                if (ite->LayerNr != ll.LNr)
1779
                                        continue;
4726 fschmid 1780
                                double x = pag->xOffset();
1781
                                double y = pag->yOffset();
1782
                                double w = pag->width();
1783
                                double h1 = pag->height();
4580 cbradney 1784
                                double ilw=ite->lineWidth();
4726 fschmid 1785
                                double x2 = ite->BoundingX - ilw / 2.0;
1786
                                double y2 = ite->BoundingY - ilw / 2.0;
1787
                                double w2 = ite->BoundingW + ilw;
1788
                                double h2 = ite->BoundingH + ilw;
8562 jghali 1789
                                if (!( qMax( x, x2 ) <= qMin( x+w, x2+w2 ) && qMax( y, y2 ) <= qMin( y+h1, y2+h2 )))
3133 fschmid 1790
                                        continue;
1791
                                if (ite->ChangedMasterItem)
1792
                                        continue;
5685 cbradney 1793
                                if ((!pag->pageName().isEmpty()) && (ite->OwnPage != static_cast<int>(pag->pageNr())) && (ite->OwnPage != -1))
3133 fschmid 1794
                                        continue;
1795
                                PutPage("q\n");
12589 fschmid 1796
                                if ((ite->doOverprint) && (!Options.UseRGB))
5320 fschmid 1797
                                {
1798
                                        QString ShName = ResNam+QString::number(ResCount);
1799
                                        ResCount++;
12080 avox 1800
                                        Transpar[ShName] = writeGState("/OP true\n"
1801
                                                                                                   "/op true\n"
1802
                                                                                                   "/OPM 1\n");
5320 fschmid 1803
                                        PutPage("/"+ShName+" gs\n");
1804
                                }
4679 fschmid 1805
/* Bookmarks on Master Pages do not make any sense */
1806
//                              if ((ite->isBookmark) && (Options.Bookmarks))
1807
//                                      PDF_Bookmark(ite, pag->height() - (ite->yPos() - pag->yOffset()));
5685 cbradney 1808
                                if (!ite->printEnabled() || ((ite->itemType() == PageItem::TextFrame) && (!pag->pageName().isEmpty()))