Subversion Repositories Scribus

Rev

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

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