Subversion Repositories Scribus

Rev

Rev 13340 | Rev 13531 | 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>
5979 avox 11
 
12
#include <sys/types.h>
13
 
14
#include "fonts/scface_ttf.h"
15
#include "fonts/scfontmetrics.h"
16
#include "util.h"
17
#include "scconfig.h"
18
 
19
 
20
 
13345 pierre 21
namespace {
22
uint word(QByteArray const & bb, uint pos)
5979 avox 23
{
13345 pierre 24
        const unsigned char * pp = reinterpret_cast<const unsigned char*>(bb.data()) + pos;
25
        return pp[0] << 24 | pp[1] << 16 | pp[2] << 8 | pp[3];
5979 avox 26
}
13345 pierre 27
uint word16(QByteArray const & bb, uint pos)
5979 avox 28
{
13345 pierre 29
        const unsigned char * pp = reinterpret_cast<const unsigned char*>(bb.data()) + pos;
30
        return pp[0] << 8 | pp[1];
5979 avox 31
}
13345 pierre 32
QString tag(QByteArray const & bb, uint pos)
5979 avox 33
{
13345 pierre 34
        char buf[5] = "1234";
35
        buf[0] = bb.data()[pos];
36
        buf[1] = bb.data()[pos+1];
37
        buf[2] = bb.data()[pos+2];
38
        buf[3] = bb.data()[pos+3];
39
        return buf;
5979 avox 40
}
13345 pierre 41
bool copy(QByteArray & dst, uint to, QByteArray & src, uint from, uint len)
5979 avox 42
{
13345 pierre 43
        if (!dst.data())
44
                return false;
45
        if (!src.data())
46
                return false;
47
        if (to + len > static_cast<uint>(dst.size()))
48
                return false;
49
        if (from + len > static_cast<uint>(src.size()))
50
                return false;
51
 
52
        memcpy(dst.data() + to, src.data() + from, len);
53
        return true;
5979 avox 54
}
55
} //namespace
56
 
57
 
13345 pierre 58
void ScFace_ttf::RawData(QByteArray & bb) const {
59
        if (formatCode == ScFace::TTCF) {
5979 avox 60
                QByteArray coll;
13345 pierre 61
                FtFace::RawData(coll);
5979 avox 62
                // access table for faceIndex
13345 pierre 63
                if (faceIndex >= static_cast<int>(word(coll, 8)))
5979 avox 64
                {
13345 pierre 65
                        bb.resize(0);
5979 avox 66
                        return;
67
                }
68
                static const uint OFFSET_TABLE_LEN = 12;
69
                static const uint   TDIR_ENTRY_LEN = 16;
13345 pierre 70
                uint faceOffset = word(coll, 12 + 4 * faceIndex);
71
                uint nTables    = word16(coll, faceOffset + 4);
72
                sDebug(QObject::tr("extracting face %1 from font %2 (offset=%3, nTables=%4)").arg(faceIndex).arg(fontFile).arg(faceOffset).arg(nTables));
5979 avox 73
                uint headerLength = OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * nTables;
74
                uint tableLengths = 0;
75
                // sum table lengths incl padding
13345 pierre 76
                for (uint i=0; i < nTables; ++i)
5979 avox 77
                {
13345 pierre 78
                        tableLengths += word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12);
79
                        tableLengths = (tableLengths+3) & ~3;
5979 avox 80
                }
13345 pierre 81
                bb.resize(headerLength + tableLengths);
82
                if (! bb.data())
5979 avox 83
                        return;
84
                // write header
13345 pierre 85
                sDebug(QObject::tr("memcpy header: %1 %2 %3").arg(0).arg(faceOffset).arg(headerLength));
86
                if (!copy(bb, 0, coll, faceOffset, headerLength))
5979 avox 87
                        return;
88
 
89
                uint pos = headerLength;
13345 pierre 90
                for (uint i=0; i < nTables; ++i)
5979 avox 91
                {
13345 pierre 92
                        uint tableSize  = word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12);
93
                        uint tableStart = word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8);
94
                        sDebug(QObject::tr("table '%1'").arg(tag(coll, tableStart)));
95
                        sDebug(QObject::tr("memcpy table: %1 %2 %3").arg(pos).arg(tableStart).arg(tableSize));
96
                        if (!copy(bb, pos, coll, tableStart, tableSize)) break;
5979 avox 97
                        // write new offset to table entry
13345 pierre 98
                        sDebug(QObject::tr("memcpy offset: %1 %2 %3").arg(OFFSET_TABLE_LEN + TDIR_ENTRY_LEN*i + 8).arg(pos).arg(4));
99
                        memcpy(bb.data() + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8, &pos, 4);
5979 avox 100
                        pos += tableSize;
101
                        // pad
13345 pierre 102
                        while ((pos & 3) != 0)
