Subversion Repositories Scribus

Rev

Rev 17635 | Rev 17758 | 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
 
17539 jghali 28
#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
14170 jghali 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"
17312 fschmid 65
#include "pageitem_table.h"
10212 cbradney 66
#include "pdfoptions.h"
67
#include "prefscontext.h"
68
#include "prefsmanager.h"
69
#include "sccolor.h"
70
#include "sccolorengine.h"
71
#include "scfonts.h"
16736 jghali 72
#include "scpage.h"
5917 jghali 73
#include "scpaths.h"
10212 cbradney 74
#include "scpattern.h"
3133 fschmid 75
#include "scribus.h"
5243 cbradney 76
#include "scribuscore.h"
3699 cbradney 77
#include "scribusdoc.h"
11599 jghali 78
#include "scstreamfilter_flate.h"
79
#include "scstreamfilter_rc4.h"
17312 fschmid 80
#include "tableutils.h"
10212 cbradney 81
#include "text/nlsconfig.h"
3133 fschmid 82
#include "util.h"
11605 jghali 83
#include "util_file.h"
10212 cbradney 84
#include "util_formats.h"
10203 cbradney 85
#include "util_math.h"
12517 fschmid 86
#include "util_ghostscript.h"
16736 jghali 87
 
13839 fschmid 88
#ifdef HAVE_OSG
14930 fschmid 89
        #include "third_party/prc/exportPRC.h"
13839 fschmid 90
#endif
3133 fschmid 91
 
16736 jghali 92
#include "ui/bookmwin.h"
93
#include "ui/bookmarkpalette.h"
94
#include "ui/multiprogressdialog.h"
95
 
3133 fschmid 96
using namespace std;
17312 fschmid 97
using namespace TableUtils;
3133 fschmid 98
 
12096 jghali 99
#if defined(_WIN32)
100
#undef GetObject
101
#endif
3133 fschmid 102
 
6562 fschmid 103
 
10054 craig 104
PDFLibCore::PDFLibCore(ScribusDoc & docu)
4264 craig 105
        : QObject(&docu),
4223 craig 106
        doc(docu),
107
        ActPageP(0),
14925 cbradney 108
        Options(doc.pdfOptions()),
4223 craig 109
        Bvie(0),
13764 jghali 110
        ucs2Codec(0),
4223 craig 111
        ObjCounter(7),
112
        ResNam("RE"),
113
        ResCount(0),
114
        NDnam("LI"),
115
        NDnum(0),
10553 fschmid 116
        KeyGen(""),
117
        OwnerKey(""),
118
        UserKey(""),
119
        FileID(""),
120
        EncryKey(""),
4223 craig 121
        Encrypt(0),
122
        KeyLen(5),
123
        colorsToUse(),
124
        spotNam("Spot"),
125
        spotCount(0),
4225 craig 126
        progressDialog(0),
4223 craig 127
        abortExport(false),
5243 cbradney 128
        usingGUI(ScCore->usingGUI())
3133 fschmid 129
{
10553 fschmid 130
        KeyGen.resize(32);
131
        OwnerKey.resize(32);
132
        UserKey.resize(32);
133
        FileID.resize(16);
134
        EncryKey.resize(5);
3133 fschmid 135
        Catalog.Outlines = 2;
136
        Catalog.PageTree = 3;
137
        Catalog.Dest = 4;
138
        PageTree.Count = 0;
139
        Outlines.First = 0;
140
        Outlines.Last = 0;
141
        Outlines.Count = 0;
142
        Seite.ObjNum = 0;
143
        Seite.Thumb = 0;
144
        int kg_array[] = {0x28, 0xbf, 0x4e, 0x5e, 0x4e, 0x75, 0x8a, 0x41, 0x64, 0x00, 0x4e, 0x56, 0xff, 0xfa,
145
                          0x01, 0x08, 0x2e, 0x2e, 0x00, 0xb6, 0xd0, 0x68, 0x3e, 0x80, 0x2f, 0x0c, 0xa9, 0xfe,
146
                          0x64, 0x53, 0x69, 0x7a};
147
        for (int a = 0; a < 32; ++a)
148
                KeyGen[a] = kg_array[a];
4028 cbradney 149
        if (usingGUI)
150
        {
10508 cbradney 151
                progressDialog = new MultiProgressDialog( tr("Saving PDF"), CommonStrings::tr_Cancel, doc.scMW());
4224 craig 152
                Q_CHECK_PTR(progressDialog);
153
                QStringList barNames, barTexts;
154
                barNames << "EMP" << "EP" << "ECPI";
5370 cbradney 155
                barTexts << tr("Exporting Master Page:") << tr("Exporting Page:") << tr("Exporting Items on Current Page:");
9803 fschmid 156
                QList<bool> barsNumeric;
5370 cbradney 157
                barsNumeric << true << true << false;
158
                progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
8559 subik 159
                connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
4028 cbradney 160
        }
3133 fschmid 161
}
162
 
10054 craig 163
PDFLibCore::~PDFLibCore()
4224 craig 164
{
165
        delete progressDialog;
166
}
167
 
4229 craig 168
static inline QString FToStr(double c)
169
{
15283 fschmid 170
        double v = c;
171
        if (fabs(c) < 0.0000001)
172
                v = 0.0;
173
        return QString::number(v, 'f', 5);
4229 craig 174
};
175
 
10054 craig 176
bool PDFLibCore::doExport(const QString& fn, const QString& nam, int Components,
4264 craig 177
                                          const std::vector<int> & pageNs, const QMap<int,QPixmap> & thumbs)
3133 fschmid 178
{
179
        QPixmap pm;
11060 jghali 180
        bool ret = false, error = false;
181
        int  pc_exportpages=0;
182
        int  pc_exportmasterpages=0;
4224 craig 183
        if (usingGUI)
184
                progressDialog->show();
5387 avox 185
        QMap<QString, QMap<uint, FPointArray> > usedFonts;
186
        usedFonts.clear();
187
        doc.getUsedFonts(usedFonts);
13764 jghali 188
        ucs2Codec = QTextCodec::codecForName("ISO-10646-UCS-2");
13791 pierre 189
        if(!ucs2Codec)
190
                ucs2Codec = QTextCodec::codecForName("UTF-16");
13764 jghali 191
        if (!ucs2Codec)
192
        {
13791 pierre 193
                PDF_Error( tr("Qt build miss both \"UTF-16\" and \"ISO-10646-UCS-2\" text codecs, pdf export is not possible") );
13764 jghali 194
                return false;
195
        }
13955 cbradney 196
        if (PDF_Begin_Doc(fn, PrefsManager::instance()->appPrefs.fontPrefs.AvailFonts, usedFonts, doc.scMW()->bookmarkPalette->BView))
3133 fschmid 197
        {
198
                QMap<int, int> pageNsMpa;
199
                for (uint a = 0; a < pageNs.size(); ++a)
200
                {
14653 jghali 201
                        pageNsMpa.insert(doc.MasterNames[doc.DocPages.at(pageNs[a]-1)->MPageNam], 0);
3133 fschmid 202
                }
4028 cbradney 203
                if (usingGUI)
3133 fschmid 204
                {
4028 cbradney 205
                        progressDialog->setOverallTotalSteps(pageNsMpa.count()+pageNs.size());
206
                        progressDialog->setTotalSteps("EMP", pageNsMpa.count());
207
                        progressDialog->setTotalSteps("EP", pageNs.size());
208
                        progressDialog->setOverallProgress(0);
209
                        progressDialog->setProgress("EMP", 0);
210
                        progressDialog->setProgress("EP", 0);
211
                }
10018 fschmid 212
                for (int ap = 0; ap < doc.MasterPages.count() && !abortExport; ++ap)
4028 cbradney 213
                {
4264 craig 214
                        if (doc.MasterItems.count() != 0)
3133 fschmid 215
                        {
216
                                if (pageNsMpa.contains(ap))
217
                                {
5243 cbradney 218
                                        qApp->processEvents();
11060 jghali 219
                                        if (!PDF_TemplatePage(doc.MasterPages.at(ap)))
220
                                                error = abortExport = true;
4028 cbradney 221
                                        ++pc_exportmasterpages;
3133 fschmid 222
                                }
223
                        }
4546 subik 224
                        if (usingGUI)
225
                        {
4028 cbradney 226
                                progressDialog->setProgress("EMP", pc_exportmasterpages);
227
                                progressDialog->setOverallProgress(pc_exportmasterpages+pc_exportpages);
228
                        }
3133 fschmid 229
                }
4028 cbradney 230
                for (uint a = 0; a < pageNs.size() && !abortExport; ++a)
3133 fschmid 231
                {
14925 cbradney 232
                        if (doc.pdfOptions().Thumbnails)
3133 fschmid 233
                                pm = thumbs[pageNs[a]];
5243 cbradney 234
                        qApp->processEvents();
4028 cbradney 235
                        if (abortExport) break;
11060 jghali 236
 
14653 jghali 237
                        PDF_Begin_Page(doc.DocPages.at(pageNs[a]-1), pm);
5243 cbradney 238
                        qApp->processEvents();
4028 cbradney 239
                        if (abortExport) break;
11060 jghali 240
 
14925 cbradney 241
                        if (!PDF_ProcessPage(doc.DocPages.at(pageNs[a]-1), pageNs[a]-1, doc.pdfOptions().doClip))
11060 jghali 242
                                error = abortExport = true;
5243 cbradney 243
                        qApp->processEvents();
4028 cbradney 244
                        if (abortExport) break;
11060 jghali 245
 
15444 craig 246
                        PDF_End_Page(a);
4028 cbradney 247
                        pc_exportpages++;
248
                        if (usingGUI)
249
                        {
250
                                progressDialog->setProgress("EP", pc_exportpages);
251
                                progressDialog->setOverallProgress(pc_exportmasterpages+pc_exportpages);
252
                        }
3133 fschmid 253
                }
4028 cbradney 254
                ret = true;//Even when aborting we return true. Dont want that "couldnt write msg"
255
                if (!abortExport)
256
                {
14925 cbradney 257
                        if ((doc.pdfOptions().Version == PDFOptions::PDFVersion_X3) || (doc.pdfOptions().Version == PDFOptions::PDFVersion_X1a) || (doc.pdfOptions().Version == PDFOptions::PDFVersion_X4))
258
                                ret = PDF_End_Doc(ScCore->PrinterProfiles[doc.pdfOptions().PrintProf], nam, Components);
4028 cbradney 259
                        else
12387 jghali 260
                                ret = PDF_End_Doc();
4028 cbradney 261
                }
3133 fschmid 262
                else
4028 cbradney 263
                        closeAndCleanup();
3133 fschmid 264
        }
4029 cbradney 265
        if (usingGUI)
266
                progressDialog->close();
11060 jghali 267
        return (ret && !error);
3133 fschmid 268
}
269
 
