Subversion Repositories Scribus

Rev

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

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