LCOV - code coverage report
Current view: top level - gfx/graphite2/src - GlyphCache.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 230 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 32 0.0 %
Legend: Lines: hit not hit

          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             : 

Generated by: LCOV version 1.13