11060 jghali 270
const QString& PDFLibCore::errorMessage(void) const
271
{
272
        return ErrorMessage;
273
}
274
 
11441 jghali 275
bool PDFLibCore::exportAborted(void) const
276
{
277
        return abortExport;
278
}
279
 
10054 craig 280
void PDFLibCore::StartObj(int nr)
3133 fschmid 281
{
12080 avox 282
        for (int i=XRef.size(); i < nr; ++i)
283
                XRef.append(0);
284
        XRef[nr-1] = bytesWritten();
4229 craig 285
        PutDoc(QString::number(nr)+ " 0 obj\n");
3133 fschmid 286
}
287
 
4229 craig 288
// Encode a string for inclusion in a
289
// PDF (literal) .
12080 avox 290
static QString PDFEncode(const QString & in)
3133 fschmid 291
{
4229 craig 292
        QString tmp("");
8559 subik 293
        for (int d = 0; d < in.length(); ++d)
3133 fschmid 294
        {
4229 craig 295
                QChar cc(in.at(d));
4230 craig 296
                if ((cc == '(') || (cc == ')') || (cc == '\\'))
297
                        tmp += '\\';
17378 jghali 298
                else if ((cc == '\r') || (cc == '\n'))
17441 jghali 299
                {
300
                        tmp += (cc == '\r') ? "\\r" : "\\n";
301
                        continue;
302
                }
3133 fschmid 303
                tmp += cc;
304
        }
305
        return tmp;
306
}
307
 
12080 avox 308
static QString blendMode(int code)
309
{
310
        switch (code)
311
        {
312
                case 0:
313
                        return("Normal");
314
                        break;
315
                case 1:
316
                        return("Darken");
317
                        break;
318
                case 2:
319
                        return("Lighten");
320
                        break;
321
                case 3:
322
                        return("Multiply");
323
                        break;
324
                case 4:
325
                        return("Screen");
326
                        break;
327
                case 5:
328
                        return("Overlay");
329
                        break;
330
                case 6:
331
                        return("HardLight");
332
                        break;
333
                case 7:
334
                        return("SoftLight");
335
                        break;
336
                case 8:
337
                        return("Difference");
338
                        break;
339
                case 9:
340
                        return("Exclusion");
341
                        break;
342
                case 10:
343
                        return("ColorDodge");
344
                        break;
345
                case 11:
346
                        return("ColorBurn");
347
                        break;
348
                case 12:
349
                        return("Hue");
350
                        break;
351
                case 13:
352
                        return("Saturation");
353
                        break;
354
                case 14:
355
                        return("Color");
356
                        break;
357
                case 15:
358
                        return("Luminosity");
359
                        break;
360
                default:
361
                        return "";
362
        }
14043 jghali 363
}
12080 avox 364
 
10054 craig 365
QByteArray PDFLibCore::EncodeUTF16(const QString &in)
7328 fschmid 366
{
14900 fschmid 367
        QString tmp = in;
13764 jghali 368
        QByteArray cres = ucs2Codec->fromUnicode( tmp );
11455 avox 369
#ifndef WORDS_BIGENDIAN
17352 jghali 370
        // on little endian systems we need 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
{
17378 jghali 405
        QString tmp;
406
        if (in.length() < 1)
407
                return "<>";
4264 craig 408
        if (!Options.Encrypt)
17378 jghali 409
        {
410
                tmp = "(" + PDFEncode(in) + ")";
411
                return tmp;
412
        }
4229 craig 413
        rc4_context_t rc4;
17378 jghali 414
        QByteArray us(in.length(), ' ');
415
        QByteArray ou(in.length(), ' ');
416
        for (int a = 0; a < in.length(); ++a)
417
                us[a] = static_cast<uchar>(QChar(in.at(a)).cell());
11599 jghali 418
        QByteArray step1 = ComputeRC4Key(ObjNum);
8562 jghali 419
        rc4_init(&rc4, reinterpret_cast<uchar*>(step1.data()), qMin(KeyLen+5, 16));
17378 jghali 420
        rc4_encrypt(&rc4, reinterpret_cast<uchar*>(us.data()), reinterpret_cast<uchar*>(ou.data()), in.length());
4229 craig 421
        QString uk = "";
17378 jghali 422
        for (int cl = 0; cl < in.length(); ++cl)
4229 craig 423
                uk += QChar(ou[cl]);
424
        tmp = "<"+String2Hex(&uk, false)+">";
3133 fschmid 425
        return tmp;
426
}
427
 
10054 craig 428
QString PDFLibCore::EncStringUTF16(const QString & in, int ObjNum)
7328 fschmid 429
{
17378 jghali 430
        if (in.length() < 1)
7355 fschmid 431
                return "<>";
7328 fschmid 432
        if (!Options.Encrypt)
433
        {
17378 jghali 434
                QByteArray us = EncodeUTF16(in);
7328 fschmid 435
                QString uk = "";
8559 subik 436
                for (int cl = 0; cl < us.size(); ++cl)
7328 fschmid 437
                        uk += QChar(us[cl]);
438
                return "<"+String2Hex(&uk, false)+">";
439
        }
440
        rc4_context_t rc4;
17378 jghali 441
        QByteArray us = EncodeUTF16(in);
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]);
17378 jghali 449
        QString tmp = "<"+String2Hex(&uk, false)+">";
7328 fschmid 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);
17378 jghali 895
        PutDoc("<<\n/Creator " + EncString("Scribus "+QString(VERSION), 2) + "\n");
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()))
17378 jghali 899
                PutDoc("/Title " + EncStringUTF16(doc.DocName, 2) + "\n");
4718 fschmid 900
        else
17378 jghali 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");
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;
17407 fschmid 947
        for (QHash<int, PageItem*>::iterator itf = doc.FrameItems.begin(); itf != doc.FrameItems.end(); ++itf)
3133 fschmid 948
        {
17407 fschmid 949
                pgit = itf.value();
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);
17312 fschmid 957
                        if (pgit->isTable())
