Subversion Repositories Scribus

Rev

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