103
                                bb.data()[pos++] = '\0';
5979 avox 104
                }
13345 pierre 105
        }      
106
        else if (formatCode == ScFace::TYPE42) {
107
                FtFace::RawData(bb);
5979 avox 108
        }
13345 pierre 109
        else {
110
                FtFace::RawData(bb);
5979 avox 111
        }
112
}
113
 
13345 pierre 114
bool ScFace_ttf::EmbedFont(QString &str) const
5979 avox 115
{
13345 pierre 116
        if (formatCode == ScFace::TYPE42) {
5979 avox 117
                //easy:
118
                QByteArray bb;
13345 pierre 119
                FtFace::RawData(bb);
5979 avox 120
                str += bb;
121
                return true;
122
        }
123
        QString tmp4;
124
        QString tmp2 = "";
125
        QString tmp3 = "";
126
        int counter = 0;
127
        char *buf[50];
128
        FT_ULong  charcode;
129
        FT_UInt   gindex;
130
        FT_Face face = ftFace();
13345 pierre 131
        if (!face) {
5979 avox 132
                return false;
133
        }
134
        const FT_Stream fts = face->stream;
13345 pierre 135
        if (ftIOFunc(fts, 0L, NULL, 0)) {
136
                return(false);
5979 avox 137
        }
138
        str+="%!PS-TrueTypeFont\n";
139
        str+="11 dict begin\n";
140
        str+="/FontName /" + psName + " def\n";
141
        str+="/Encoding /ISOLatin1Encoding where {pop ISOLatin1Encoding} {StandardEncoding} ifelse def\n";
142
        str+="/PaintType 0 def\n/FontMatrix [1 0 0 1 0 0] def\n";
143
        str+="/FontBBox ["+FontBBox+"] def\n";
144
        str+="/FontType 42 def\n";
145
        str+="/FontInfo 8 dict dup begin\n";
146
        str+="/FamilyName (" + psName + ") def\n";
147
        str+="end readonly def\n";
148
        unsigned char *tmp = new unsigned char[65535];
149
        int length;
150
        char linebuf[80];
151
        str += "/sfnts [";
152
        int poso=0;
13345 pierre 153
        do {
5979 avox 154
                int posi=0;
155
                length= fts->size - fts->pos;
13345 pierre 156
                if (length > 65534) {
5979 avox 157
                        length = 65534;
158
                }
13345 pierre 159
                if (!ftIOFunc(fts, 0L, tmp, length))
5979 avox 160
                {
161
                        str+="\n<\n";
13345 pierre 162
                        for (int j = 0; j < length; j++)
5979 avox 163
                        {
164
                                unsigned char u=tmp[posi];
13345 pierre 165
                                linebuf[poso]=((u >> 4) & 15) + '0';
166
                                if(u>0x9f) linebuf[poso]+='a'-':';
5979 avox 167
                                ++poso;
168
                                u&=15; linebuf[poso]=u + '0';
13345 pierre 169
                                if(u>0x9) linebuf[poso]+='a'-':';
5979 avox 170
                                ++posi;
171
                                ++poso;
13345 pierre 172
                                if (poso > 70)
5979 avox 173
                                {
174
                                        linebuf[poso++]='\n';
175
                                        linebuf[poso++]=0;
176
                                        str += linebuf;
177
                                        poso = 0;
178
                                }
179
                        }
180
                        linebuf[poso++]=0;
181
                        str += linebuf;
182
                        poso = 0;
183
                        str += "00\n>";
184
                }
13345 pierre 185
                else {
186
                        sDebug(QObject::tr("Font %1 is broken (read stream), no embedding").arg(fontFile));
5979 avox 187
                        str += "\n] def\n";
13345 pierre 188
                        status = qMax(status,ScFace::BROKENGLYPHS);
5979 avox 189
                        return false;
190
                }
13345 pierre 191
        } while (length==65534);
192
 
5979 avox 193
        str += "\n] def\n";
9556 avox 194
        delete[] tmp;
5979 avox 195
        gindex = 0;
13345 pierre 196
        charcode = FT_Get_First_Char(face, &gindex );
197
        while (gindex != 0)
5979 avox 198
        {
13345 pierre 199
                FT_Get_Glyph_Name(face, gindex, buf, 50);
200
                tmp2 += "/"+QString(reinterpret_cast<char*>(buf))+" "+tmp3.setNum(gindex)+" def\n";
201
                 charcode = FT_Get_Next_Char(face, charcode, &gindex );
5979 avox 202
                counter++;
203
        }
13345 pierre 204
        tmp4.setNum(counter);
5979 avox 205
        str += "/CharStrings " + tmp4 + " dict dup begin\n"+tmp2;
206
        str += "end readonly def\n";
207
        str += "FontName currentdict end definefont pop\n";
13345 pierre 208
        return(true);
5979 avox 209
}
210