Subversion Repositories Scribus

Rev

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