Subversion Repositories Scribus

Rev

Rev 5979 | Rev 8495 | 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
 
8
#include <qfile.h>
9
#include <qstring.h>
10
#include <qobject.h>
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
 
21
namespace {
22
uint word(QByteArray const & bb, uint pos)
23
{
24
        unsigned char * pp = reinterpret_cast<unsigned char*>(bb.data()) + pos;
25
        return pp[0] << 24 | pp[1] << 16 | pp[2] << 8 | pp[3];
26
}
27
uint word16(QByteArray const & bb, uint pos)
28
{
29
        unsigned char * pp = reinterpret_cast<unsigned char*>(bb.data()) + pos;
30
        return pp[0] << 8 | pp[1];
31
}
32
QString tag(QByteArray const & bb, uint pos)
33
{
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;
40
}
41
bool copy(QByteArray & dst, uint to, QByteArray & src, uint from, uint len)
42
{
43
        if (!dst.data())
44
                return false;
45
        if (!src.data())
46
                return false;
47
        if (to + len > dst.size())
48
                return false;
49
        if (from + len > src.size())
50
                return false;
51
 
52
        memcpy(dst.data() + to, src.data() + from, len);
53
        return true;
54
}
55
} //namespace
56
 
57
 
6307 avox 58
void ScFace_ttf::RawData(QByteArray & bb) const {
5979 avox 59
        if (formatCode == ScFace::TTCF) {
60
                QByteArray coll;
61
                FtFace::RawData(coll);
62
                // access table for faceIndex
63
                if (faceIndex >= static_cast<int>(word(coll, 8)))
64
                {
65
                        bb.resize(0);
66
                        return;
67
                }
68
                static const uint OFFSET_TABLE_LEN = 12;
69
                static const uint   TDIR_ENTRY_LEN = 16;
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));
73
                uint headerLength = OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * nTables;
74
                uint tableLengths = 0;
75
                // sum table lengths incl padding
76
                for (uint i=0; i < nTables; ++i)
77
                {
78
                        tableLengths += word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12);
79
                        tableLengths = (tableLengths+3) & ~3;
80
                }
81
                bb.resize(headerLength + tableLengths);
82
                if (! bb.data())
83
                        return;
84
                // write header
85
                sDebug(QObject::tr("memcpy header: %1 %2 %3").arg(0).arg(faceOffset).arg(headerLength));
86
                if (!copy(bb, 0, coll, faceOffset, headerLength))
87
                        return;
88
 
89
                uint pos = headerLength;
90
                for (uint i=0; i < nTables; ++i)
91
                {
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;
97
                        // write new offset to table entry
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);
100
                        pos += tableSize;
101
                        // pad
102
                        while ((pos & 3) != 0)
103
                                bb.data()[pos++] = '\0';
104
                }
105
        }      
106
        else if (formatCode == ScFace::TYPE42) {
107
                FtFace::RawData(bb);
108
        }
109
        else {
110
                FtFace::RawData(bb);
111
        }
112
}
113
 
6307 avox 114
bool ScFace_ttf::EmbedFont(QString &str) const
5979 avox 115
{
116
        if (formatCode == ScFace::TYPE42) {
117
                //easy:
118
                QByteArray bb;
119
                FtFace::RawData(bb);
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();
131
        if (!face) {
132
                return false;
133
        }
134
        const FT_Stream fts = face->stream;
135
        if (ftIOFunc(fts, 0L, NULL, 0)) {
136
                return(false);
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;
153
        do {
154
                int posi=0;
155
                length= fts->size - fts->pos;
156
                if (length > 65534) {
157
                        length = 65534;
158
                }
159
                if (!ftIOFunc(fts, 0L, tmp, length))
160
                {
161
                        str+="\n<\n";
162
                        for (int j = 0; j < length; j++)
163
                        {
164
                                unsigned char u=tmp[posi];
165
                                linebuf[poso]=((u >> 4) & 15) + '0';
166
                                if(u>0x9f) linebuf[poso]+='a'-':';
167
                                ++poso;
168
                                u&=15; linebuf[poso]=u + '0';
169
                                if(u>0x9) linebuf[poso]+='a'-':';
170
                                ++posi;
171
                                ++poso;
172
                                if (poso > 70)
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
                }
185
                else {
186
                        sDebug(QObject::tr("Font %1 is broken (read stream), no embedding").arg(fontFile).arg(gindex));
187
                        str += "\n] def\n";
188
                        status = QMAX(status,ScFace::BROKENGLYPHS);
189
                        return false;
190
                }
191
        } while (length==65534);
192
 
193
        str += "\n] def\n";
194
        delete tmp;
195
        gindex = 0;
196
        charcode = FT_Get_First_Char(face, &gindex );
197
        while (gindex != 0)
198
        {
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 );
202
                counter++;
203
        }
204
        tmp4.setNum(counter);
205
        str += "/CharStrings " + tmp4 + " dict dup begin\n"+tmp2;
206
        str += "end readonly def\n";
207
        str += "FontName currentdict end definefont pop\n";
208
        return(true);
209
}
210