Subversion Repositories Scribus

Rev

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

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