Subversion Repositories Scribus

Rev

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