Subversion Repositories Scribus

Rev

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