Subversion Repositories Scribus

Rev

Rev 12700 | Rev 12763 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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