958
                        {
959
                                for (int row = 0; row < pgit->asTable()->rows(); ++row)
960
                                {
961
                                        for (int col = 0; col < pgit->asTable()->columns(); col ++)
962
                                        {
963
                                                TableCell cell = pgit->asTable()->cellAt(row, col);
964
                                                if (cell.row() == row && cell.column() == col)
965
                                                {
966
                                                        PageItem* textFrame = cell.textFrame();
967
                                                        for (uint e = 0; e < static_cast<uint>(textFrame->itemText.length()); ++e)
968
                                                        {
969
                                                                ReallyUsed.insert(textFrame->itemText.charStyle(e).font().replacementName(), DocFonts[textFrame->itemText.charStyle(e).font().replacementName()]);
970
                                                        }
971
                                                }
972
                                        }
973
                                }
974
                        }
16953 fschmid 975
                        if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
8092 fschmid 976
                        {
16953 fschmid 977
                                if (pgit->isAnnotation())
12763 fschmid 978
                                {
16953 fschmid 979
                                        int annotType  = pgit->annotation().Type();
980
                                        bool mustEmbed = ((annotType >= 2) && (annotType <= 6) && (annotType != 4));
981
                                        if (pgit->annotation().Type() == 4)
982
                                                StdFonts.insert("/ZapfDingbats", "");
983
                                        if (pgit->itemText.length() > 0 || mustEmbed)
984
                                        {
985
                                                if (Options.Version < PDFOptions::PDFVersion_14)
986
                                                        StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
987
                                                ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
988
                                        }
12763 fschmid 989
                                }
17751 jghali 990
                                uint start = pgit->isTextFrame() ? (uint) pgit->firstInFrame() : 0;
991
                                uint stop  = pgit->isTextFrame() ? (uint) pgit->lastInFrame() + 1 : (uint) pgit->itemText.length();
992
                                for (uint e = start; e < stop; ++e)
16953 fschmid 993
                                {
994
                                        ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
995
                                }
8092 fschmid 996
                        }
3133 fschmid 997
                }
998
        }
9856 fschmid 999
        for (int c = 0; c < doc.MasterItems.count(); ++c)
3133 fschmid 1000
        {
4264 craig 1001
                pgit = doc.MasterItems.at(c);
16953 fschmid 1002
                if (pgit->isGroup())
1003
                        allItems = pgit->asGroupFrame()->getItemList();
1004
                else
1005
                        allItems.append(pgit);
1006
                for (int ii = 0; ii < allItems.count(); ii++)
3133 fschmid 1007
                {
16953 fschmid 1008
                        pgit = allItems.at(ii);
17312 fschmid 1009
                        if (pgit->isTable())
1010
                        {
1011
                                for (int row = 0; row < pgit->asTable()->rows(); ++row)
1012
                                {
1013
                                        for (int col = 0; col < pgit->asTable()->columns(); col ++)
1014
                                        {
1015
                                                TableCell cell = pgit->asTable()->cellAt(row, col);
1016
                                                if (cell.row() == row && cell.column() == col)
1017
                                                {
1018
                                                        PageItem* textFrame = cell.textFrame();
1019
                                                        for (uint e = 0; e < static_cast<uint>(textFrame->itemText.length()); ++e)
1020
                                                        {
1021
                                                                ReallyUsed.insert(textFrame->itemText.charStyle(e).font().replacementName(), DocFonts[textFrame->itemText.charStyle(e).font().replacementName()]);
1022
                                                        }
1023
                                                }
1024
                                        }
1025
                                }
1026
                        }
16953 fschmid 1027
                        if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
8092 fschmid 1028
                        {
16953 fschmid 1029
                                if (pgit->isAnnotation())
12763 fschmid 1030
                                {
16953 fschmid 1031
                                        int annotType  = pgit->annotation().Type();
1032
                                        bool mustEmbed = ((annotType >= 2) && (annotType <= 6) && (annotType != 4));
1033
                                        if (pgit->annotation().Type() == 4)
1034
                                                StdFonts.insert("/ZapfDingbats", "");
1035
                                        if (pgit->itemText.length() > 0 || mustEmbed)
1036
                                        {
1037
                                                if (Options.Version < PDFOptions::PDFVersion_14)
1038
                                                        StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
1039
                                                ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
1040
                                        }
12763 fschmid 1041
                                }
17751 jghali 1042
                                uint start = pgit->isTextFrame() ? (uint) pgit->firstInFrame() : 0;
1043
                                uint stop  = pgit->isTextFrame() ? (uint) pgit->lastInFrame() + 1 : (uint) pgit->itemText.length();
1044
                                for (uint e = start; e < stop; ++e)
16953 fschmid 1045
                                {
1046
                                        ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
1047
                                }
8092 fschmid 1048
                        }
3133 fschmid 1049
                }
1050
        }
9856 fschmid 1051
        for (int d = 0; d < doc.Items->count(); ++d)
3133 fschmid 1052
        {
4264 craig 1053
                pgit = doc.Items->at(d);
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++)
3133 fschmid 1059
                {
16953 fschmid 1060
                        pgit = allItems.at(ii);
17312 fschmid 1061
                        if (pgit->isTable())
1062
                        {
1063
                                for (int row = 0; row < pgit->asTable()->rows(); ++row)
1064
                                {
1065
                                        for (int col = 0; col < pgit->asTable()->columns(); col ++)
1066
                                        {
1067
                                                TableCell cell = pgit->asTable()->cellAt(row, col);
1068
                                                if (cell.row() == row && cell.column() == col)
1069
                                                {
1070
                                                        PageItem* textFrame = cell.textFrame();
1071
                                                        for (uint e = 0; e < static_cast<uint>(textFrame->itemText.length()); ++e)
1072
                                                        {
1073
                                                                ReallyUsed.insert(textFrame->itemText.charStyle(e).font().replacementName(), DocFonts[textFrame->itemText.charStyle(e).font().replacementName()]);
1074
                                                        }
1075
                                                }
1076
                                        }
1077
                                }
1078
                        }
16953 fschmid 1079
                        if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
8092 fschmid 1080
                        {
16953 fschmid 1081
                                if (pgit->isAnnotation())
12763 fschmid 1082
                                {
16953 fschmid 1083
                                        int annotType  = pgit->annotation().Type();
1084
                                        bool mustEmbed = ((annotType >= 2) && (annotType <= 6) && (annotType != 4));
1085
                                        if (pgit->annotation().Type() == 4)
1086
                                                StdFonts.insert("/ZapfDingbats", "");
1087
                                        if (pgit->itemText.length() > 0 || mustEmbed)
1088
                                        {
1089
                                                if (Options.Version < PDFOptions::PDFVersion_14)
1090
                                                        StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
1091
                                                ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
1092
                                        }
12763 fschmid 1093
                                }
17751 jghali 1094
                                uint start = pgit->isTextFrame() ? (uint) pgit->firstInFrame() : 0;
1095
                                uint stop  = pgit->isTextFrame() ? (uint) pgit->lastInFrame() + 1 : (uint) pgit->itemText.length();
1096
                                for (uint e = start; e < stop; ++e)
16953 fschmid 1097
                                {
1098
                                        ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
1099
                                }
8092 fschmid 1100
                        }
3133 fschmid 1101
                }
1102
        }
11453 fschmid 1103
/*      if (Options.docInfoMarks)
6943 fschmid 1104
        {
1105
                StdFonts.insert("/Helvetica", "");
11453 fschmid 1106
        } */
16052 fschmid 1107
        QStringList patterns = doc.getPatternDependencyList(doc.getUsedPatterns());
8559 subik 1108
        for (int c = 0; c < patterns.count(); ++c)
