Subversion Repositories Scribus

Rev

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