1 /*
2 * FTGL - OpenGL font library
3 *
4 * Copyright (c) 2001-2004 Henry Maddocks <ftgl@opengl.geek.nz>
5 * Copyright (c) 2008 Sam Hocevar <sam@hocevar.net>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 #include "config.h"
28
29 #include "FTFace.h"
30 #include "FTCleanup.h"
31 #include "FTGL/FTLibrary.h"
32
33 #include FT_TRUETYPE_TABLES_H
34
FTFace(const char * fontFilePath,bool precomputeKerning)35 FTFace::FTFace(const char* fontFilePath, bool precomputeKerning)
36 : numGlyphs(0),
37 fontEncodingList(0),
38 kerningCache(0),
39 err(0)
40 {
41 const FT_Long DEFAULT_FACE_INDEX = 0;
42 ftFace = new FT_Face;
43
44 err = FT_New_Face(*FTLibrary::Instance().GetLibrary(), fontFilePath,
45 DEFAULT_FACE_INDEX, ftFace);
46 if(err)
47 {
48 delete ftFace;
49 ftFace = 0;
50 return;
51 }
52
53 FTCleanup::Instance()->RegisterObject(&ftFace);
54
55 numGlyphs = (*ftFace)->num_glyphs;
56 hasKerningTable = (FT_HAS_KERNING((*ftFace)) != 0);
57
58 if(hasKerningTable && precomputeKerning)
59 {
60 BuildKerningCache();
61 }
62 }
63
64
FTFace(const unsigned char * pBufferBytes,size_t bufferSizeInBytes,bool precomputeKerning)65 FTFace::FTFace(const unsigned char *pBufferBytes, size_t bufferSizeInBytes,
66 bool precomputeKerning)
67 : numGlyphs(0),
68 fontEncodingList(0),
69 kerningCache(0),
70 err(0)
71 {
72 const FT_Long DEFAULT_FACE_INDEX = 0;
73 ftFace = new FT_Face;
74
75 err = FT_New_Memory_Face(*FTLibrary::Instance().GetLibrary(),
76 (FT_Byte const *)pBufferBytes, (FT_Long)bufferSizeInBytes,
77 DEFAULT_FACE_INDEX, ftFace);
78 if(err)
79 {
80 delete ftFace;
81 ftFace = 0;
82 return;
83 }
84
85 FTCleanup::Instance()->RegisterObject(&ftFace);
86
87 numGlyphs = (*ftFace)->num_glyphs;
88 hasKerningTable = (FT_HAS_KERNING((*ftFace)) != 0);
89
90 if(hasKerningTable && precomputeKerning)
91 {
92 BuildKerningCache();
93 }
94 }
95
96
~FTFace()97 FTFace::~FTFace()
98 {
99 delete[] kerningCache;
100
101 if(ftFace)
102 {
103 FTCleanup::Instance()->UnregisterObject(&ftFace);
104
105 FT_Done_Face(*ftFace);
106 delete ftFace;
107 ftFace = 0;
108 }
109 }
110
111
Attach(const char * fontFilePath)112 bool FTFace::Attach(const char* fontFilePath)
113 {
114 err = FT_Attach_File(*ftFace, fontFilePath);
115 return !err;
116 }
117
118
Attach(const unsigned char * pBufferBytes,size_t bufferSizeInBytes)119 bool FTFace::Attach(const unsigned char *pBufferBytes,
120 size_t bufferSizeInBytes)
121 {
122 FT_Open_Args open;
123
124 open.flags = FT_OPEN_MEMORY;
125 open.memory_base = (FT_Byte const *)pBufferBytes;
126 open.memory_size = (FT_Long)bufferSizeInBytes;
127
128 err = FT_Attach_Stream(*ftFace, &open);
129 return !err;
130 }
131
132
Size(const unsigned int size,const unsigned int res)133 const FTSize& FTFace::Size(const unsigned int size, const unsigned int res)
134 {
135 charSize.CharSize(ftFace, size, res, res);
136 err = charSize.Error();
137
138 return charSize;
139 }
140
141
CharMapCount() const142 unsigned int FTFace::CharMapCount() const
143 {
144 return (*ftFace)->num_charmaps;
145 }
146
147
CharMapList()148 FT_Encoding* FTFace::CharMapList()
149 {
150 if(0 == fontEncodingList)
151 {
152 fontEncodingList = new FT_Encoding[CharMapCount()];
153 for(size_t i = 0; i < CharMapCount(); ++i)
154 {
155 fontEncodingList[i] = (*ftFace)->charmaps[i]->encoding;
156 }
157 }
158
159 return fontEncodingList;
160 }
161
162
KernAdvance(unsigned int index1,unsigned int index2)163 FTPoint FTFace::KernAdvance(unsigned int index1, unsigned int index2)
164 {
165 FTGL_DOUBLE x, y;
166
167 if(!hasKerningTable || !index1 || !index2)
168 {
169 return FTPoint(0.0, 0.0);
170 }
171
172 if(kerningCache && index1 < FTFace::MAX_PRECOMPUTED
173 && index2 < FTFace::MAX_PRECOMPUTED)
174 {
175 x = kerningCache[2 * (index2 * FTFace::MAX_PRECOMPUTED + index1)];
176 y = kerningCache[2 * (index2 * FTFace::MAX_PRECOMPUTED + index1) + 1];
177 return FTPoint(x, y);
178 }
179
180 FT_Vector kernAdvance;
181 kernAdvance.x = kernAdvance.y = 0;
182
183 err = FT_Get_Kerning(*ftFace, index1, index2, ft_kerning_unfitted,
184 &kernAdvance);
185 if(err)
186 {
187 return FTPoint(0.0f, 0.0f);
188 }
189
190 x = static_cast<float>(kernAdvance.x) / 64.0f;
191 y = static_cast<float>(kernAdvance.y) / 64.0f;
192
193 return FTPoint(x, y);
194 }
195
196
Glyph(unsigned int index,FT_Int load_flags)197 FT_GlyphSlot FTFace::Glyph(unsigned int index, FT_Int load_flags)
198 {
199 err = FT_Load_Glyph(*ftFace, index, load_flags);
200 if(err)
201 {
202 return NULL;
203 }
204
205 return (*ftFace)->glyph;
206 }
207
208
BuildKerningCache()209 void FTFace::BuildKerningCache()
210 {
211 FT_Vector kernAdvance;
212 kernAdvance.x = 0;
213 kernAdvance.y = 0;
214 kerningCache = new FTGL_DOUBLE[FTFace::MAX_PRECOMPUTED
215 * FTFace::MAX_PRECOMPUTED * 2];
216 for(unsigned int j = 0; j < FTFace::MAX_PRECOMPUTED; j++)
217 {
218 for(unsigned int i = 0; i < FTFace::MAX_PRECOMPUTED; i++)
219 {
220 err = FT_Get_Kerning(*ftFace, i, j, ft_kerning_unfitted,
221 &kernAdvance);
222 if(err)
223 {
224 delete[] kerningCache;
225 kerningCache = NULL;
226 return;
227 }
228
229 kerningCache[2 * (j * FTFace::MAX_PRECOMPUTED + i)] =
230 static_cast<FTGL_DOUBLE>(kernAdvance.x) / 64.0;
231 kerningCache[2 * (j * FTFace::MAX_PRECOMPUTED + i) + 1] =
232 static_cast<FTGL_DOUBLE>(kernAdvance.y) / 64.0;
233 }
234 }
235 }
236
237