Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
5979 avox 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
*/
7
 
10223 cbradney 8
#include <QFile>
9
#include <QString>
10
#include <QObject>
13531 pierre 11
#include <QDebug>
12
// #include <QTime>
5979 avox 13
 
14
#include <sys/types.h>
15
 
16
#include "fonts/scface_ttf.h"
17
#include "fonts/scfontmetrics.h"
18
#include "util.h"
19
#include "scconfig.h"
20
 
13531 pierre 21
KernFeature::KernFeature ( FT_Face face )
22
                :m_valid ( true )
23
{
24
        FontName = QString ( face->family_name ) + " " + QString ( face->style_name )   ;
25
//      qDebug() <<"KF"<<FontName;
26
//      QTime t;
27
//      t.start();
28
        FT_ULong length = 0;
29
        if ( !FT_Load_Sfnt_Table ( face, TTAG_GPOS , 0, NULL, &length ) )
30
        {
31
//              qDebug() <<"\t"<<"GPOS table len"<<length;
32
                if ( length > 32 )
33
                {
34
                        GPOSTableRaw.resize ( length );
35
                        FT_Load_Sfnt_Table ( face, TTAG_GPOS, 0, reinterpret_cast<FT_Byte*> ( GPOSTableRaw.data() ), &length );
5979 avox 36
 
13531 pierre 37
                        makeCoverage();
38
                }
39
                else
40
                        m_valid = false;
5979 avox 41
 
13531 pierre 42
                GPOSTableRaw.clear();
43
                coverages.clear();
44
        }
45
        else
46
                m_valid = false;
47
 
48
        if ( !m_valid )
49
                pairs.clear();
50
//      qDebug() <<"\t"<<m_valid;
51
//      qDebug() <<"\t"<<t.elapsed();
52
}
53
 
54
KernFeature::KernFeature ( const KernFeature & kf )
5979 avox 55
{
13531 pierre 56
        m_valid = kf.m_valid;
57
        if ( m_valid )
58
                pairs = kf.pairs;
59
 
5979 avox 60
}
13531 pierre 61
 
62
 
63
KernFeature::~ KernFeature()
5979 avox 64
{
65
}
13531 pierre 66
 
67
double KernFeature::getPairValue ( unsigned int glyph1, unsigned int glyph2 ) const
5979 avox 68
{
13531 pierre 69
        if ( m_valid )
70
        {
71
                if ( pairs.contains ( glyph1 ) )
72
                {
73
                        if ( pairs[glyph1].contains ( glyph2 ) )
74
                        {
75
                                return pairs[glyph1][glyph2];
76
                        }
77
                }
78
        }
79
        return 0.0;
5979 avox 80
}
13531 pierre 81
 
