1 /*  GRAPHITE2 LICENSING
2 
3     Copyright 2010, SIL International
4     All rights reserved.
5 
6     This library is free software; you can redistribute it and/or modify
7     it under the terms of the GNU Lesser General Public License as published
8     by the Free Software Foundation; either version 2.1 of License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Lesser General Public License for more details.
15 
16     You should also have received a copy of the GNU Lesser General Public
17     License along with this library in the file named "LICENSE".
18     If not, write to the Free Software Foundation, 51 Franklin Street,
19     Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20     internet at http://www.fsf.org/licenses/lgpl.html.
21 
22 Alternatively, the contents of this file may be used under the terms of the
23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
24 License, as published by the Free Software Foundation, either version 2
25 of the License or (at your option) any later version.
26 */
27 #include <cstring>
28 #include "graphite2/Segment.h"
29 #include "inc/CmapCache.h"
30 #include "inc/debug.h"
31 #include "inc/Decompressor.h"
32 #include "inc/Endian.h"
33 #include "inc/Face.h"
34 #include "inc/FileFace.h"
35 #include "inc/GlyphFace.h"
36 #include "inc/json.h"
37 #include "inc/Segment.h"
38 #include "inc/NameTable.h"
39 #include "inc/Error.h"
40 
41 using namespace graphite2;
42 
43 namespace
44 {
45 enum compression
46 {
47     NONE,
48     LZ4
49 };
50 
51 }
52 
Face(const void * appFaceHandle,const gr_face_ops & ops)53 Face::Face(const void* appFaceHandle/*non-NULL*/, const gr_face_ops & ops)
54 : m_appFaceHandle(appFaceHandle),
55   m_pFileFace(NULL),
56   m_pGlyphFaceCache(NULL),
57   m_cmap(NULL),
58   m_pNames(NULL),
59   m_logger(NULL),
60   m_error(0), m_errcntxt(0),
61   m_silfs(NULL),
62   m_numSilf(0),
63   m_ascent(0),
64   m_descent(0)
65 {
66     memset(&m_ops, 0, sizeof m_ops);
67     memcpy(&m_ops, &ops, min(sizeof m_ops, ops.size));
68 }
69 
70 
~Face()71 Face::~Face()
72 {
73     setLogger(0);
74     delete m_pGlyphFaceCache;
75     delete m_cmap;
76     delete[] m_silfs;
77 #ifndef GRAPHITE2_NFILEFACE
78     delete m_pFileFace;
79 #endif
80     delete m_pNames;
81 }
82 
default_glyph_advance(const void * font_ptr,gr_uint16 glyphid)83 float Face::default_glyph_advance(const void* font_ptr, gr_uint16 glyphid)
84 {
85     const Font & font = *reinterpret_cast<const Font *>(font_ptr);
86 
87     return font.face().glyphs().glyph(glyphid)->theAdvance().x * font.scale();
88 }
89 
readGlyphs(uint32 faceOptions)90 bool Face::readGlyphs(uint32 faceOptions)
91 {
92     Error e;
93 #ifdef GRAPHITE2_TELEMETRY
94     telemetry::category _glyph_cat(tele.glyph);
95 #endif
96     error_context(EC_READGLYPHS);
97     m_pGlyphFaceCache = new GlyphCache(*this, faceOptions);
98 
99     if (e.test(!m_pGlyphFaceCache, E_OUTOFMEM)
100         || e.test(m_pGlyphFaceCache->numGlyphs() == 0, E_NOGLYPHS)
101         || e.test(m_pGlyphFaceCache->unitsPerEm() == 0, E_BADUPEM))
102     {
103         return error(e);
104     }
105 
106     if (faceOptions & gr_face_cacheCmap)
107         m_cmap = new CachedCmap(*this);
108     else
109         m_cmap = new DirectCmap(*this);
110     if (e.test(!m_cmap, E_OUTOFMEM) || e.test(!*m_cmap, E_BADCMAP))
111         return error(e);
112 
113     if (faceOptions & gr_face_preloadGlyphs)
114         nameTable();        // preload the name table along with the glyphs.
115 
116     return true;
117 }
118 
readGraphite(const Table & silf)119 bool Face::readGraphite(const Table & silf)
120 {
121 #ifdef GRAPHITE2_TELEMETRY
122     telemetry::category _silf_cat(tele.silf);
123 #endif
124     Error e;
125     error_context(EC_READSILF);
126     const byte * p = silf;
127     if (e.test(!p, E_NOSILF) || e.test(silf.size() < 20, E_BADSIZE)) return error(e);
128 
129     const uint32 version = be::read<uint32>(p);
130     if (e.test(version < 0x00020000, E_TOOOLD)) return error(e);
131     if (version >= 0x00030000)
132         be::skip<uint32>(p);        // compilerVersion
133     m_numSilf = be::read<uint16>(p);
134 
135     be::skip<uint16>(p);            // reserved
136 
137     bool havePasses = false;
138     m_silfs = new Silf[m_numSilf];
139     if (e.test(!m_silfs, E_OUTOFMEM)) return error(e);
140     for (int i = 0; i < m_numSilf; i++)
141     {
142         error_context(EC_ASILF + (i << 8));
143         const uint32 offset = be::read<uint32>(p),
144                      next   = i == m_numSilf - 1 ? uint32(silf.size()) : be::peek<uint32>(p);
145         if (e.test(next > silf.size() || offset >= next, E_BADSIZE))
146             return error(e);
147 
148         if (!m_silfs[i].readGraphite(silf + offset, next - offset, *this, version))
149             return false;
150 
151         if (m_silfs[i].numPasses())
152             havePasses = true;
153     }
154 
155     return havePasses;
156 }
157 
readFeatures()158 bool Face::readFeatures()
159 {
160     return m_Sill.readFace(*this);
161 }
162 
runGraphite(Segment * seg,const Silf * aSilf) const163 bool Face::runGraphite(Segment *seg, const Silf *aSilf) const
164 {
165 #if !defined GRAPHITE2_NTRACING
166     json * dbgout = logger();
167     if (dbgout)
168     {
169         *dbgout << json::object
170                     << "id"         << objectid(seg)
171                     << "passes"     << json::array;
172     }
173 #endif
174 
175 //    if ((seg->dir() & 1) != aSilf->dir())
176 //        seg->reverseSlots();
177     if ((seg->dir() & 3) == 3 && aSilf->bidiPass() == 0xFF)
178         seg->doMirror(aSilf->aMirror());
179     bool res = aSilf->runGraphite(seg, 0, aSilf->positionPass(), true);
180     if (res)
181     {
182         seg->associateChars(0, seg->charInfoCount());
183         if (aSilf->flags() & 0x20)
184             res &= seg->initCollisions();
185         if (res)
186             res &= aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false);
187     }
188 
189 #if !defined GRAPHITE2_NTRACING
190     if (dbgout)
191 {
192         seg->positionSlots(0, 0, 0, seg->currdir());
193         *dbgout             << json::item
194                             << json::close // Close up the passes array
195                 << "outputdir" << (seg->currdir() ? "rtl" : "ltr")
196                 << "output" << json::array;
197         for(Slot * s = seg->first(); s; s = s->next())
198             *dbgout     << dslot(seg, s);
199         *dbgout         << json::close
200                 << "advance" << seg->advance()
201                 << "chars"   << json::array;
202         for(size_t i = 0, n = seg->charInfoCount(); i != n; ++i)
203             *dbgout     << json::flat << *seg->charinfo(int(i));
204         *dbgout         << json::close  // Close up the chars array
205                     << json::close;     // Close up the segment object
206     }
207 #endif
208 
209     return res;
210 }
211 
setLogger(FILE * log_file GR_MAYBE_UNUSED)212 void Face::setLogger(FILE * log_file GR_MAYBE_UNUSED)
213 {
214 #if !defined GRAPHITE2_NTRACING
215     delete m_logger;
216     m_logger = log_file ? new json(log_file) : 0;
217 #endif
218 }
219 
chooseSilf(uint32 script) const220 const Silf *Face::chooseSilf(uint32 script) const
221 {
222     if (m_numSilf == 0)
223         return NULL;
224     else if (m_numSilf == 1 || script == 0)
225         return m_silfs;
226     else // do more work here
227         return m_silfs;
228 }
229 
findPseudo(uint32 uid) const230 uint16 Face::findPseudo(uint32 uid) const
231 {
232     return (m_numSilf) ? m_silfs[0].findPseudo(uid) : 0;
233 }
234 
getGlyphMetric(uint16 gid,uint8 metric) const235 int32 Face::getGlyphMetric(uint16 gid, uint8 metric) const
236 {
237     switch (metrics(metric))
238     {
239         case kgmetAscent : return m_ascent;
240         case kgmetDescent : return m_descent;
241         default:
242             if (gid >= glyphs().numGlyphs()) return 0;
243             return glyphs().glyph(gid)->getMetric(metric);
244     }
245 }
246 
takeFileFace(FileFace * pFileFace GR_MAYBE_UNUSED)247 void Face::takeFileFace(FileFace* pFileFace GR_MAYBE_UNUSED/*takes ownership*/)
248 {
249 #ifndef GRAPHITE2_NFILEFACE
250     if (m_pFileFace==pFileFace)
251       return;
252 
253     delete m_pFileFace;
254     m_pFileFace = pFileFace;
255 #endif
256 }
257 
nameTable() const258 NameTable * Face::nameTable() const
259 {
260     if (m_pNames) return m_pNames;
261     const Table name(*this, Tag::name);
262     if (name)
263         m_pNames = new NameTable(name, name.size());
264     return m_pNames;
265 }
266 
languageForLocale(const char * locale) const267 uint16 Face::languageForLocale(const char * locale) const
268 {
269     nameTable();
270     if (m_pNames)
271         return m_pNames->getLanguageId(locale);
272     return 0;
273 }
274 
275 
276 
Table(const Face & face,const Tag n,uint32 version)277 Face::Table::Table(const Face & face, const Tag n, uint32 version) throw()
278 : _f(&face), _sz(0), _compressed(false)
279 {
280     _p = static_cast<const byte *>((*_f->m_ops.get_table)(_f->m_appFaceHandle, n, &_sz));
281 
282     if (!TtfUtil::CheckTable(n, _p, _sz))
283     {
284         release();     // Make sure we release the table buffer even if the table failed its checks
285         return;
286     }
287 
288     if (be::peek<uint32>(_p) >= version)
289         decompress();
290 }
291 
release()292 void Face::Table::release()
293 {
294     if (_compressed)
295         free(const_cast<byte *>(_p));
296     else if (_p && _f->m_ops.release_table)
297         (*_f->m_ops.release_table)(_f->m_appFaceHandle, _p);
298     _p = 0; _sz = 0;
299 }
300 
operator =(const Table && rhs)301 Face::Table & Face::Table::operator = (const Table && rhs) throw()
302 {
303     if (this == &rhs)   return *this;
304     release();
305     new (this) Table(std::move(rhs));
306     return *this;
307 }
308 
decompress()309 Error Face::Table::decompress()
310 {
311     Error e;
312     if (e.test(_sz < 5 * sizeof(uint32), E_BADSIZE))
313         return e;
314     byte * uncompressed_table = 0;
315     size_t uncompressed_size = 0;
316 
317     const byte * p = _p;
318     const uint32 version = be::read<uint32>(p);    // Table version number.
319 
320     // The scheme is in the top 5 bits of the 1st uint32.
321     const uint32 hdr = be::read<uint32>(p);
322     switch(compression(hdr >> 27))
323     {
324     case NONE: return e;
325 
326     case LZ4:
327     {
328         uncompressed_size  = hdr & 0x07ffffff;
329         uncompressed_table = gralloc<byte>(uncompressed_size);
330         if (!e.test(!uncompressed_table || uncompressed_size < 4, E_OUTOFMEM))
331         {
332             memset(uncompressed_table, 0, 4);   // make sure version number is initialised
333             // coverity[forward_null : FALSE] - uncompressed_table has been checked so can't be null
334             // coverity[checked_return : FALSE] - we test e later
335             e.test(lz4::decompress(p, _sz - 2*sizeof(uint32), uncompressed_table, uncompressed_size) != signed(uncompressed_size), E_SHRINKERFAILED);
336         }
337         break;
338     }
339 
340     default:
341         e.error(E_BADSCHEME);
342     };
343 
344     // Check the uncompressed version number against the original.
345     if (!e)
346         // coverity[forward_null : FALSE] - uncompressed_table has already been tested so can't be null
347         // coverity[checked_return : FALSE] - we test e later
348         e.test(be::peek<uint32>(uncompressed_table) != version, E_SHRINKERFAILED);
349 
350     // Tell the provider to release the compressed form since were replacing
351     //   it anyway.
352     release();
353 
354     if (e)
355     {
356         free(uncompressed_table);
357         uncompressed_table = 0;
358         uncompressed_size  = 0;
359     }
360 
361     _p = uncompressed_table;
362     _sz = uncompressed_size;
363     _compressed = true;
364 
365     return e;
366 }
367