w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Face.cpp
Go to the documentation of this file.
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 
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 
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 
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 
90 bool Face::readGlyphs(uint32 faceOptions)
91 {
92  Error e;
93 #ifdef GRAPHITE2_TELEMETRY
94  telemetry::category _glyph_cat(tele.glyph);
95 #endif
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 
119 bool Face::readGraphite(const Table & silf)
120 {
121 #ifdef GRAPHITE2_TELEMETRY
122  telemetry::category _silf_cat(tele.silf);
123 #endif
124  Error e;
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 
158 bool Face::readFeatures()
159 {
160  return m_Sill.readFace(*this);
161 }
162 
163 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 
213 {
214 #if !defined GRAPHITE2_NTRACING
215  delete m_logger;
216  m_logger = log_file ? new json(log_file) : 0;
217 #endif
218 }
219 
220 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 
230 uint16 Face::findPseudo(uint32 uid) const
231 {
232  return (m_numSilf) ? m_silfs[0].findPseudo(uid) : 0;
233 }
234 
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 
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 
258 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 
267 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 
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 
293 {
294  if (_compressed)
295  free(const_cast<byte *>(_p));
296  else if (_p && _f->m_ops.release_table)
298  _p = 0; _sz = 0;
299 }
300 
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 
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 }
#define name
#define next(a)
Definition: aptex-macros.h:924
static internal_font_number font_ptr
Definition: aptex.h:490
Definition: Endian.h:47
Table & operator=(const Table &&rhs)
const byte * _p
Definition: Face.h:172
const Face * _f
Definition: Face.h:171
void setLogger(FILE *log_file)
uint16 languageForLocale(const char *locale) const
Definition: Face.cpp:267
gr_face_ops m_ops
Definition: Face.h:102
void takeFileFace(FileFace *pFileFace)
int32 getGlyphMetric(uint16 gid, uint8 metric) const
Definition: Face.cpp:235
virtual bool runGraphite(Segment *seg, const Silf *silf) const
Definition: Face.cpp:163
Cmap * m_cmap
Definition: Face.h:106
FileFace * m_pFileFace
Definition: Face.h:104
bool readGraphite(const Table &silf)
Definition: Face.cpp:119
uint16 m_ascent
Definition: Face.h:115
SillMap m_Sill
Definition: Face.h:101
json * m_logger
Definition: Face.h:108
unsigned int error() const
Definition: Face.h:94
const Silf * chooseSilf(uint32 script) const
Definition: Face.cpp:220
const void * m_appFaceHandle
Definition: Face.h:103
const GlyphCache & glyphs() const
Definition: Face.h:150
unsigned int error_context() const
Definition: Face.h:96
uint16 m_numSilf
Definition: Face.h:113
uint16 m_descent
Definition: Face.h:116
NameTable * m_pNames
Definition: Face.h:107
bool readFeatures()
Definition: Face.cpp:158
GlyphCache * m_pGlyphFaceCache
Definition: Face.h:105
Silf * m_silfs
Definition: Face.h:112
NameTable * nameTable() const
Definition: Face.cpp:258
uint16 findPseudo(uint32 uid) const
Definition: Face.cpp:230
static float default_glyph_advance(const void *face_ptr, gr_uint16 glyphid)
Definition: Face.cpp:83
bool readGlyphs(uint32 faceOptions)
Definition: Face.cpp:90
json * logger() const
Definition: Face.h:162
unsigned short unitsPerEm() const
Definition: GlyphCache.h:142
unsigned short numGlyphs() const
Definition: GlyphCache.h:130
const GlyphFace * glyph(unsigned short glyphid) const
Definition: GlyphCache.cpp:216
int32 getMetric(uint8 metric) const
Definition: GlyphFace.cpp:32
uint16 getLanguageId(const char *bcp47Locale)
Definition: NameTable.cpp:216
uint8 bidiPass() const
Definition: Silf.h:92
uint8 aMirror() const
Definition: Silf.h:85
uint8 positionPass() const
Definition: Silf.h:90
uint16 findPseudo(uint32 uid) const
Definition: Silf.cpp:305
uint8 numPasses() const
Definition: Silf.h:93
byte flags() const
Definition: Silf.h:96
bool runGraphite(Segment *seg, uint8 firstPass=0, uint8 lastPass=0, int dobidi=0) const
Definition: Silf.cpp:357
bool readFace(const Face &face)
Definition: FeatureMap.cpp:190
static void close(json &)
Definition: json.cpp:108
static void flat(json &)
Definition: json.cpp:107
static void array(json &)
Definition: json.cpp:110
static void object(json &)
Definition: json.cpp:109
static void item(json &)
Definition: json.cpp:111
#define n
Definition: t4ht.c:1290
#define free(a)
Definition: decNumber.cpp:310
int compression
struct move_struct move
struct _gcache GlyphCache
#define s
Definition: afcover.h:80
#define memcpy(d, s, n)
Definition: gsftopk.c:64
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 xE2 xB2 x9E xE2 xB2 x9F xD0 xBE xD0 x9E xF0 x90 x90 x84 xF0 x90 x90 xAC xE1 x83 x98 xE1 x83 x94 xE1 x83 x90 xE1 xB2 xBF xE2 xB0 x95 xE2 xB1 x85 xCE xBF xCE x9F xE0 xA8 xA0 xE0 xA8 xB0 xE0 xA9 xA6 Kayah xEA xA4 x8D xEA xA4 x80 Khmer xE1 xA7 xA1 xE1 xA7 xAA xE0 xBB x90 Latin Subscript xE2 x82 x92 xE2 x82 x80 xEA x93 xB3 xF0 x96 xB9 xA1 xF0 x96 xB9 x9B xF0 x96 xB9 xAF xE1 x80 x9D xE1 x80 x84 xE1 x80 x82 no script
Definition: afscript.h:271
FT_Face face
Definition: cffdrivr.c:659
unsigned short uint16
Definition: tiff.h:62
unsigned long uint32
Definition: tiff.h:68
long int32
Definition: tiff.h:67
unsigned char uint8
Definition: tiff.h:60
hb_face_t * Face
Definition: luaharfbuzz.h:13
string release
Definition: conf.py:29
bool CheckTable(const Tag TableId, const void *pTable, size_t lTableSize)
Definition: TtfUtil.cpp:228
Definition: bits.h:30
@ kgmetAscent
Definition: GlyphFace.h:40
@ kgmetDescent
Definition: GlyphFace.h:40
@ E_SHRINKERFAILED
Definition: Error.h:131
@ E_BADCMAP
Definition: Error.h:63
@ E_TOOOLD
Definition: Error.h:65
@ E_NOGLYPHS
Definition: Error.h:61
@ E_OUTOFMEM
Definition: Error.h:60
@ E_NOSILF
Definition: Error.h:64
@ E_BADSIZE
Definition: Error.h:66
@ E_BADUPEM
Definition: Error.h:62
@ E_BADSCHEME
Definition: Error.h:130
@ EC_READGLYPHS
Definition: Error.h:48
@ EC_READSILF
Definition: Error.h:49
@ EC_ASILF
Definition: Error.h:50
std::pair< const Segment *const, const Slot *const > dslot
Definition: debug.h:45
gr_uint32 uint32
Definition: Main.h:41
int decompress(void const *in, size_t in_size, void *out, size_t out_size)
#define version
Definition: nup.c:10
#define min(a, b)
Definition: pbmplus.h:223
#define res(length)
Definition: picttoppm.c:287
#define NONE
Definition: pngtopnm.c:48
static int offset
Definition: ppmtogif.c:642
bstring c int memset(void *s, int c, int length)
@ gr_face_preloadGlyphs
Definition: Font.h:62
@ gr_face_cacheCmap
Definition: Font.h:64
unsigned short gr_uint16
Definition: Types.h:34
#define GR_MAYBE_UNUSED
Definition: Main.h:172
struct Table Table
ShellFileEnvironment e
Definition: sh6.c:388
Definition: lobject.h:497
Definition: pbmfont.h:11
struct glyph * glyph[256]
Definition: pbmfont.h:14
int x
Definition: pbmfont.h:6
gr_release_table_fn release_table
Definition: Font.h:116
size_t size
Definition: Font.h:111
Definition: sh2.c:920
Definition: gd.c:2418
#define FILE
Definition: t1stdio.h:34
static FILE * log_file
Definition: tex4ht.c:1100
Definition: alloca.c:152
static const char * locale
Definition: uresb.c:52
#define peek(p, c)
Definition: y.tab.c:10311