Subversion Repositories Scribus

Rev

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