Subversion Repositories Scribus

Rev

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

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