Subversion Repositories Scribus

Rev

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