82
void KernFeature::makeCoverage()
5979 avox 83
{
13531 pierre 84
        if ( GPOSTableRaw.isEmpty() )
85
                return;
86
 
87
        quint16 FeatureList_Offset= toUint16 ( 6 );
88
        quint16 LookupList_Offset = toUint16 ( 8 );
89
 
90
        // Find the offsets of the kern feature tables
91
        quint16 FeatureCount = toUint16 ( FeatureList_Offset );;
92
        QList<quint16> FeatureKern_Offset;
93
        for ( quint16 FeatureRecord ( 0 ); FeatureRecord < FeatureCount; ++ FeatureRecord )
94
        {
95
                int rawIdx ( FeatureList_Offset + 2 + ( 6 * FeatureRecord ) );
96
                quint32 tag ( FT_MAKE_TAG ( GPOSTableRaw.at ( rawIdx ),
97
                                            GPOSTableRaw.at ( rawIdx + 1 ),
98
                                            GPOSTableRaw.at ( rawIdx + 2 ),
99
                                            GPOSTableRaw.at ( rawIdx + 3 ) ) );
100
                if ( tag == TTAG_kern )
101
                {
102
                        FeatureKern_Offset << ( toUint16 ( rawIdx + 4 ) + FeatureList_Offset );
103
 
104
                }
105
        }
106
 
107
        // Extract indices of lookups for feture kern
108
        QList<quint16> LookupListIndex;
109
        foreach ( quint16 kern, FeatureKern_Offset )
110
        {
111
                quint16 LookupCount ( toUint16 ( kern + 2 ) );
112
                for ( int llio ( 0 ) ; llio < LookupCount; ++llio )
113
                {
114
                        quint16 Idx ( toUint16 ( kern + 4 + ( llio * 2 ) ) );
115
                        if ( !LookupListIndex.contains ( Idx ) )
116
                        {
117
                                LookupListIndex <<Idx ;
118
                        }
119
                }
120
        }
121
 
122
 
123
        // Extract offsets of lookup tables for feature kern
124
        QList<quint16> LookupTables;
125
        QList<quint16> PairAdjustmentSubTables;
126
        for ( int i ( 0 ); i < LookupListIndex.count(); ++i )
127
        {
128
                int rawIdx ( LookupList_Offset + 2 + ( LookupListIndex[i] * 2 ) );
129
                quint16 Lookup ( toUint16 ( rawIdx )  + LookupList_Offset );
130
                quint16 SubTableCount ( toUint16 ( Lookup + 4 ) );
131
                for ( int stIdx ( 0 ); stIdx < SubTableCount; ++ stIdx )
132
                {
133
                        quint16 SubTable ( toUint16 ( Lookup + 6 + ( 2 * stIdx ) ) + Lookup );
134
 
135
//                      quint16 PosFormat ( toUint16 ( SubTable ) );
136
                        quint16 Coverage_Offset ( toUint16 ( SubTable + 2 ) + SubTable );
137
                        quint16 CoverageFormat ( toUint16 ( Coverage_Offset ) );
138
 
139
                        if ( 1 == CoverageFormat ) // glyph indices based
140
                        {
141
                                quint16 GlyphCount ( toUint16 ( Coverage_Offset + 2 ) );
142
                                quint16 GlyphID ( Coverage_Offset + 4 );
143
 
144
                                for ( unsigned int gl ( 0 ); gl < GlyphCount; ++gl )
145
                                {
146
                                        coverages[SubTable] << toUint16 ( GlyphID + ( gl * 2 ) );
147
                                }
148
                        }
149
                        else if ( 2 == CoverageFormat ) // Coverage Format2 => ranges based
150
                        {
151
                                quint16 RangeCount ( toUint16 ( Coverage_Offset + 2 ) );
152
 
153
//                              int gl_base ( 0 );
154
                                for ( int r ( 0 ); r < RangeCount; ++r )
155
                                {
156
                                        quint16 rBase ( Coverage_Offset + 4 + ( r * 6 ) );
157
                                        quint16 Start ( toUint16 ( rBase ) );
158
                                        quint16 End ( toUint16 ( rBase + 2 ) );
159
//                                      quint16 StartCoverageIndex ( toUint16 ( rBase + 4 ) );
160
                                        for ( unsigned int gl ( Start ); gl <= End; ++gl )
161
                                                coverages[SubTable]  << gl;
162
                                }
163
                        }
164
                        else
14819 fschmid 165
                        {
13531 pierre 166
                                qDebug() <<"Unknow Coverage Format:"<<CoverageFormat;
14819 fschmid 167
                                continue;
168
                        }
13531 pierre 169
 
170
                        makePairs ( SubTable );
171
                }
172
 
173
        }
174
 
175
 
5979 avox 176
}
13531 pierre 177
 
178
 
