Subversion Repositories Scribus

Rev

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