Subversion Repositories Scribus

Rev

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