179
void KernFeature::makePairs ( quint16 subtableOffset )
180
{
181
        /*
182
        Lookup Type 2:
183
        Pair Adjustment Positioning Subtable
184
        */
185
 
186
        quint16 PosFormat ( toUint16 ( subtableOffset ) );
187
 
188
        if ( PosFormat == 1 )
189
        {
190
                quint16 ValueFormat1 ( toUint16 ( subtableOffset +4 ) );
191
                quint16 ValueFormat2 ( toUint16 ( subtableOffset +6 ) );
192
                quint16 PairSetCount ( toUint16 ( subtableOffset +8 ) );
193
                if ( ValueFormat1 && ValueFormat2 )
194
                {
195
                        for ( int psIdx ( 0 ); psIdx < PairSetCount; ++ psIdx )
196
                        {
197
                                unsigned int FirstGlyph ( coverages[subtableOffset][psIdx] );
198
                                quint16 PairSetOffset ( toUint16 ( subtableOffset +10 + ( 2 * psIdx ) ) +  subtableOffset );
199
                                quint16 PairValueCount ( toUint16 ( PairSetOffset ) );
200
                                quint16 PairValueRecord ( PairSetOffset + 2 );
201
                                for ( int pvIdx ( 0 );pvIdx < PairValueCount; ++pvIdx )
202
                                {
203
                                        quint16 recordBase ( PairValueRecord + ( ( 2 + 2 + 2 ) * pvIdx ) );
204
                                        quint16 SecondGlyph ( toUint16 ( recordBase ) );
205
                                        qint16 Value1 ( toInt16 ( recordBase + 2 ) );
206
                                        pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
207
 
208
                                }
209
 
210
                        }
211
                }
212
                else if ( ValueFormat1 && ( !ValueFormat2 ) )
213
                {
214
                        for ( int psIdx ( 0 ); psIdx < PairSetCount; ++ psIdx )
215
                        {
216
                                unsigned int FirstGlyph ( coverages[subtableOffset][psIdx] );
217
                                quint16 PairSetOffset ( toUint16 ( subtableOffset +10 + ( 2 * psIdx ) ) +  subtableOffset );
218
                                quint16 PairValueCount ( toUint16 ( PairSetOffset ) );
219
                                quint16 PairValueRecord ( PairSetOffset + 2 );
220
                                for ( int pvIdx ( 0 );pvIdx < PairValueCount; ++pvIdx )
221
                                {
222
                                        quint16 recordBase ( PairValueRecord + ( ( 2 + 2 ) * pvIdx ) );
223
                                        quint16 SecondGlyph ( toUint16 ( recordBase ) );
224
                                        qint16 Value1 ( toInt16 ( recordBase + 2 ) );
225
                                        pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
226
 
227
                                }
228
 
229
                        }
230
                }
231
                else
232
                {
233
                        qDebug() <<"ValueFormat1 is null or both ValueFormat1 and ValueFormat2 are null";
234
                }
235
 
236
        }
237
        else if ( PosFormat == 2 )
238
        {
239
                quint16 ValueFormat1 ( toUint16 ( subtableOffset +4 ) );
240
                quint16 ValueFormat2 ( toUint16 ( subtableOffset +6 ) );
241
                quint16 ClassDef1 ( toUint16 ( subtableOffset +8 )  + subtableOffset );
242
                quint16 ClassDef2 ( toUint16 ( subtableOffset +10 ) + subtableOffset );
243
                quint16 Class1Count ( toUint16 ( subtableOffset +12 ) );
244
                quint16 Class2Count ( toUint16 ( subtableOffset +14 ) );
245
                quint16 Class1Record ( subtableOffset +16 );
246
 
247
                // first extract classses
248
                ClassDefTable Class1Data ( getClass ( ClassDef1 , subtableOffset ) );
249
                ClassDefTable Class2Data ( getClass ( ClassDef2 , subtableOffset ) );
250
 
251
                if ( ValueFormat1 && ValueFormat2 )
252
                {
253
                        for ( quint16 C1 ( 0 );C1 < Class1Count; ++C1 )
254
                        {
255
                                QList<quint16> Class1 ( Class1Data[C1] );
256
                                quint16 Class2Record ( Class1Record + ( C1 * ( 2 * 2 * Class2Count ) ) );
257
                                for ( quint16 C2 ( 0 );C2 < Class2Count; ++C2 )
258
                                {
259
                                        qint16 Value1 ( toInt16 ( Class2Record + ( C2 * ( 2 * 2 ) ) ) );
260
                                        QList<quint16> Class2 ( Class2Data[C2] );
261
                                        // keep it barbarian :D
262
                                        foreach ( quint16 FirstGlyph, Class1 )
263
                                        {
264
                                                foreach ( quint16 SecondGlyph, Class2 )
265
                                                {
266
                                                        if ( Value1 )
267
                                                                pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
268
                                                }
269
                                        }
270
                                }
271
                        }
272
                }
273
                else if ( ValueFormat1 && ( !ValueFormat2 ) )
274
                {
275
                        for ( quint16 C1 ( 0 );C1 < Class1Count; ++C1 )
276
                        {
277
                                QString cdbg ( QString::number ( C1 ).rightJustified ( 5,QChar ( 32 ) ) );
278
                                QList<quint16> Class1 ( Class1Data[C1] );
279
                                quint16 Class2Record ( Class1Record + ( C1 * ( 2 * Class2Count ) ) );
280
                                for ( quint16 C2 ( 0 );C2 < Class2Count; ++C2 )
281
                                {
282
                                        qint16 Value1 ( toInt16 ( Class2Record + ( C2 * 2 ) ) );
283
                                        QList<quint16> Class2 ( Class2Data[C2] );
284
 
285
                                        foreach ( quint16 FirstGlyph, Class1 )
286
                                        {
287
                                                foreach ( quint16 SecondGlyph, Class2 )
288
                                                {
289
                                                        if ( Value1 )
290
                                                                pairs[FirstGlyph][SecondGlyph] = double ( Value1 );
291
                                                }
292
                                        }
293
                                }
294
                        }
295
                }
296
                else
297
                {
298
                        qDebug() <<"ValueFormat1 is null or both ValueFormat1 and ValueFormat2 are null";
299
                }
300
 
301
        }
302
        else
303
                qDebug() <<"unknown PosFormat"<<PosFormat;
304
}
305
 
