1 /* GRAPHITE2 LICENSING
2
3 Copyright 2012, 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 "graphite2/Font.h"
28
29 #include "inc/Main.h"
30 #include "inc/Face.h" //for the tags
31 #include "inc/GlyphCache.h"
32 #include "inc/GlyphFace.h"
33 #include "inc/Endian.h"
34 #include "inc/bits.h"
35
36 using namespace graphite2;
37
38 namespace
39 {
40 // Iterator over version 1 or 2 glat entries which consist of a series of
41 // +-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+
42 // v1 |k|n|v1 |v2 |...|vN | or v2 | k | n |v1 |v2 |...|vN |
43 // +-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+
44 // variable length structures.
45
46 template<typename W>
47 class _glat_iterator : public std::iterator<std::input_iterator_tag, std::pair<sparse::key_type, sparse::mapped_type> >
48 {
key() const49 unsigned short key() const { return uint16(be::peek<W>(_e) + _n); }
run() const50 unsigned int run() const { return be::peek<W>(_e+sizeof(W)); }
advance_entry()51 void advance_entry() { _n = 0; _e = _v; be::skip<W>(_v,2); }
52 public:
_glat_iterator(const void * glat=0)53 _glat_iterator(const void * glat=0) : _e(reinterpret_cast<const byte *>(glat)), _v(_e+2*sizeof(W)), _n(0) {}
54
operator ++()55 _glat_iterator<W> & operator ++ () {
56 ++_n; be::skip<uint16>(_v);
57 if (_n == run()) advance_entry();
58 return *this;
59 }
operator ++(int)60 _glat_iterator<W> operator ++ (int) { _glat_iterator<W> tmp(*this); operator++(); return tmp; }
61
62 // This is strictly a >= operator. A true == operator could be
63 // implemented that test for overlap but it would be more expensive a
64 // test.
operator ==(const _glat_iterator<W> & rhs)65 bool operator == (const _glat_iterator<W> & rhs) { return _v >= rhs._e - 1; }
operator !=(const _glat_iterator<W> & rhs)66 bool operator != (const _glat_iterator<W> & rhs) { return !operator==(rhs); }
67
operator *() const68 value_type operator * () const {
69 return value_type(key(), be::peek<uint16>(_v));
70 }
71
72 protected:
73 const byte * _e, * _v;
74 size_t _n;
75 };
76
77 typedef _glat_iterator<uint8> glat_iterator;
78 typedef _glat_iterator<uint16> glat2_iterator;
79 }
80
81 const SlantBox SlantBox::empty = {0,0,0,0};
82
83
84 class GlyphCache::Loader
85 {
86 public:
87 Loader(const Face & face); //return result indicates success. Do not use if failed.
88
89 operator bool () const throw();
90 unsigned short int units_per_em() const throw();
91 unsigned short int num_glyphs() const throw();
92 unsigned short int num_attrs() const throw();
93 bool has_boxes() const throw();
94
95 const GlyphFace * read_glyph(unsigned short gid, GlyphFace &, int *numsubs) const throw();
96 GlyphBox * read_box(uint16 gid, GlyphBox *curr, const GlyphFace & face) const throw();
97
98 CLASS_NEW_DELETE;
99 private:
100 Face::Table _head,
101 _hhea,
102 _hmtx,
103 _glyf,
104 _loca,
105 m_pGlat,
106 m_pGloc;
107
108 bool _long_fmt;
109 bool _has_boxes;
110 unsigned short _num_glyphs_graphics, //i.e. boundary box and advance
111 _num_glyphs_attributes,
112 _num_attrs; // number of glyph attributes per glyph
113 };
114
115
116
GlyphCache(const Face & face,const uint32 face_options)117 GlyphCache::GlyphCache(const Face & face, const uint32 face_options)
118 : _glyph_loader(new Loader(face)),
119 _glyphs(_glyph_loader && *_glyph_loader && _glyph_loader->num_glyphs()
120 ? grzeroalloc<const GlyphFace *>(_glyph_loader->num_glyphs()) : 0),
121 _boxes(_glyph_loader && _glyph_loader->has_boxes() && _glyph_loader->num_glyphs()
122 ? grzeroalloc<GlyphBox *>(_glyph_loader->num_glyphs()) : 0),
123 _num_glyphs(_glyphs ? _glyph_loader->num_glyphs() : 0),
124 _num_attrs(_glyphs ? _glyph_loader->num_attrs() : 0),
125 _upem(_glyphs ? _glyph_loader->units_per_em() : 0)
126 {
127 if ((face_options & gr_face_preloadGlyphs) && _glyph_loader && _glyphs)
128 {
129 int numsubs = 0;
130 GlyphFace * const glyphs = new GlyphFace [_num_glyphs];
131 if (!glyphs)
132 return;
133
134 // The 0 glyph is definately required.
135 _glyphs[0] = _glyph_loader->read_glyph(0, glyphs[0], &numsubs);
136
137 // glyphs[0] has the same address as the glyphs array just allocated,
138 // thus assigning the &glyphs[0] to _glyphs[0] means _glyphs[0] points
139 // to the entire array.
140 const GlyphFace * loaded = _glyphs[0];
141 for (uint16 gid = 1; loaded && gid != _num_glyphs; ++gid)
142 _glyphs[gid] = loaded = _glyph_loader->read_glyph(gid, glyphs[gid], &numsubs);
143
144 if (!loaded)
145 {
146 _glyphs[0] = 0;
147 delete [] glyphs;
148 }
149 else if (numsubs > 0 && _boxes)
150 {
151 GlyphBox * boxes = (GlyphBox *)gralloc<char>(_num_glyphs * sizeof(GlyphBox) + numsubs * 8 * sizeof(float));
152 GlyphBox * currbox = boxes;
153
154 for (uint16 gid = 0; currbox && gid != _num_glyphs; ++gid)
155 {
156 _boxes[gid] = currbox;
157 currbox = _glyph_loader->read_box(gid, currbox, *_glyphs[gid]);
158 }
159 if (!currbox)
160 {
161 free(boxes);
162 _boxes[0] = 0;
163 }
164 }
165 delete _glyph_loader;
166 _glyph_loader = 0;
167 // coverity[leaked_storage : FALSE] - calling read_glyph on index 0 saved
168 // glyphs as _glyphs[0]. Setting _glyph_loader to nullptr here flags that
169 // the dtor needs to call delete[] on _glyphs[0] to release what was allocated
170 // as glyphs
171 }
172
173 if (_glyphs && glyph(0) == 0)
174 {
175 free(_glyphs);
176 _glyphs = 0;
177 if (_boxes)
178 {
179 free(_boxes);
180 _boxes = 0;
181 }
182 _num_glyphs = _num_attrs = _upem = 0;
183 }
184 }
185
186
~GlyphCache()187 GlyphCache::~GlyphCache()
188 {
189 if (_glyphs)
190 {
191 if (_glyph_loader)
192 {
193 const GlyphFace * * g = _glyphs;
194 for(unsigned short n = _num_glyphs; n; --n, ++g)
195 delete *g;
196 }
197 else
198 delete [] _glyphs[0];
199 free(_glyphs);
200 }
201 if (_boxes)
202 {
203 if (_glyph_loader)
204 {
205 GlyphBox * * g = _boxes;
206 for (uint16 n = _num_glyphs; n; --n, ++g)
207 free(*g);
208 }
209 else
210 free(_boxes[0]);
211 free(_boxes);
212 }
213 delete _glyph_loader;
214 }
215
glyph(unsigned short glyphid) const216 const GlyphFace *GlyphCache::glyph(unsigned short glyphid) const //result may be changed by subsequent call with a different glyphid
217 {
218 if (glyphid >= numGlyphs())
219 return _glyphs[0];
220 const GlyphFace * & p = _glyphs[glyphid];
221 if (p == 0 && _glyph_loader)
222 {
223 int numsubs = 0;
224 GlyphFace * g = new GlyphFace();
225 if (g) p = _glyph_loader->read_glyph(glyphid, *g, &numsubs);
226 if (!p)
227 {
228 delete g;
229 return *_glyphs;
230 }
231 if (_boxes)
232 {
233 _boxes[glyphid] = (GlyphBox *)gralloc<char>(sizeof(GlyphBox) + 8 * numsubs * sizeof(float));
234 if (!_glyph_loader->read_box(glyphid, _boxes[glyphid], *_glyphs[glyphid]))
235 {
236 free(_boxes[glyphid]);
237 _boxes[glyphid] = 0;
238 }
239 }
240 }
241 return p;
242 }
243
244
245
Loader(const Face & face)246 GlyphCache::Loader::Loader(const Face & face)
247 : _head(face, Tag::head),
248 _hhea(face, Tag::hhea),
249 _hmtx(face, Tag::hmtx),
250 _glyf(face, Tag::glyf),
251 _loca(face, Tag::loca),
252 _long_fmt(false),
253 _has_boxes(false),
254 _num_glyphs_graphics(0),
255 _num_glyphs_attributes(0),
256 _num_attrs(0)
257 {
258 if (!operator bool())
259 return;
260
261 const Face::Table maxp = Face::Table(face, Tag::maxp);
262 if (!maxp) { _head = Face::Table(); return; }
263
264 _num_glyphs_graphics = static_cast<unsigned short>(TtfUtil::GlyphCount(maxp));
265 // This will fail if the number of glyphs is wildly out of range.
266 if (_glyf && TtfUtil::LocaLookup(_num_glyphs_graphics-1, _loca, _loca.size(), _head) == size_t(-2))
267 {
268 _head = Face::Table();
269 return;
270 }
271
272 if ((m_pGlat = Face::Table(face, Tag::Glat, 0x00030000)) == NULL
273 || (m_pGloc = Face::Table(face, Tag::Gloc)) == NULL
274 || m_pGloc.size() < 8)
275 {
276 _head = Face::Table();
277 return;
278 }
279 const byte * p = m_pGloc;
280 int version = be::read<uint32>(p);
281 const uint16 flags = be::read<uint16>(p);
282 _num_attrs = be::read<uint16>(p);
283 // We can accurately calculate the number of attributed glyphs by
284 // subtracting the length of the attribids array (numAttribs long if present)
285 // and dividing by either 2 or 4 depending on shor or lonf format
286 _long_fmt = flags & 1;
287 ptrdiff_t tmpnumgattrs = (m_pGloc.size()
288 - (p - m_pGloc)
289 - sizeof(uint16)*(flags & 0x2 ? _num_attrs : 0))
290 / (_long_fmt ? sizeof(uint32) : sizeof(uint16)) - 1;
291
292 if (version >= 0x00020000 || tmpnumgattrs < 0 || tmpnumgattrs > 65535
293 || _num_attrs == 0 || _num_attrs > 0x3000 // is this hard limit appropriate?
294 || _num_glyphs_graphics > tmpnumgattrs
295 || m_pGlat.size() < 4)
296 {
297 _head = Face::Table();
298 return;
299 }
300
301 _num_glyphs_attributes = static_cast<unsigned short>(tmpnumgattrs);
302 p = m_pGlat;
303 version = be::read<uint32>(p);
304 if (version >= 0x00040000 || (version >= 0x00030000 && m_pGlat.size() < 8)) // reject Glat tables that are too new
305 {
306 _head = Face::Table();
307 return;
308 }
309 else if (version >= 0x00030000)
310 {
311 unsigned int glatflags = be::read<uint32>(p);
312 _has_boxes = glatflags & 1;
313 // delete this once the compiler is fixed
314 _has_boxes = true;
315 }
316 }
317
318 inline
operator bool() const319 GlyphCache::Loader::operator bool () const throw()
320 {
321 return _head && _hhea && _hmtx && !(bool(_glyf) != bool(_loca));
322 }
323
324 inline
units_per_em() const325 unsigned short int GlyphCache::Loader::units_per_em() const throw()
326 {
327 return _head ? TtfUtil::DesignUnits(_head) : 0;
328 }
329
330 inline
num_glyphs() const331 unsigned short int GlyphCache::Loader::num_glyphs() const throw()
332 {
333 return max(_num_glyphs_graphics, _num_glyphs_attributes);
334 }
335
336 inline
num_attrs() const337 unsigned short int GlyphCache::Loader::num_attrs() const throw()
338 {
339 return _num_attrs;
340 }
341
342 inline
has_boxes() const343 bool GlyphCache::Loader::has_boxes () const throw()
344 {
345 return _has_boxes;
346 }
347
read_glyph(unsigned short glyphid,GlyphFace & glyph,int * numsubs) const348 const GlyphFace * GlyphCache::Loader::read_glyph(unsigned short glyphid, GlyphFace & glyph, int *numsubs) const throw()
349 {
350 Rect bbox;
351 Position advance;
352
353 if (glyphid < _num_glyphs_graphics)
354 {
355 int nLsb;
356 unsigned int nAdvWid;
357 if (_glyf)
358 {
359 int xMin, yMin, xMax, yMax;
360 size_t locidx = TtfUtil::LocaLookup(glyphid, _loca, _loca.size(), _head);
361 void *pGlyph = TtfUtil::GlyfLookup(_glyf, locidx, _glyf.size());
362
363 if (pGlyph && TtfUtil::GlyfBox(pGlyph, xMin, yMin, xMax, yMax))
364 {
365 if ((xMin > xMax) || (yMin > yMax))
366 return 0;
367 bbox = Rect(Position(static_cast<float>(xMin), static_cast<float>(yMin)),
368 Position(static_cast<float>(xMax), static_cast<float>(yMax)));
369 }
370 }
371 if (TtfUtil::HorMetrics(glyphid, _hmtx, _hmtx.size(), _hhea, nLsb, nAdvWid))
372 advance = Position(static_cast<float>(nAdvWid), 0);
373 }
374
375 if (glyphid < _num_glyphs_attributes)
376 {
377 const byte * gloc = m_pGloc;
378 size_t glocs = 0, gloce = 0;
379
380 be::skip<uint32>(gloc);
381 be::skip<uint16>(gloc,2);
382 if (_long_fmt)
383 {
384 if (8 + glyphid * sizeof(uint32) > m_pGloc.size())
385 return 0;
386 be::skip<uint32>(gloc, glyphid);
387 glocs = be::read<uint32>(gloc);
388 gloce = be::peek<uint32>(gloc);
389 }
390 else
391 {
392 if (8 + glyphid * sizeof(uint16) > m_pGloc.size())
393 return 0;
394 be::skip<uint16>(gloc, glyphid);
395 glocs = be::read<uint16>(gloc);
396 gloce = be::peek<uint16>(gloc);
397 }
398
399 if (glocs >= m_pGlat.size() - 1 || gloce > m_pGlat.size())
400 return 0;
401
402 const uint32 glat_version = be::peek<uint32>(m_pGlat);
403 if (glat_version >= 0x00030000)
404 {
405 if (glocs >= gloce)
406 return 0;
407 const byte * p = m_pGlat + glocs;
408 uint16 bmap = be::read<uint16>(p);
409 int num = bit_set_count((uint32)bmap);
410 if (numsubs) *numsubs += num;
411 glocs += 6 + 8 * num;
412 if (glocs > gloce)
413 return 0;
414 }
415 if (glat_version < 0x00020000)
416 {
417 if (gloce - glocs < 2*sizeof(byte)+sizeof(uint16)
418 || gloce - glocs > _num_attrs*(2*sizeof(byte)+sizeof(uint16)))
419 return 0;
420 new (&glyph) GlyphFace(bbox, advance, glat_iterator(m_pGlat + glocs), glat_iterator(m_pGlat + gloce));
421 }
422 else
423 {
424 if (gloce - glocs < 3*sizeof(uint16) // can a glyph have no attributes? why not?
425 || gloce - glocs > _num_attrs*3*sizeof(uint16)
426 || glocs > m_pGlat.size() - 2*sizeof(uint16))
427 return 0;
428 new (&glyph) GlyphFace(bbox, advance, glat2_iterator(m_pGlat + glocs), glat2_iterator(m_pGlat + gloce));
429 }
430 if (!glyph.attrs() || glyph.attrs().capacity() > _num_attrs)
431 return 0;
432 }
433 return &glyph;
434 }
435
scale_to(uint8 t,float zmin,float zmax)436 inline float scale_to(uint8 t, float zmin, float zmax)
437 {
438 return (zmin + t * (zmax - zmin) / 255);
439 }
440
readbox(Rect & b,uint8 zxmin,uint8 zymin,uint8 zxmax,uint8 zymax)441 Rect readbox(Rect &b, uint8 zxmin, uint8 zymin, uint8 zxmax, uint8 zymax)
442 {
443 return Rect(Position(scale_to(zxmin, b.bl.x, b.tr.x), scale_to(zymin, b.bl.y, b.tr.y)),
444 Position(scale_to(zxmax, b.bl.x, b.tr.x), scale_to(zymax, b.bl.y, b.tr.y)));
445 }
446
read_box(uint16 gid,GlyphBox * curr,const GlyphFace & glyph) const447 GlyphBox * GlyphCache::Loader::read_box(uint16 gid, GlyphBox *curr, const GlyphFace & glyph) const throw()
448 {
449 if (gid >= _num_glyphs_attributes) return 0;
450
451 const byte * gloc = m_pGloc;
452 size_t glocs = 0, gloce = 0;
453
454 be::skip<uint32>(gloc);
455 be::skip<uint16>(gloc,2);
456 if (_long_fmt)
457 {
458 be::skip<uint32>(gloc, gid);
459 glocs = be::read<uint32>(gloc);
460 gloce = be::peek<uint32>(gloc);
461 }
462 else
463 {
464 be::skip<uint16>(gloc, gid);
465 glocs = be::read<uint16>(gloc);
466 gloce = be::peek<uint16>(gloc);
467 }
468
469 if (gloce > m_pGlat.size() || glocs + 6 >= gloce)
470 return 0;
471
472 const byte * p = m_pGlat + glocs;
473 uint16 bmap = be::read<uint16>(p);
474 int num = bit_set_count((uint32)bmap);
475
476 Rect bbox = glyph.theBBox();
477 Rect diamax(Position(bbox.bl.x + bbox.bl.y, bbox.bl.x - bbox.tr.y),
478 Position(bbox.tr.x + bbox.tr.y, bbox.tr.x - bbox.bl.y));
479 Rect diabound = readbox(diamax, p[0], p[2], p[1], p[3]);
480 ::new (curr) GlyphBox(num, bmap, &diabound);
481 be::skip<uint8>(p, 4);
482 if (glocs + 6 + num * 8 >= gloce)
483 return 0;
484
485 for (int i = 0; i < num * 2; ++i)
486 {
487 Rect box = readbox((i & 1) ? diamax : bbox, p[0], p[2], p[1], p[3]);
488 curr->addSubBox(i >> 1, i & 1, &box);
489 be::skip<uint8>(p, 4);
490 }
491 return (GlyphBox *)((char *)(curr) + sizeof(GlyphBox) + 2 * num * sizeof(Rect));
492 }
493