6407 fschmid 1109
        {
1110
                ScPattern pa = doc.docPatterns[patterns[c]];
9856 fschmid 1111
                for (int o = 0; o < pa.items.count(); o++)
6407 fschmid 1112
                {
1113
                        pgit = pa.items.at(o);
16953 fschmid 1114
                        if (pgit->isGroup())
1115
                                allItems = pgit->asGroupFrame()->getItemList();
1116
                        else
1117
                                allItems.append(pgit);
1118
                        for (int ii = 0; ii < allItems.count(); ii++)
6407 fschmid 1119
                        {
16953 fschmid 1120
                                pgit = allItems.at(ii);
17312 fschmid 1121
                                if (pgit->isTable())
1122
                                {
1123
                                        for (int row = 0; row < pgit->asTable()->rows(); ++row)
1124
                                        {
1125
                                                for (int col = 0; col < pgit->asTable()->columns(); col ++)
1126
                                                {
1127
                                                        TableCell cell = pgit->asTable()->cellAt(row, col);
1128
                                                        if (cell.row() == row && cell.column() == col)
1129
                                                        {
1130
                                                                PageItem* textFrame = cell.textFrame();
1131
                                                                for (uint e = 0; e < static_cast<uint>(textFrame->itemText.length()); ++e)
1132
                                                                {
1133
                                                                        ReallyUsed.insert(textFrame->itemText.charStyle(e).font().replacementName(), DocFonts[textFrame->itemText.charStyle(e).font().replacementName()]);
1134
                                                                }
1135
                                                        }
1136
                                                }
1137
                                        }
1138
                                }
16953 fschmid 1139
                                if ((pgit->itemType() == PageItem::TextFrame) || (pgit->itemType() == PageItem::PathText))
8351 fschmid 1140
                                {
16953 fschmid 1141
                                        if (pgit->isAnnotation())
12763 fschmid 1142
                                        {
16953 fschmid 1143
                                                if (pgit->annotation().Type() == 4)
1144
                                                        StdFonts.insert("/ZapfDingbats", "");
1145
                                                if (pgit->itemText.length() > 0)
1146
                                                {
1147
                                                        if (Options.Version < PDFOptions::PDFVersion_14)
1148
                                                                StdFonts.insert(ind2PDFabr[pgit->annotation().Font()], "");
1149
                                                        ReallyUsed.insert(pgit->itemText.defaultStyle().charStyle().font().replacementName(), DocFonts[pgit->itemText.defaultStyle().charStyle().font().replacementName()]);
1150
                                                }
12763 fschmid 1151
                                        }
17751 jghali 1152
                                        uint start = pgit->isTextFrame() ? (uint) pgit->firstInFrame() : 0;
1153
                                        uint stop  = pgit->isTextFrame() ? (uint) pgit->lastInFrame() + 1 : (uint) pgit->itemText.length();
1154
                                        for (uint e = start; e < stop; ++e)
16953 fschmid 1155
                                        {
1156
                                                ReallyUsed.insert(pgit->itemText.charStyle(e).font().replacementName(), DocFonts[pgit->itemText.charStyle(e).font().replacementName()]);
1157
                                        }
8351 fschmid 1158
                                }
6407 fschmid 1159
                        }
1160
                }
1161
        }
4017 fschmid 1162
        a = 0;
1163
        QMap<QString, QString>::Iterator itStd;
1164
        for (itStd = StdFonts.begin(); itStd != StdFonts.end(); ++itStd)
1165
        {
12080 avox 1166
                uint fontObject = newObject();
1167
                StartObj(fontObject);
4017 fschmid 1168
                PutDoc("<<\n/Type /Font\n/Subtype /Type1\n");
8392 fschmid 1169
                PutDoc("/Name /FoStd"+QString::number(a)+"\n");
4017 fschmid 1170
                PutDoc("/BaseFont "+itStd.key()+"\n");
8432 fschmid 1171
                if (itStd.key() != "/ZapfDingbats")
1172
                {
1173
                        PutDoc("/Encoding << \n");
1174
                        PutDoc("/Differences [ \n");
1175
                        PutDoc("24 /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde\n");
1176
                        PutDoc("39 /quotesingle 96 /grave 128 /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction /guilsinglleft /guilsinglright\n");
1177
                        PutDoc("/minus /perthousand /quotedblbase /quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron\n");
1178
                        PutDoc("/Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron 164 /currency 166 /brokenbar 168 /dieresis /copyright /ordfeminine 172 /logicalnot\n");
1179
                        PutDoc("/.notdef /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu 183 /periodcentered /cedilla /onesuperior /ordmasculine\n");
1180
                        PutDoc("188 /onequarter /onehalf /threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex\n");
1181
                        PutDoc("/Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n");
1182
                        PutDoc("/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n");
1183
                        PutDoc("/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis\n");
1184
                        PutDoc("/divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis\n");
1185
                        PutDoc("] >>\n");
1186
                }
4017 fschmid 1187
                PutDoc(">>\nendobj\n");
12080 avox 1188
                Seite.FObjects["FoStd"+QString::number(a)] = fontObject;
10469 cbradney 1189
                itStd.value() = "FoStd"+QString::number(a);
4017 fschmid 1190
                a++;
1191
        }
5387 avox 1192
        QMap<QString,QMap<uint, FPointArray> >::Iterator it;
3133 fschmid 1193
        a = 0;
1194
        for (it = ReallyUsed.begin(); it != ReallyUsed.end(); ++it)