306
KernFeature::ClassDefTable KernFeature::getClass ( quint16 classDefOffset, quint16 coverageId )
307
{
308
        ClassDefTable ret;
309
        ret[0] = coverages[coverageId];
310
        quint16 ClassFormat ( toUint16 ( classDefOffset ) );
311
        if ( ClassFormat == 1 )
312
        {
313
                quint16 StartGlyph ( toUint16 ( classDefOffset +2 ) );
314
                quint16 GlyphCount ( toUint16 ( classDefOffset +4 ) );
315
                quint16 ClassValueArray ( classDefOffset + 6 );
316
 
317
                for ( quint16 CV ( 0 );CV < GlyphCount; ++CV )
318
                {
319
                        ret[0].removeAll ( StartGlyph + CV );
320
                        ret[ toUint16 ( ClassValueArray + ( CV * 2 ) ) ] << StartGlyph + CV;
321
                }
322
        }
323
        else if ( ClassFormat == 2 )
324
        {
325
                quint16 ClassRangeCount ( toUint16 ( classDefOffset + 2 ) );
326
                quint16 ClassRangeRecord ( classDefOffset + 4 );
327
                for ( int CRR ( 0 ); CRR < ClassRangeCount; ++CRR )
328
                {
329
                        quint16 Start ( toUint16 ( ClassRangeRecord + ( CRR * 6 ) ) );
330
                        quint16 End ( toUint16 ( ClassRangeRecord + ( CRR * 6 ) + 2 ) );
331
                        quint16 Class ( toUint16 ( ClassRangeRecord + ( CRR * 6 ) + 4 ) );
332
 
333
                        for ( quint16 gl ( Start ); gl <= End; ++gl )
334
                        {
335
                                ret[0].removeAll ( gl );
336
                                ret[Class] << gl;
337
                        }
338
                }
339
        }
340
        else
341
                qDebug() <<"Unknown Class Table type";
342
 
343
        return ret;
344
}
345
 
