Subversion Repositories Scribus

Rev

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