Subversion Repositories Scribus

Rev

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

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