346
quint16 KernFeature::toUint16 ( quint16 index )
347
{
348
        if ( ( index + 2 ) > GPOSTableRaw.count() )
349
        {
350
                qDebug() << "HORROR!" << index << GPOSTableRaw.count() << FontName ;
351
                // Rather no kerning at all than random kerning
352
//              m_valid = false;
353
                return 0;
354
        }
355
        // FIXME I just do not know how it has to be done *properly*
356
        quint16 c1 ( GPOSTableRaw.at ( index ) );
357
        quint16 c2 ( GPOSTableRaw.at ( index + 1 ) );
358
        c1 &= 0xFF;
359
        c2 &= 0xFF;
360
        quint16 ret ( ( c1 << 8 ) | c2 );
361
        return ret;
362
}
363
 
364
qint16 KernFeature::toInt16 ( quint16 index )
365
{
366
        if ( ( index + 2 ) > GPOSTableRaw.count() )
367
        {
368
                return 0;
369
        }
370
        // FIXME I just do not know how it has to be done *properly*
371
        quint16 c1 ( GPOSTableRaw.at ( index ) );
372
        quint16 c2 ( GPOSTableRaw.at ( index + 1 ) );
373
        c1 &= 0xFF;
374
        c2 &= 0xFF;
375
        qint16 ret ( ( c1 << 8 ) | c2 );
376
        return ret;
377
}
378
 
379
 
380
namespace
381
{
382
        uint word ( QByteArray const & bb, uint pos )
383
        {
384
                const unsigned char * pp = reinterpret_cast<const unsigned char*> ( bb.data() ) + pos;
385
                return pp[0] << 24 | pp[1] << 16 | pp[2] << 8 | pp[3];
386
        }
387
        uint word16 ( QByteArray const & bb, uint pos )
388
        {
389
                const unsigned char * pp = reinterpret_cast<const unsigned char*> ( bb.data() ) + pos;
390
                return pp[0] << 8 | pp[1];
391
        }
392
        QString tag ( QByteArray const & bb, uint pos )
393
        {
394
                char buf[5] = "1234";
395
                buf[0] = bb.data() [pos];
396
                buf[1] = bb.data() [pos+1];
397
                buf[2] = bb.data() [pos+2];
398
                buf[3] = bb.data() [pos+3];
399
                return buf;
400
        }
401
        bool copy ( QByteArray & dst, uint to, QByteArray & src, uint from, uint len )
402
        {
403
                if ( !dst.data() )
404
                        return false;
405
                if ( !src.data() )
406
                        return false;
407
                if ( to + len > static_cast<uint> ( dst.size() ) )
408
                        return false;
409
                if ( from + len > static_cast<uint> ( src.size() ) )
410
                        return false;
411
 
412
                memcpy ( dst.data() + to, src.data() + from, len );
413
                return true;
414
        }
5979 avox 415
} //namespace
416
 
13531 pierre 417
ScFace_ttf::ScFace_ttf ( QString fam, QString sty, QString alt, QString scname, QString psname, QString path, int face )
418
                : FtFace ( fam, sty, alt, scname, psname, path, face )
419
{
420
        formatCode = ScFace::SFNT;
421
        kernFeature = 0;
422
}
5979 avox 423
 
13531 pierre 424
ScFace_ttf::~ ScFace_ttf()
425
{
426
        if ( kernFeature )
427
                delete kernFeature;
428
}
429
 
430
 
431
void ScFace_ttf::load() const
432
{
433
        if ( !kernFeature )
434
                kernFeature = new KernFeature ( ftFace() );
435
        FtFace::load();
436
}
437
 
438
void ScFace_ttf::unload() const
439
{
440
        if ( kernFeature )
441
                delete kernFeature;
442
        kernFeature = 0;
443
        FtFace::unload();
444
}
445
 
446
 
