Subversion Repositories Scribus

Rev

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

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