Subversion Repositories Scribus

Rev

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