Subversion Repositories Scribus

Rev

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