447
void ScFace_ttf::RawData ( QByteArray & bb ) const
448
{
449
        if ( formatCode == ScFace::TTCF )
450
        {
5979 avox 451
                QByteArray coll;
13531 pierre 452
                FtFace::RawData ( coll );
5979 avox 453
                // access table for faceIndex
13531 pierre 454
                if ( faceIndex >= static_cast<int> ( word ( coll, 8 ) ) )
5979 avox 455
                {
13531 pierre 456
                        bb.resize ( 0 );
5979 avox 457
                        return;
458
                }
459
                static const uint OFFSET_TABLE_LEN = 12;
460
                static const uint   TDIR_ENTRY_LEN = 16;
13531 pierre 461
                uint faceOffset = word ( coll, 12 + 4 * faceIndex );
462
                uint nTables    = word16 ( coll, faceOffset + 4 );
463
                sDebug ( QObject::tr ( "extracting face %1 from font %2 (offset=%3, nTables=%4)" ).arg ( faceIndex ).arg ( fontFile ).arg ( faceOffset ).arg ( nTables ) );
5979 avox 464
                uint headerLength = OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * nTables;
465
                uint tableLengths = 0;
466
                // sum table lengths incl padding
13531 pierre 467
                for ( uint i=0; i < nTables; ++i )
5979 avox 468
                {
13531 pierre 469
                        tableLengths += word ( coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12 );
470
                        tableLengths = ( tableLengths+3 ) & ~3;
5979 avox 471
                }
13531 pierre 472
                bb.resize ( headerLength + tableLengths );
473
                if ( ! bb.data() )
5979 avox 474
                        return;
475
                // write header
13531 pierre 476
                sDebug ( QObject::tr ( "memcpy header: %1 %2 %3" ).arg ( 0 ).arg ( faceOffset ).arg ( headerLength ) );
477
                if ( !copy ( bb, 0, coll, faceOffset, headerLength ) )
5979 avox 478
                        return;
479
 
480
                uint pos = headerLength;
13531 pierre 481
                for ( uint i=0; i < nTables; ++i )
5979 avox 482
                {
13531 pierre 483
                        uint tableSize  = word ( coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12 );
484
                        uint tableStart = word ( coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8 );
485
                        sDebug ( QObject::tr ( "table '%1'" ).arg ( tag ( coll, tableStart ) ) );
486
                        sDebug ( QObject::tr ( "memcpy table: %1 %2 %3" ).arg ( pos ).arg ( tableStart ).arg ( tableSize ) );
487
                        if ( !copy ( bb, pos, coll, tableStart, tableSize ) ) break;
5979 avox 488
                        // write new offset to table entry
13531 pierre 489
                        sDebug ( QObject::tr ( "memcpy offset: %1 %2 %3" ).arg ( OFFSET_TABLE_LEN + TDIR_ENTRY_LEN*i + 8 ).arg ( pos ).arg ( 4 ) );
490
                        memcpy ( bb.data() + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8, &pos, 4 );
5979 avox 491
                        pos += tableSize;
492
                        // pad
13531 pierre 493
                        while ( ( pos & 3 ) != 0 )
494
                                bb.data() [pos++] = '\0';
5979 avox 495
                }
496
        }
13531 pierre 497
        else if ( formatCode == ScFace::TYPE42 )
498
        {
499
                FtFace::RawData ( bb );
5979 avox 500
        }
13531 pierre 501
        else
502
        {
503
                FtFace::RawData ( bb );
504
        }
5979 avox 505
}
506
 