1195
        {
16336 jghali 1196
                ScFace& face(AllFonts[it.key()]);
1197
                ScFace::FontFormat fformat = face.format();
1198
                if ((!face.hasNames()) || (Options.SubsetList.contains(it.key())))
3133 fschmid 1199
                {
16336 jghali 1200
                        if (face.hasNames())
3133 fschmid 1201
                        {
8469 fschmid 1202
                                UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
1203
                                uint SubFonts = 0;
8559 subik 1204
                                int glyphCount = 0;
15071 fschmid 1205
                                double minx = 999999.9;
1206
                                double miny = 999999.9;
1207
                                double maxx = -999999.9;
1208
                                double maxy = -999999.9;
9803 fschmid 1209
                                QList<uint> glyphWidths;
8469 fschmid 1210
                                QStringList charProcs;
1211
                                QString encoding = "<< /Type /Encoding\n/Differences [ 0\n";
1212
                                QString fon("");
1213
                                QMap<uint, uint> glyphMapping;
1214
                                QMap<uint,std::pair<QChar,QString> > gl;
16336 jghali 1215
                                face.glyphNames(gl);
10469 cbradney 1216
                                QMap<uint,FPointArray>& RealGlyphs(it.value());
8469 fschmid 1217
                                QMap<uint,FPointArray>::Iterator ig;
1218
                                for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
3133 fschmid 1219
                                {
8469 fschmid 1220
                                        FPoint np, np1, np2;
1221
                                        bool nPath = true;
1222
                                        fon = "";
10469 cbradney 1223
                                        if (ig.value().size() > 3)
3133 fschmid 1224
                                        {
10469 cbradney 1225
                                                FPointArray gly = ig.value();
13951 fschmid 1226
                                                QTransform mat;
8469 fschmid 1227
                                                mat.scale(100.0, -100.0);
1228
                                                gly.map(mat);
1229
                                                gly.translate(0, 1000);
1230
                                                for (uint poi = 0; poi < gly.size()-3; poi += 4)
3133 fschmid 1231
                                                {
8469 fschmid 1232
                                                        if (gly.point(poi).x() > 900000)
1233
                                                        {
1234
                                                                fon += "h\n";
1235
                                                                nPath = true;
1236
                                                                continue;
1237
                                                        }
1238
                                                        if (nPath)
1239
                                                        {
1240
                                                                np = gly.point(poi);
1241
                                                                fon += FToStr(np.x())+" "+FToStr(np.y())+" m\n";
1242
                                                                nPath = false;
1243
                                                        }
1244
                                                        np = gly.point(poi+1);
1245
                                                        np1 = gly.point(poi+3);
1246
                                                        np2 = gly.point(poi+2);
1247
                                                        fon += FToStr(np.x()) + " " + FToStr(np.y()) + " " + FToStr(np1.x()) + " " + FToStr(np1.y()) + " " + FToStr(np2.x()) + " " + FToStr(np2.y()) + " c\n";
3133 fschmid 1248
                                                }
8469 fschmid 1249
                                                fon += "h f*\n";
1250
                                                np = getMinClipF(&gly);
1251
                                                np1 = getMaxClipF(&gly);
1252
                                        }
1253
                                        else
1254
                                        {
1255
                                                fon = "h";
1256
                                                np = FPoint(0, 0);
1257
                                                np1 = FPoint(0, 0);
1258
                                        }
1259
                                        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 1260
                                        minx = qMin(minx, np.x());
1261
                                        miny = qMin(miny, np.y());
1262
                                        maxx = qMax(maxx, np1.x());
1263
                                        maxy = qMax(maxy, np1.y());
8469 fschmid 1264
                                        glyphWidths.append(qRound(np1.x()));
12080 avox 1265
                                        uint charProcObject = newObject();
1266
                                        charProcs.append("/"+gl[ig.key()].second+" "+QString::number(charProcObject)+" 0 R\n");
8469 fschmid 1267
                                        encoding += "/"+gl[ig.key()].second+" ";
1268
                                        glyphMapping.insert(ig.key(), glyphCount + SubFonts * 256);
12080 avox 1269
                                        StartObj(charProcObject);
11317 jghali 1270
                                        if (Options.Compress)
8469 fschmid 1271
                                                fon = CompressStr(&fon);
1272
                                        PutDoc("<< /Length "+QString::number(fon.length()+1));
11317 jghali 1273
                                        if (Options.Compress)
8469 fschmid 1274
                                                PutDoc("\n/Filter /FlateDecode");
12080 avox 1275
                                        PutDoc("\n>>\nstream\n"+EncStream(fon, charProcObject)+"\nendstream\nendobj\n");
8469 fschmid 1276
                                        glyphCount++;
13522 jghali 1277
                                        int glyphsLeft = RealGlyphs.count() - SubFonts * 256;
1278
                                        if ((glyphCount > 255) || (glyphCount == glyphsLeft))
8469 fschmid 1279
                                        {
12080 avox 1280
                                                uint fontWidths = newObject();
1281
                                                StartObj(fontWidths);
8469 fschmid 1282
                                                PutDoc("[ ");
8559 subik 1283
                                                for (int ww = 0; ww < glyphWidths.count(); ++ww)
3133 fschmid 1284
                                                {
8469 fschmid 1285
                                                        PutDoc(QString::number(qRound(glyphWidths[ww]))+" ");
3133 fschmid 1286
                                                }
8469 fschmid 1287
                                                PutDoc("]\nendobj\n");
12080 avox 1288
                                                uint fontCharProcs = newObject();
1289
                                                StartObj(fontCharProcs);
8469 fschmid 1290
                                                PutDoc("<<\n");
8559 subik 1291
                                                for (int ww = 0; ww < charProcs.count(); ++ww)
8469 fschmid 1292
                                                {
1293
                                                        PutDoc(charProcs[ww]);
1294
                                                }
1295
                                                PutDoc(">>\nendobj\n");
12080 avox 1296
                                                uint fontEncoding = newObject();
1297
                                                StartObj(fontEncoding);
8469 fschmid 1298
                                                PutDoc(encoding);
1299
                                                PutDoc("]\n");
1300
                                                PutDoc(">>\nendobj\n");
12080 avox 1301
                                                uint font3Object = newObject();
1302
                                                StartObj(font3Object);
8469 fschmid 1303
                                                PutDoc("<<\n/Type /Font\n/Subtype /Type3\n");
1304
                                                PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(SubFonts)+"\n");
1305
                                                PutDoc("/FirstChar 0\n");
1306
                                                PutDoc("/LastChar "+QString::number(glyphCount-1)+"\n");
12080 avox 1307
                                                PutDoc("/Widths "+QString::number(fontWidths)+" 0 R\n");
1308
                                                PutDoc("/CharProcs "+QString::number(fontCharProcs)+" 0 R\n");
8469 fschmid 1309
                                                PutDoc("/FontBBox ["+QString::number(qRound(minx))+" "+QString::number(qRound(miny))+" "+QString::number(qRound(maxx))+ " "+QString::number(qRound(maxy))+"]\n");
1310
                                                PutDoc("/FontMatrix [0.001 0 0 0.001 0 0]\n");
12080 avox 1311
                                                PutDoc("/Encoding "+QString::number(fontEncoding)+" 0 R\n");
8469 fschmid 1312
                                                PutDoc(">>\nendobj\n");
12080 avox 1313
                                                Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(SubFonts)] = font3Object;
8469 fschmid 1314
                                                charProcs.clear();
1315
                                                glyphWidths.clear();
1316
//                                              glyphMapping.clear();
1317
                                                glyphCount = 0;
13522 jghali 1318
                                                ++SubFonts;
15071 fschmid 1319
                                                minx = 999999.9;
1320
                                                miny = 999999.9;
1321
                                                maxx = -999999.9;
1322
                                                maxy = -999999.9;
8469 fschmid 1323
                                                encoding = "<< /Type /Encoding\n/Differences [ 0\n";
3133 fschmid 1324
                                        }
1325
                                }
8469 fschmid 1326
                                Type3Fonts.insert("/Fo"+QString::number(a), glyphMapping);
1327
                        }
1328
                        else
1329
                        {
1330
                                QString fon("");
10469 cbradney 1331
                                QMap<uint,FPointArray>& RealGlyphs(it.value());
8469 fschmid 1332
                                QMap<uint,FPointArray>::Iterator ig;
1333
                                for (ig = RealGlyphs.begin(); ig != RealGlyphs.end(); ++ig)
5606 fschmid 1334
                                {
8469 fschmid 1335
                                        FPoint np, np1, np2;
1336
                                        bool nPath = true;
1337
                                        fon = "";
10469 cbradney 1338
                                        if (ig.value().size() > 3)
8469 fschmid 1339
                                        {
10469 cbradney 1340
                                                FPointArray gly = ig.value();
13951 fschmid 1341
                                                QTransform mat;
8469 fschmid 1342
                                                mat.scale(0.1, 0.1);
1343
                                                gly.map(mat);
1344
                                                for (uint poi = 0; poi < gly.size()-3; poi += 4)
1345
                                                {
1346
                                                        if (gly.point(poi).x() > 900000)
1347
                                                        {
1348
                                                                fon += "h\n";
1349
                                                                nPath = true;
1350
                                                                continue;
1351
                                                        }
1352
                                                        if (nPath)
1353
                                                        {
1354
                                                                np = gly.point(poi);
1355
                                                                fon += FToStr(np.x())+" "+FToStr(-np.y())+" m\n";
1356
                                                                nPath = false;
1357
                                                        }
1358
                                                        np = gly.point(poi+1);
1359
                                                        np1 = gly.point(poi+3);
1360
                                                        np2 = gly.point(poi+2);
1361
                                                        fon += FToStr(np.x()) + " " + FToStr(-np.y()) + " " +
1362
                                                                FToStr(np1.x()) + " " + FToStr(-np1.y()) + " " +
1363
                                                                FToStr(np2.x()) + " " + FToStr(-np2.y()) + " c\n";
1364
                                                }
1365
                                                fon += "h f*\n";
1366
                                                np = getMinClipF(&gly);
1367
                                                np1 = getMaxClipF(&gly);
1368
                                        }
1369
                                        else
1370
                                        {
1371
                                                fon = "h";
1372
                                                np = FPoint(0, 0);
1373
                                                np1 = FPoint(0, 0);
1374
                                        }
12080 avox 1375
                                        uint fontGlyphXForm = newObject();
1376
                                        StartObj(fontGlyphXForm);
8469 fschmid 1377
                                        PutDoc("<<\n/Type /XObject\n/Subtype /Form\n/FormType 1\n");
1378
                                        PutDoc("/BBox [ "+FToStr(np.x())+" "+FToStr(-np.y())+" "+FToStr(np1.x())+ " "+FToStr(-np1.y())+" ]\n");
1379
                                        PutDoc("/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]\n");
1380
                                        PutDoc(">>\n");
11317 jghali 1381
                                        if (Options.Compress)
8469 fschmid 1382
                                                fon = CompressStr(&fon);
1383
                                        PutDoc("/Length "+QString::number(fon.length()+1));
11317 jghali 1384
                                        if (Options.Compress)
8469 fschmid 1385
                                                PutDoc("\n/Filter /FlateDecode");
12080 avox 1386
                                        PutDoc(" >>\nstream\n"+EncStream(fon, fontGlyphXForm)+"\nendstream\nendobj\n");
17617 jghali 1387
                                        Seite.XObjects[face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+QString::number(ig.key())] = fontGlyphXForm;
5606 fschmid 1388
                                }
3133 fschmid 1389
                        }
1390
                }
1391
                else
