Line data Source code
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 : {
49 0 : unsigned short key() const { return be::peek<W>(_e) + _n; }
50 0 : unsigned int run() const { return be::peek<W>(_e+sizeof(W)); }
51 0 : void advance_entry() { _n = 0; _e = _v; be::skip<W>(_v,2); }
52 : public:
53 0 : _glat_iterator(const void * glat=0) : _e(reinterpret_cast<const byte *>(glat)), _v(_e+2*sizeof(W)), _n(0) {}
54 :
55 0 : _glat_iterator<W> & operator ++ () {
56 0 : ++_n; be::skip<uint16>(_v);
57 0 : if (_n == run()) advance_entry();
58 0 : return *this;
59 : }
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.
65 0 : bool operator == (const _glat_iterator<W> & rhs) { return _v >= rhs._e - 1; }
66 0 : bool operator != (const _glat_iterator<W> & rhs) { return !operator==(rhs); }
67 :
68 0 : value_type operator * () const {
69 0 : 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 0 : class GlyphCache::Loader
85 : {
86 : public:
87 : Loader(const Face & face, const bool dumb_font); //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 0 : 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 :
117 0 : GlyphCache::GlyphCache(const Face & face, const uint32 face_options)
118 0 : : _glyph_loader(new Loader(face, bool(face_options & gr_face_dumbRendering))),
119 0 : _glyphs(_glyph_loader && *_glyph_loader && _glyph_loader->num_glyphs()
120 0 : ? grzeroalloc<const GlyphFace *>(_glyph_loader->num_glyphs()) : 0),
121 0 : _boxes(_glyph_loader && _glyph_loader->has_boxes() && _glyph_loader->num_glyphs()
122 0 : ? grzeroalloc<GlyphBox *>(_glyph_loader->num_glyphs()) : 0),
123 0 : _num_glyphs(_glyphs ? _glyph_loader->num_glyphs() : 0),
124 0 : _num_attrs(_glyphs ? _glyph_loader->num_attrs() : 0),
125 0 : _upem(_glyphs ? _glyph_loader->units_per_em() : 0)
126 : {
127 0 : if ((face_options & gr_face_preloadGlyphs) && _glyph_loader && _glyphs)
128 : {
129 0 : int numsubs = 0;
130 0 : GlyphFace * const glyphs = new GlyphFace [_num_glyphs];
131 0 : if (!glyphs)
132 0 : return;
133 :
134 : // The 0 glyph is definately required.
135 0 : _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 0 : const GlyphFace * loaded = _glyphs[0];
141 0 : for (uint16 gid = 1; loaded && gid != _num_glyphs; ++gid)
142 0 : _glyphs[gid] = loaded = _glyph_loader->read_glyph(gid, glyphs[gid], &numsubs);
143 :
144 0 : if (!loaded)
145 : {
146 0 : _glyphs[0] = 0;
147 0 : delete [] glyphs;
148 : }
149 0 : else if (numsubs > 0 && _boxes)
150 : {
151 0 : GlyphBox * boxes = (GlyphBox *)gralloc<char>(_num_glyphs * sizeof(GlyphBox) + numsubs * 8 * sizeof(float));
152 0 : GlyphBox * currbox = boxes;
153 :
154 0 : for (uint16 gid = 0; currbox && gid != _num_glyphs; ++gid)
155 : {
156 0 : _boxes[gid] = currbox;
157 0 : currbox = _glyph_loader->read_box(gid, currbox, *_glyphs[gid]);
158 : }
159 0 : if (!currbox)
160 : {
161 0 : free(boxes);
162 0 : _boxes[0] = 0;
163 : }
164 : }
165 0 : delete _glyph_loader;
166 0 : _glyph_loader = 0;
167 : }
168 :
169 0 : if (_glyphs && glyph(0) == 0)
170 : {
171 0 : free(_glyphs);
172 0 : _glyphs = 0;
173 0 : if (_boxes)
174 : {
175 0 : free(_boxes);
176 0 : _boxes = 0;
177 : }
178 0 : _num_glyphs = _num_attrs = _upem = 0;
179 : }
180 : }
181 :
182 :
183 0 : GlyphCache::~GlyphCache()
184 : {
185 0 : if (_glyphs)
186 : {
187 0 : if (_glyph_loader)
188 : {
189 0 : const GlyphFace * * g = _glyphs;
190 0 : for(unsigned short n = _num_glyphs; n; --n, ++g)
191 0 : delete *g;
192 : }
193 : else
194 0 : delete [] _glyphs[0];
195 0 : free(_glyphs);
196 : }
197 0 : if (_boxes)
198 : {
199 0 : if (_glyph_loader)
200 : {
201 0 : GlyphBox * * g = _boxes;
202 0 : for (uint16 n = _num_glyphs; n; --n, ++g)
203 0 : free(*g);
204 : }
205 : else
206 0 : free(_boxes[0]);
207 0 : free(_boxes);
208 : }
209 0 : delete _glyph_loader;
210 0 : }
211 :
212 0 : const GlyphFace *GlyphCache::glyph(unsigned short glyphid) const //result may be changed by subsequent call with a different glyphid
213 : {
214 0 : if (glyphid >= numGlyphs())
215 0 : return _glyphs[0];
216 0 : const GlyphFace * & p = _glyphs[glyphid];
217 0 : if (p == 0 && _glyph_loader)
218 : {
219 0 : int numsubs = 0;
220 0 : GlyphFace * g = new GlyphFace();
221 0 : if (g) p = _glyph_loader->read_glyph(glyphid, *g, &numsubs);
222 0 : if (!p)
223 : {
224 0 : delete g;
225 0 : return *_glyphs;
226 : }
227 0 : if (_boxes)
228 : {
229 0 : _boxes[glyphid] = (GlyphBox *)gralloc<char>(sizeof(GlyphBox) + 8 * numsubs * sizeof(float));
230 0 : if (!_glyph_loader->read_box(glyphid, _boxes[glyphid], *_glyphs[glyphid]))
231 : {
232 0 : free(_boxes[glyphid]);
233 0 : _boxes[glyphid] = 0;
234 : }
235 : }
236 : }
237 0 : return p;
238 : }
239 :
240 :
241 :
242 0 : GlyphCache::Loader::Loader(const Face & face, const bool dumb_font)
243 : : _head(face, Tag::head),
244 : _hhea(face, Tag::hhea),
245 : _hmtx(face, Tag::hmtx),
246 : _glyf(face, Tag::glyf),
247 : _loca(face, Tag::loca),
248 : _long_fmt(false),
249 : _has_boxes(false),
250 : _num_glyphs_graphics(0),
251 : _num_glyphs_attributes(0),
252 0 : _num_attrs(0)
253 : {
254 0 : if (!operator bool())
255 0 : return;
256 :
257 0 : const Face::Table maxp = Face::Table(face, Tag::maxp);
258 0 : if (!maxp) { _head = Face::Table(); return; }
259 :
260 0 : _num_glyphs_graphics = TtfUtil::GlyphCount(maxp);
261 : // This will fail if the number of glyphs is wildly out of range.
262 0 : if (_glyf && TtfUtil::LocaLookup(_num_glyphs_graphics-1, _loca, _loca.size(), _head) == size_t(-2))
263 : {
264 0 : _head = Face::Table();
265 0 : return;
266 : }
267 :
268 0 : if (!dumb_font)
269 : {
270 0 : if ((m_pGlat = Face::Table(face, Tag::Glat, 0x00030000)) == NULL
271 0 : || (m_pGloc = Face::Table(face, Tag::Gloc)) == NULL
272 0 : || m_pGloc.size() < 8)
273 : {
274 0 : _head = Face::Table();
275 0 : return;
276 : }
277 0 : const byte * p = m_pGloc;
278 0 : int version = be::read<uint32>(p);
279 0 : const uint16 flags = be::read<uint16>(p);
280 0 : _num_attrs = be::read<uint16>(p);
281 : // We can accurately calculate the number of attributed glyphs by
282 : // subtracting the length of the attribids array (numAttribs long if present)
283 : // and dividing by either 2 or 4 depending on shor or lonf format
284 0 : _long_fmt = flags & 1;
285 0 : int tmpnumgattrs = (m_pGloc.size()
286 0 : - (p - m_pGloc)
287 0 : - sizeof(uint16)*(flags & 0x2 ? _num_attrs : 0))
288 0 : / (_long_fmt ? sizeof(uint32) : sizeof(uint16)) - 1;
289 :
290 0 : if (version >= 0x00020000 || tmpnumgattrs < 0 || tmpnumgattrs > 65535
291 0 : || _num_attrs == 0 || _num_attrs > 0x3000 // is this hard limit appropriate?
292 0 : || _num_glyphs_graphics > tmpnumgattrs
293 0 : || m_pGlat.size() < 4)
294 : {
295 0 : _head = Face::Table();
296 0 : return;
297 : }
298 :
299 0 : _num_glyphs_attributes = static_cast<unsigned short>(tmpnumgattrs);
300 0 : p = m_pGlat;
301 0 : version = be::read<uint32>(p);
302 0 : if (version >= 0x00040000 || (version >= 0x00030000 && m_pGlat.size() < 8)) // reject Glat tables that are too new
303 : {
304 0 : _head = Face::Table();
305 0 : return;
306 : }
307 0 : else if (version >= 0x00030000)
308 : {
309 0 : unsigned int glatflags = be::read<uint32>(p);
310 0 : _has_boxes = glatflags & 1;
311 : // delete this once the compiler is fixed
312 0 : _has_boxes = true;
313 : }
314 : }
315 : }
316 :
317 : inline
318 0 : GlyphCache::Loader::operator bool () const throw()
319 : {
320 0 : return _head && _hhea && _hmtx && !(bool(_glyf) != bool(_loca));
321 : }
322 :
323 : inline
324 0 : unsigned short int GlyphCache::Loader::units_per_em() const throw()
325 : {
326 0 : return _head ? TtfUtil::DesignUnits(_head) : 0;
327 : }
328 :
329 : inline
330 0 : unsigned short int GlyphCache::Loader::num_glyphs() const throw()
331 : {
332 0 : return max(_num_glyphs_graphics, _num_glyphs_attributes);
333 : }
334 :
335 : inline
336 0 : unsigned short int GlyphCache::Loader::num_attrs() const throw()
337 : {
338 0 : return _num_attrs;
339 : }
340 :
341 : inline
342 0 : bool GlyphCache::Loader::has_boxes () const throw()
343 : {
344 0 : return _has_boxes;
345 : }
346 :
347 0 : const GlyphFace * GlyphCache::Loader::read_glyph(unsigned short glyphid, GlyphFace & glyph, int *numsubs) const throw()
348 : {
349 0 : Rect bbox;
350 0 : Position advance;
351 :
352 0 : if (glyphid < _num_glyphs_graphics)
353 : {
354 : int nLsb;
355 : unsigned int nAdvWid;
356 0 : if (_glyf)
357 : {
358 : int xMin, yMin, xMax, yMax;
359 0 : size_t locidx = TtfUtil::LocaLookup(glyphid, _loca, _loca.size(), _head);
360 0 : void *pGlyph = TtfUtil::GlyfLookup(_glyf, locidx, _glyf.size());
361 :
362 0 : if (pGlyph && TtfUtil::GlyfBox(pGlyph, xMin, yMin, xMax, yMax))
363 : {
364 0 : if ((xMin > xMax) || (yMin > yMax))
365 0 : return 0;
366 0 : bbox = Rect(Position(static_cast<float>(xMin), static_cast<float>(yMin)),
367 0 : Position(static_cast<float>(xMax), static_cast<float>(yMax)));
368 : }
369 : }
370 0 : if (TtfUtil::HorMetrics(glyphid, _hmtx, _hmtx.size(), _hhea, nLsb, nAdvWid))
371 0 : advance = Position(static_cast<float>(nAdvWid), 0);
372 : }
373 :
374 0 : if (glyphid < _num_glyphs_attributes)
375 : {
376 0 : const byte * gloc = m_pGloc;
377 0 : size_t glocs = 0, gloce = 0;
378 :
379 0 : be::skip<uint32>(gloc);
380 0 : be::skip<uint16>(gloc,2);
381 0 : if (_long_fmt)
382 : {
383 0 : if (8 + glyphid * sizeof(uint32) > m_pGloc.size())
384 0 : return 0;
385 0 : be::skip<uint32>(gloc, glyphid);
386 0 : glocs = be::read<uint32>(gloc);
387 0 : gloce = be::peek<uint32>(gloc);
388 : }
389 : else
390 : {
391 0 : if (8 + glyphid * sizeof(uint16) > m_pGloc.size())
392 0 : return 0;
393 0 : be::skip<uint16>(gloc, glyphid);
394 0 : glocs = be::read<uint16>(gloc);
395 0 : gloce = be::peek<uint16>(gloc);
396 : }
397 :
398 0 : if (glocs >= m_pGlat.size() - 1 || gloce > m_pGlat.size())
399 0 : return 0;
400 :
401 0 : const uint32 glat_version = be::peek<uint32>(m_pGlat);
402 0 : if (glat_version >= 0x00030000)
403 : {
404 0 : if (glocs >= gloce)
405 0 : return 0;
406 0 : const byte * p = m_pGlat + glocs;
407 0 : uint16 bmap = be::read<uint16>(p);
408 0 : int num = bit_set_count((uint32)bmap);
409 0 : if (numsubs) *numsubs += num;
410 0 : glocs += 6 + 8 * num;
411 0 : if (glocs > gloce)
412 0 : return 0;
413 : }
414 0 : if (glat_version < 0x00020000)
415 : {
416 0 : if (gloce - glocs < 2*sizeof(byte)+sizeof(uint16)
417 0 : || gloce - glocs > _num_attrs*(2*sizeof(byte)+sizeof(uint16)))
418 0 : return 0;
419 0 : new (&glyph) GlyphFace(bbox, advance, glat_iterator(m_pGlat + glocs), glat_iterator(m_pGlat + gloce));
420 : }
421 : else
422 : {
423 0 : if (gloce - glocs < 3*sizeof(uint16) // can a glyph have no attributes? why not?
424 0 : || gloce - glocs > _num_attrs*3*sizeof(uint16)
425 0 : || glocs > m_pGlat.size() - 2*sizeof(uint16))
426 0 : return 0;
427 0 : new (&glyph) GlyphFace(bbox, advance, glat2_iterator(m_pGlat + glocs), glat2_iterator(m_pGlat + gloce));
428 : }
429 0 : if (!glyph.attrs() || glyph.attrs().capacity() > _num_attrs)
430 0 : return 0;
431 : }
432 0 : return &glyph;
433 : }
434 :
435 0 : inline float scale_to(uint8 t, float zmin, float zmax)
436 : {
437 0 : return (zmin + t * (zmax - zmin) / 255);
438 : }
439 :
440 0 : Rect readbox(Rect &b, uint8 zxmin, uint8 zymin, uint8 zxmax, uint8 zymax)
441 : {
442 0 : return Rect(Position(scale_to(zxmin, b.bl.x, b.tr.x), scale_to(zymin, b.bl.y, b.tr.y)),
443 0 : Position(scale_to(zxmax, b.bl.x, b.tr.x), scale_to(zymax, b.bl.y, b.tr.y)));
444 : }
445 :
446 0 : GlyphBox * GlyphCache::Loader::read_box(uint16 gid, GlyphBox *curr, const GlyphFace & glyph) const throw()
447 : {
448 0 : if (gid >= _num_glyphs_attributes) return 0;
449 :
450 0 : const byte * gloc = m_pGloc;
451 0 : size_t glocs = 0, gloce = 0;
452 :
453 0 : be::skip<uint32>(gloc);
454 0 : be::skip<uint16>(gloc,2);
455 0 : if (_long_fmt)
456 : {
457 0 : be::skip<uint32>(gloc, gid);
458 0 : glocs = be::read<uint32>(gloc);
459 0 : gloce = be::peek<uint32>(gloc);
460 : }
461 : else
462 : {
463 0 : be::skip<uint16>(gloc, gid);
464 0 : glocs = be::read<uint16>(gloc);
465 0 : gloce = be::peek<uint16>(gloc);
466 : }
467 :
468 0 : if (gloce > m_pGlat.size() || glocs + 6 >= gloce)
469 0 : return 0;
470 :
471 0 : const byte * p = m_pGlat + glocs;
472 0 : uint16 bmap = be::read<uint16>(p);
473 0 : int num = bit_set_count((uint32)bmap);
474 :
475 0 : Rect bbox = glyph.theBBox();
476 0 : Rect diamax(Position(bbox.bl.x + bbox.bl.y, bbox.bl.x - bbox.tr.y),
477 0 : Position(bbox.tr.x + bbox.tr.y, bbox.tr.x - bbox.bl.y));
478 0 : Rect diabound = readbox(diamax, p[0], p[2], p[1], p[3]);
479 0 : ::new (curr) GlyphBox(num, bmap, &diabound);
480 0 : be::skip<uint8>(p, 4);
481 0 : if (glocs + 6 + num * 8 >= gloce)
482 0 : return 0;
483 :
484 0 : for (int i = 0; i < num * 2; ++i)
485 : {
486 0 : Rect box = readbox((i & 1) ? diamax : bbox, p[0], p[2], p[1], p[3]);
487 0 : curr->addSubBox(i >> 1, i & 1, &box);
488 0 : be::skip<uint8>(p, 4);
489 : }
490 0 : return (GlyphBox *)((char *)(curr) + sizeof(GlyphBox) + 2 * num * sizeof(Rect));
491 : }
492 :
|