13531 pierre 507
bool ScFace_ttf::EmbedFont ( QString &str ) const
5979 avox 508
{
13531 pierre 509
        if ( formatCode == ScFace::TYPE42 )
510
        {
5979 avox 511
                //easy:
512
                QByteArray bb;
13531 pierre 513
                FtFace::RawData ( bb );
5979 avox 514
                str += bb;
515
                return true;
516
        }
517
        QString tmp4;
518
        QString tmp2 = "";
519
        QString tmp3 = "";
520
        int counter = 0;
521
        char *buf[50];
522
        FT_ULong  charcode;
523
        FT_UInt   gindex;
524
        FT_Face face = ftFace();
13531 pierre 525
        if ( !face )
526
        {
5979 avox 527
                return false;
528
        }
529
        const FT_Stream fts = face->stream;
13531 pierre 530
        if ( ftIOFunc ( fts, 0L, NULL, 0 ) )
531
        {
532
                return ( false );
5979 avox 533
        }
534
        str+="%!PS-TrueTypeFont\n";
535
        str+="11 dict begin\n";
536
        str+="/FontName /" + psName + " def\n";
537
        str+="/Encoding /ISOLatin1Encoding where {pop ISOLatin1Encoding} {StandardEncoding} ifelse def\n";
538
        str+="/PaintType 0 def\n/FontMatrix [1 0 0 1 0 0] def\n";
539
        str+="/FontBBox ["+FontBBox+"] def\n";
540
        str+="/FontType 42 def\n";
541
        str+="/FontInfo 8 dict dup begin\n";
542
        str+="/FamilyName (" + psName + ") def\n";
543
        str+="end readonly def\n";
544
        unsigned char *tmp = new unsigned char[65535];
545
        int length;
546
        char linebuf[80];
547
        str += "/sfnts [";
548
        int poso=0;
13531 pierre 549
        do
550
        {
5979 avox 551
                int posi=0;
552
                length= fts->size - fts->pos;
13531 pierre 553
                if ( length > 65534 )
554
                {
5979 avox 555
                        length = 65534;
556
                }
13531 pierre 557
                if ( !ftIOFunc ( fts, 0L, tmp, length ) )
5979 avox 558
                {
559
                        str+="\n<\n";
13531 pierre 560
                        for ( int j = 0; j < length; j++ )
5979 avox 561
                        {
562
                                unsigned char u=tmp[posi];
13531 pierre 563
                                linebuf[poso]= ( ( u >> 4 ) & 15 ) + '0';
564
                                if ( u>0x9f ) linebuf[poso]+='a'-':';
5979 avox 565
                                ++poso;
566
                                u&=15; linebuf[poso]=u + '0';
13531 pierre 567
                                if ( u>0x9 ) linebuf[poso]+='a'-':';
5979 avox 568
                                ++posi;
569
                                ++poso;
13531 pierre 570
                                if ( poso > 70 )
5979 avox 571
                                {
572
                                        linebuf[poso++]='\n';
573
                                        linebuf[poso++]=0;
574
                                        str += linebuf;
575
                                        poso = 0;
576
                                }
577
                        }
578
                        linebuf[poso++]=0;
579
                        str += linebuf;
580
                        poso = 0;
581
                        str += "00\n>";
582
                }
13531 pierre 583
                else
584
                {
585
                        sDebug ( QObject::tr ( "Font %1 is broken (read stream), no embedding" ).arg ( fontFile ) );
5979 avox 586
                        str += "\n] def\n";
13531 pierre 587
                        status = qMax ( status,ScFace::BROKENGLYPHS );
5979 avox 588
                        return false;
589
                }
13531 pierre 590
        }
591
        while ( length==65534 );
592
 
5979 avox 593
        str += "\n] def\n";
9556 avox 594
        delete[] tmp;
5979 avox 595
        gindex = 0;
13531 pierre 596
        charcode = FT_Get_First_Char ( face, &gindex );
597
        while ( gindex != 0 )
5979 avox 598
        {
13531 pierre 599
                FT_Get_Glyph_Name ( face, gindex, buf, 50 );
600
                tmp2 += "/"+QString ( reinterpret_cast<char*> ( buf ) ) +" "+tmp3.setNum ( gindex ) +" def\n";
601
                charcode = FT_Get_Next_Char ( face, charcode, &gindex );
5979 avox 602
                counter++;
603
        }
13531 pierre 604
        tmp4.setNum ( counter );
5979 avox 605
        str += "/CharStrings " + tmp4 + " dict dup begin\n"+tmp2;
606
        str += "end readonly def\n";
607
        str += "FontName currentdict end definefont pop\n";
13531 pierre 608
        return ( true );
5979 avox 609
}
610
 
13531 pierre 611
qreal ScFace_ttf::glyphKerning ( uint gl1, uint gl2, qreal sz ) const
612
{
613
        if ( kernFeature->isValid() )
614
        {
615
                return kernFeature->getPairValue ( gl1,gl2 ) / m_uniEM * sz;
616
 
617
        }
618
        else
619
                return FtFace::glyphKerning ( gl1, gl2, sz );
620
}
621
 
622