1392
                {
4229 craig 1393
                        UsedFontsP.insert(it.key(), "/Fo"+QString::number(a));
12080 avox 1394
                        uint embeddedFontObject = 0;
5980 avox 1395
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1396
                        {
3829 cbradney 1397
                                QString fon("");
17617 jghali 1398
                                QByteArray bb;
12080 avox 1399
                                embeddedFontObject = newObject();
1400
                                StartObj(embeddedFontObject);
17617 jghali 1401
                                face.RawData(bb);
8559 subik 1402
                                int posi;
3133 fschmid 1403
                                for (posi = 6; posi < bb.size(); ++posi)
1404
                                {
1405
                                        if ((bb[posi] == static_cast<char>(0x80)) && (static_cast<int>(bb[posi+1]) == 2))
1406
                                                break;
1407
                                        fon += QChar(bb[posi]);
1408
                                }
1409
                                int len1 = fon.length();
8559 subik 1410
                                int ulen;
3133 fschmid 1411
                                ulen = bb[posi+2] & 0xff;
1412
                                ulen |= (bb[posi+3] << 8) & 0xff00;
1413
                                ulen |= (bb[posi+4] << 16) & 0xff0000;
1414
                                ulen |= (bb[posi+5] << 24) & 0xff000000;
1415
                                if (ulen > bb.size())
1416
                                        ulen = bb.size()-7;
1417
                                posi += 6;
8559 subik 1418
                                for (int j = 0; j < ulen; ++j)
3133 fschmid 1419
                                        fon += QChar(bb[posi++]);
1420
                                posi += 6;
1421
                                int len2 = fon.length()-len1;
8559 subik 1422
                                for (int j = posi; j < bb.size(); ++j)
3133 fschmid 1423
                                {
1424
                                        if ((bb[j] == static_cast<char>(0x80)) && (static_cast<int>(bb[j+1]) == 3))
1425
                                                break;
1426
                                        if (bb[j] == '\r')
1427
                                                fon += "\n";
1428
                                        else
1429
                                                fon += QChar(bb[j]);
1430
                                }
1431
                                int len3 = fon.length()-len2-len1;
11317 jghali 1432
                                if (Options.Compress)
3133 fschmid 1433
                                        fon = CompressStr(&fon);
4229 craig 1434
                                PutDoc("<<\n/Length "+QString::number(fon.length()+1)+"\n");
1435
                                PutDoc("/Length1 "+QString::number(len1)+"\n");
1436
                                PutDoc("/Length2 "+QString::number(len2)+"\n");
1437
                                PutDoc("/Length3 "+QString::number(len3)+"\n");
11317 jghali 1438
                                if (Options.Compress)
3133 fschmid 1439
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1440
                                PutDoc(">>\nstream\n"+EncStream(fon,embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1441
                        }
5980 avox 1442
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1443
                        {
3829 cbradney 1444
                                QString fon("");
1445
                                QString fon2("");
1446
                                QString tm("");
3133 fschmid 1447
                                uint value;
1448
                                bool ok = true;
12080 avox 1449
                                embeddedFontObject = newObject();
1450
                                StartObj(embeddedFontObject);
17617 jghali 1451
                                face.EmbedFont(fon);
10469 cbradney 1452
                                int len1 = fon.indexOf("eexec")+5;
3133 fschmid 1453
                                fon2 = fon.left(len1)+"\n";
10469 cbradney 1454
                                int len2 = fon.indexOf("0000000000000000000000000");
3133 fschmid 1455
                                if (len2 == -1)
1456
                                        len2 = fon.length()+1;
1457
                                int count = 0;
1458
                                for (int xx = len1; xx < len2-1; ++xx)
1459
                                {
1460
                                        tm = fon.at(xx);
1461
                                        if ((tm == QChar(13)) || (tm == QChar(10)))
1462
                                                continue;
1463
                                        xx++;
1464
                                        count++;
1465
                                        tm += fon.at(xx);
1466
                                        value = tm.toUInt(&ok, 16);
1467
                                        fon2 += QChar(value);
1468
                                }
1469
                                fon2 += fon.mid(len2);
11317 jghali 1470
                                if (Options.Compress)
3133 fschmid 1471
                                        fon2 = CompressStr(&fon2);
4229 craig 1472
                                PutDoc("<<\n/Length "+QString::number(fon2.length()+1)+"\n");
1473
                                PutDoc("/Length1 "+QString::number(len1+1)+"\n");
1474
                                PutDoc("/Length2 "+QString::number(count)+"\n");
1475
                                PutDoc(static_cast<int>(fon.length()-len2) == -1 ? QString("/Length3 0\n") : "/Length3 "+QString::number(fon.length()-len2)+"\n");
11317 jghali 1476
                                if (Options.Compress)
3133 fschmid 1477
                                        PutDoc("/Filter /FlateDecode\n");
12080 avox 1478
                                PutDoc(">>\nstream\n"+EncStream(fon2, embeddedFontObject)+"\nendstream\nendobj\n");
3133 fschmid 1479
                        }
5980 avox 1480
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
3133 fschmid 1481
                        {
17617 jghali 1482
                                QByteArray bb;
12080 avox 1483
                                embeddedFontObject = newObject();
1484
                                StartObj(embeddedFontObject);
17617 jghali 1485
                                face.RawData(bb);
1486
                                int len = bb.length();
11317 jghali 1487
                                if (Options.Compress)
17617 jghali 1488
                                        bb = CompressArray(bb);
1489
                                //qDebug() << QString("sfnt data: size=%1 compressed=%2").arg(len).arg(bb.length());
1490
                                PutDoc("<<\n/Length " + QString::number(bb.length() + 1) + "\n");
1491
                                PutDoc("/Length1 " + QString::number(len) + "\n");
11317 jghali 1492
                                if (Options.Compress)
3133 fschmid 1493
                                        PutDoc("/Filter /FlateDecode\n");
17617 jghali 1494
                                PutDoc(">>\nstream\n");
1495
                                EncodeArrayToStream(bb, embeddedFontObject);
1496
                                PutDoc("\nendstream\nendobj\n");
3133 fschmid 1497
                        }
12080 avox 1498
                        uint fontDescriptor = newObject();
1499
                        StartObj(fontDescriptor);
5387 avox 1500
                        // TODO: think about QByteArray ScFace::getFontDescriptor() -- AV
3133 fschmid 1501
                        PutDoc("<<\n/Type /FontDescriptor\n");
17617 jghali 1502
                        PutDoc("/FontName /"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1503
                        PutDoc("/FontBBox [ "+face.fontBBoxAsString()+" ]\n");
3133 fschmid 1504
                        PutDoc("/Flags ");
5980 avox 1505
                        //FIXME: isItalic() should be queried from ScFace, not from Qt -- AV
3544 avox 1506
                        //QFontInfo fo = QFontInfo(it.data());
3133 fschmid 1507
                        int pfl = 0;
17617 jghali 1508
                        if (face.isFixedPitch())
3133 fschmid 1509
                                pfl = pfl ^ 1;
3544 avox 1510
                        //if (fo.italic())
15364 jghali 1511
                        if (AllFonts[it.key()].italicAngleAsString() != "0")
3133 fschmid 1512
                                pfl = pfl ^ 64;
1513
//                      pfl = pfl ^ 4;
1514
                        pfl = pfl ^ 32;
4229 craig 1515
                        PutDoc(QString::number(pfl)+"\n");
17617 jghali 1516
                        PutDoc("/Ascent " + face.ascentAsString()+"\n");
1517
                        PutDoc("/Descent " + face.descentAsString()+"\n");
1518
                        PutDoc("/CapHeight " + face.capHeightAsString()+"\n");
1519
                        PutDoc("/ItalicAngle " + face.italicAngleAsString()+"\n");
1520
//                      PutDoc("/Ascent "+QString::number(static_cast<int>(face.ascent()))+"\n");
1521
//                      PutDoc("/Descent "+QString::number(static_cast<int>(face.descent()))+"\n");
1522
//                      PutDoc("/CapHeight "+QString::number(static_cast<int>(face.capHeight()))+"\n");
1523
//                      PutDoc("/ItalicAngle "+face.italicAngle()+"\n");
1524
//                      PutDoc("/StemV "+ face.stemV() + "\n");
6213 fschmid 1525
                        PutDoc("/StemV 1\n");
5980 avox 1526
                        if ((fformat == ScFace::SFNT || fformat == ScFace::TTCF) && (Options.EmbedList.contains(it.key())))
12080 avox 1527
                                PutDoc("/FontFile2 "+QString::number(embeddedFontObject)+" 0 R\n");
5980 avox 1528
                        if ((fformat == ScFace::PFB) && (Options.EmbedList.contains(it.key())))
12080 avox 1529
                                PutDoc("/FontFile "+QString::number(embeddedFontObject)+" 0 R\n");
5980 avox 1530
                        if ((fformat == ScFace::PFA) && (Options.EmbedList.contains(it.key())))
12080 avox 1531
                                PutDoc("/FontFile "+QString::number(embeddedFontObject)+" 0 R\n");
3133 fschmid 1532
                        PutDoc(">>\nendobj\n");
17628 jghali 1533
 
1534
                        QMap<uint,std::pair<QChar,QString> > gl;
1535
                        face.glyphNames(gl);
1536
                        int nglyphs = 0;
1537
                        QMap<uint,std::pair<QChar,QString> >::Iterator gli;
1538
                        for (gli = gl.begin(); gli != gl.end(); ++gli)
3133 fschmid 1539
                        {
17628 jghali 1540
                                if (gli.key() > static_cast<uint>(nglyphs))
1541
                                        nglyphs = gli.key();
1542
                        }
1543
                        ++nglyphs;
1544
//                      qDebug() << QString("pdflib: nglyphs %1 max %2").arg(nglyphs).arg(face.maxGlyph());
1545
                        uint FontDes = fontDescriptor;
1546
                        if (Options.Version == PDFOptions::PDFVersion_X4 && (fformat == ScFace::SFNT || fformat == ScFace::TTCF))
1547
                        {
1548
                                uint fontWidths2 = newObject();
1549
                                StartObj(fontWidths2);
1550
                                QStringList toUnicodeMaps;
1551
                                QList<int> toUnicodeMapsCount;
1552
                                QString toUnicodeMap = "";
1553
                                int toUnicodeMapCounter = 0;
1554
 
1555
                                PutDoc("[ ");
1556
                                QList<uint> keys = gl.uniqueKeys();
1557
                                QList<uint>::iterator git;
1558
                                for (git = keys.begin(); git != keys.end(); ++git)
3133 fschmid 1559
                                {
17628 jghali 1560
                                        PutDoc(QString::number(*git)+" ["+QString::number(static_cast<int>(face.glyphWidth(*git)* 1000))+"] " );
1561
                                        QString tmp, tmp2;
1562
                                        tmp.sprintf("%02X", *git);
1563
                                        tmp2.sprintf("%04X", gl.value(*git).first.unicode());
1564
                                        toUnicodeMap += QString("<%1> <%2>\n").arg(tmp).arg((tmp2));
1565
                                        toUnicodeMapCounter++;
1566
                                        if (toUnicodeMapCounter == 100)
1567
                                        {
1568
                                                toUnicodeMaps.append(toUnicodeMap);
1569
                                                toUnicodeMapsCount.append(toUnicodeMapCounter);
1570
                                                toUnicodeMap = "";
1571
                                                toUnicodeMapCounter = 0;
1572
                                        }
3133 fschmid 1573
                                }
1574
                                PutDoc("]\nendobj\n");
17628 jghali 1575
                                if (toUnicodeMapCounter != 0)
1576
                                {
1577
                                        toUnicodeMaps.append(toUnicodeMap);
1578
                                        toUnicodeMapsCount.append(toUnicodeMapCounter);
1579
                                }
1580
                                QString toUnicodeMapStream = "";
1581
                                toUnicodeMapStream += "/CIDInit /ProcSet findresource begin\n";
1582
                                toUnicodeMapStream += "12 dict begin\n";
1583
                                toUnicodeMapStream += "begincmap\n";
1584
                                toUnicodeMapStream += "/CIDSystemInfo <<\n";
1585
                                toUnicodeMapStream += "/Registry (Adobe)\n";
1586
                                toUnicodeMapStream += "/Ordering (UCS)\n";
1587
                                toUnicodeMapStream += "/Supplement 0\n";
1588
                                toUnicodeMapStream += ">> def\n";
1589
                                toUnicodeMapStream += "/CMapName /Adobe-Identity-UCS def\n";
1590
                                toUnicodeMapStream += "/CMapType 2 def\n";
1591
                                toUnicodeMapStream += "1 begincodespacerange\n";
1592
                                toUnicodeMapStream += "<0000> <FFFF>\n";
1593
                                toUnicodeMapStream += "endcodespacerange\n";
1594
                                for (int uniC = 0; uniC < toUnicodeMaps.count(); uniC++)
1595
                                {
1596
                                        toUnicodeMapStream += QString("%1 beginbfchar\n").arg(toUnicodeMapsCount[uniC]);
1597
                                        toUnicodeMapStream += toUnicodeMaps[uniC];
1598
                                        toUnicodeMapStream += "endbfchar\n";
1599
                                }
1600
                                toUnicodeMapStream += "endcmap\n";
1601
                                toUnicodeMapStream += "CMapName currentdict /CMap defineresource pop\n";
1602
                                toUnicodeMapStream += "end\n";
1603
                                toUnicodeMapStream += "end\n";
1604
                                uint fontToUnicode2 = WritePDFStream(toUnicodeMapStream);
1605
                                uint fontObject2 = newObject();
1606
                                StartObj(fontObject2);
1607
                                PutDoc("<<\n/Type /Font\n/Subtype /Type0\n");
4229 craig 1608
                                PutDoc("/Name /Fo"+QString::number(a)+"\n");
17628 jghali 1609
                                PutDoc("/BaseFont /"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1610
                                PutDoc("/Encoding /Identity-H\n");
1611
                                PutDoc("/ToUnicode "+QString::number(fontToUnicode2)+" 0 R\n");
1612
                                PutDoc("/DescendantFonts [");
1613
                                PutDoc("<</Type /Font");
1614
                                PutDoc("/Subtype /CIDFontType2");
1615
                                PutDoc("/BaseFont /"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ));
1616
                                PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R");
1617
                                PutDoc("/CIDSystemInfo <</Ordering(Identity)/Registry(Adobe)/Supplement 0>>");
1618
                                PutDoc("/DW 1000");
1619
                                PutDoc("/W "+QString::number(fontWidths2)+" 0 R");
1620
                                PutDoc("/CIDToGIDMap /Identity");
1621
                                PutDoc(">>"); // close CIDFont dictionary
1622
                                PutDoc("]\n"); // close DescendantFonts array
3133 fschmid 1623
                                PutDoc(">>\nendobj\n");
17628 jghali 1624
                                Seite.FObjects["Fo"+QString::number(a)] = fontObject2;
3133 fschmid 1625
                        }
17628 jghali 1626
                        else
1627
                        {
1628
                                uint Fcc = nglyphs / 224;
1629
                                if ((nglyphs % 224) != 0)
1630
                                        Fcc += 1;
1631
                                for (uint Fc = 0; Fc < Fcc; ++Fc)
8092 fschmid 1632
                                {
12080 avox 1633
                                        uint fontWidths2 = newObject();
1634
                                        StartObj(fontWidths2);
17628 jghali 1635
                                        int chCount = 32;
1636
                                        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 ");
1637
                                        for (int ww = 32; ww < 256; ++ww)
1638
                                        {
1639
                                                uint glyph = 224 * Fc + ww - 32;
1640
                                                if (gl.contains(glyph))
1641
                                                        PutDoc(QString::number(static_cast<int>(face.glyphWidth(glyph)* 1000))+" ");
1642
                                                else
1643
                                                        PutDoc("0 ");
1644
                                                chCount++;
1645
                                                if (signed(glyph) == nglyphs-1)
1646
                                                        break;
1647
                                        }
1648
                                        PutDoc("]\nendobj\n");
1649
                                        uint fontEncoding2 = newObject();
1650
                                        StartObj(fontEncoding2);
8147 fschmid 1651
                                        QStringList toUnicodeMaps;
9803 fschmid 1652
                                        QList<int> toUnicodeMapsCount;
8136 fschmid 1653
                                        QString toUnicodeMap = "";
1654
                                        int toUnicodeMapCounter = 0;
17628 jghali 1655
                                        PutDoc("<< /Type /Encoding\n");
1656
                                        PutDoc("/Differences [ \n");
1657
                                        int crc = 0;
1658
                                        bool startOfSeq = true;
1659
                                        for (int ww2 = 32; ww2 < 256; ++ww2)
3133 fschmid 1660
                                        {
17628 jghali 1661
                                                uint glyph = 224 * Fc + ww2 - 32;
1662
                                                QMap<uint,std::pair<QChar,QString> >::Iterator glIt = gl.find(glyph);
1663
                                                if (glIt != gl.end() && !glIt.value().second.isEmpty())
6213 fschmid 1664
                                                {
17628 jghali 1665
                                                        if (startOfSeq)
1666
                                                        {
1667
                                                                PutDoc(QString::number(ww2)+" ");
1668
                                                                startOfSeq = false;
1669
                                                        }
1670
                                                        PutDoc("/"+glIt.value().second+" ");
1671
                                                        QString tmp, tmp2;
1672
                                                        tmp.sprintf("%02X", ww2);
1673
                                                        tmp2.sprintf("%04X", glIt.value().first.unicode());
1674
                                                        toUnicodeMap += QString("<%1> <%2>\n").arg(tmp).arg((tmp2));
1675
                                                        toUnicodeMapCounter++;
1676
                                                        if (toUnicodeMapCounter == 100)
1677
                                                        {
1678
                                                                toUnicodeMaps.append(toUnicodeMap);
1679
                                                                toUnicodeMapsCount.append(toUnicodeMapCounter);
1680
                                                                toUnicodeMap = "";
1681
                                                                toUnicodeMapCounter = 0;
1682
                                                        }
1683
                                                        crc++;
6213 fschmid 1684
                                                }
17628 jghali 1685
                                                else
1686
                                                {
1687
                                                        startOfSeq = true;
1688
                                                }
1689
                                                if (signed(glyph) == nglyphs-1)
1690
                                                        break;
1691
                                                if (crc > 8)
1692
                                                {
1693
                                                        PutDoc("\n");
1694
                                                        crc = 0;
1695
                                                }
3133 fschmid 1696
                                        }
8147 fschmid 1697
                                        if (toUnicodeMapCounter != 0)
1698
                                        {
1699
                                                toUnicodeMaps.append(toUnicodeMap);
1700
                                                toUnicodeMapsCount.append(toUnicodeMapCounter);
1701
                                        }
17628 jghali 1702
                                        PutDoc("]\n");
1703
                                        PutDoc(">>\nendobj\n");
8136 fschmid 1704
                                        QString toUnicodeMapStream = "";
1705
                                        toUnicodeMapStream += "/CIDInit /ProcSet findresource begin\n";
1706
                                        toUnicodeMapStream += "12 dict begin\n";
1707
                                        toUnicodeMapStream += "begincmap\n";
1708
                                        toUnicodeMapStream += "/CIDSystemInfo <<\n";
1709
                                        toUnicodeMapStream += "/Registry (Adobe)\n";
1710
                                        toUnicodeMapStream += "/Ordering (UCS)\n";
1711
                                        toUnicodeMapStream += "/Supplement 0\n";
1712
                                        toUnicodeMapStream += ">> def\n";
1713
                                        toUnicodeMapStream += "/CMapName /Adobe-Identity-UCS def\n";
1714
                                        toUnicodeMapStream += "/CMapType 2 def\n";
1715
                                        toUnicodeMapStream += "1 begincodespacerange\n";
8147 fschmid 1716
                                        toUnicodeMapStream += "<0000> <FFFF>\n";
8136 fschmid 1717
                                        toUnicodeMapStream += "endcodespacerange\n";
8559 subik 1718
                                        for (int uniC = 0; uniC < toUnicodeMaps.count(); uniC++)
8147 fschmid 1719
                                        {
1720
                                                toUnicodeMapStream += QString("%1 beginbfchar\n").arg(toUnicodeMapsCount[uniC]);
1721
                                                toUnicodeMapStream += toUnicodeMaps[uniC];
1722
                                                toUnicodeMapStream += "endbfchar\n";
1723
                                        }
8136 fschmid 1724
                                        toUnicodeMapStream += "endcmap\n";
1725
                                        toUnicodeMapStream += "CMapName currentdict /CMap defineresource pop\n";
1726
                                        toUnicodeMapStream += "end\n";
1727
                                        toUnicodeMapStream += "end\n";
12906 jghali 1728
                                        uint fontToUnicode2 = WritePDFStream(toUnicodeMapStream);
12080 avox 1729
                                        uint fontObject2 = newObject();
1730
                                        StartObj(fontObject2);
3133 fschmid 1731
                                        PutDoc("<<\n/Type /Font\n/Subtype ");
5980 avox 1732
                                        PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
17628 jghali 1733
                                        PutDoc("/Name /Fo"+QString::number(a)+"S"+QString::number(Fc)+"\n");
17617 jghali 1734
                                        PutDoc("/BaseFont /"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
3133 fschmid 1735
                                        PutDoc("/FirstChar 0\n");
17628 jghali 1736
                                        PutDoc("/LastChar "+QString::number(chCount-1)+"\n");
1737
                                        PutDoc("/Widths "+QString::number(fontWidths2)+" 0 R\n");
1738
                                        PutDoc("/Encoding "+QString::number(fontEncoding2)+" 0 R\n");
1739
                                        PutDoc("/ToUnicode "+QString::number(fontToUnicode2)+" 0 R\n");
4229 craig 1740
                                        PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
3133 fschmid 1741
                                        PutDoc(">>\nendobj\n");
17628 jghali 1742
                                        Seite.FObjects["Fo"+QString::number(a)+"S"+QString::number(Fc)] = fontObject2;
1743
                                } // for(Fc)
1744
                                uint fontWidthsForm = newObject();
1745
                                StartObj(fontWidthsForm);
1746
                                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 ");
1747
                                for (int ww = 32; ww < 256; ++ww)
1748
                                {
1749
                                        uint glyph = face.char2CMap(QChar(ww));
1750
                                        if (gl.contains(glyph))
1751
                                                PutDoc(QString::number(static_cast<int>(face.glyphWidth(glyph)* 1000))+" ");
1752
                                        else
1753
                                                PutDoc("0 ");
8101 fschmid 1754
                                }
17628 jghali 1755
                                PutDoc("]\nendobj\n");
1756
                                uint fontObjectForm = newObject();
1757
                                StartObj(fontObjectForm);
1758
                                PutDoc("<<\n/Type /Font\n/Subtype ");
1759
                                PutDoc((fformat == ScFace::SFNT || fformat == ScFace::TTCF) ? "/TrueType\n" : "/Type1\n");
1760
//                              if (fformat == ScFace::SFNT || fformat == ScFace::TTCF)
1761
//                              {
1762
//                                      PutDoc("/TrueType\n");
1763
                                        PutDoc("/Name /Fo"+QString::number(a)+"Form"+"\n");
1764
                                        Seite.FObjects["Fo"+QString::number(a)+"Form"] = fontObjectForm;
1765
                                        UsedFontsF.insert(it.key(), "/Fo"+QString::number(a)+"Form");
1766
/*                              }
1767
                                else
1768
                                {
1769
                                        PutDoc("/Type1\n");
1770
                                        PutDoc("/Name /"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1771
                                        Seite.FObjects[face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )] = ObjCounter;
1772
                                        UsedFontsF.insert(it.key(), "/"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" ));
1773
                                } */
1774
                                PutDoc("/BaseFont /"+face.psName().replace( QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )+"\n");
1775
                                PutDoc("/Encoding << \n");
1776
                                PutDoc("/Differences [ \n");
1777
                                PutDoc("24 /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde\n");
1778
                                PutDoc("39 /quotesingle 96 /grave 128 /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction /guilsinglleft /guilsinglright\n");
1779
                                PutDoc("/minus /perthousand /quotedblbase /quotedblleft /quotedblright /quoteleft /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron\n");
1780
                                PutDoc("/Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron 164 /currency 166 /brokenbar 168 /dieresis /copyright /ordfeminine 172 /logicalnot\n");
1781
                                PutDoc("/.notdef /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu 183 /periodcentered /cedilla /onesuperior /ordmasculine\n");
1782
                                PutDoc("188 /onequarter /onehalf /threequarters 192 /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex\n");
1783
                                PutDoc("/Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash\n");
1784
                                PutDoc("/Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla\n");
1785
                                PutDoc("/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis\n");
1786
                                PutDoc("/divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis\n");
1787
                                PutDoc("] >>\n");
1788
                                PutDoc("/FirstChar 0\n");
1789
                                PutDoc("/LastChar 255\n");
1790
                                PutDoc("/Widths "+QString::number(fontWidthsForm)+" 0 R\n");
1791
                                PutDoc("/FontDescriptor "+QString::number(FontDes)+" 0 R\n");
1792
                                PutDoc(">>\nendobj\n");
1793
                        }
3133 fschmid 1794
                }
1795
                a++;
1796
        }
4264 craig 1797
        if (Options.UseLPI)
3133 fschmid 1798
        {
12080 avox 1799
                uint halftones = newObject();
1800
                StartObj(halftones);
3133 fschmid 1801
                PutDoc("<<\n/Type /Halftone\n/HalftoneType 5\n");
4264 craig 1802
                QMap<QString,LPIData>::const_iterator itlp;
1803
                for (itlp = Options.LPISettings.constBegin(); itlp != Options.LPISettings.constEnd(); ++itlp)
3133 fschmid 1804
                {
1805
                        PutDoc("/"+itlp.key()+"\n<<\n/Type /Halftone\n/HalftoneType 1