Subversion Repositories Scribus

Rev

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