GlyphCache.cpp (16340B)
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 unsigned short key() const { return uint16(be::peek<W>(_e) + _n); } 50 unsigned int run() const { return be::peek<W>(_e+sizeof(W)); } 51 void advance_entry() { _n = 0; _e = _v; be::skip<W>(_v,2); } 52 public: 53 _glat_iterator(const void * glat=0) : _e(reinterpret_cast<const byte *>(glat)), _v(_e+2*sizeof(W)), _n(0) {} 54 55 _glat_iterator<W> & operator ++ () { 56 ++_n; be::skip<uint16>(_v); 57 if (_n == run()) advance_entry(); 58 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 bool operator == (const _glat_iterator<W> & rhs) { return _v >= rhs._e - 1; } 66 bool operator != (const _glat_iterator<W> & rhs) { return !operator==(rhs); } 67 68 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 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 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 216 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 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 319 GlyphCache::Loader::operator bool () const throw() 320 { 321 return _head && _hhea && _hmtx && !(bool(_glyf) != bool(_loca)); 322 } 323 324 inline 325 unsigned short int GlyphCache::Loader::units_per_em() const throw() 326 { 327 return _head ? TtfUtil::DesignUnits(_head) : 0; 328 } 329 330 inline 331 unsigned short int GlyphCache::Loader::num_glyphs() const throw() 332 { 333 return max(_num_glyphs_graphics, _num_glyphs_attributes); 334 } 335 336 inline 337 unsigned short int GlyphCache::Loader::num_attrs() const throw() 338 { 339 return _num_attrs; 340 } 341 342 inline 343 bool GlyphCache::Loader::has_boxes () const throw() 344 { 345 return _has_boxes; 346 } 347 348 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 436 inline float scale_to(uint8 t, float zmin, float zmax) 437 { 438 return (zmin + t * (zmax - zmin) / 255); 439 } 440 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 447 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 }