Subversion Repositories Scribus

Rev

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