gfx/graphite2/src/Face.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*  GRAPHITE2 LICENSING
     3     Copyright 2010, SIL International
     4     All rights reserved.
     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.
    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.
    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.
    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/Endian.h"
    32 #include "inc/Face.h"
    33 #include "inc/FileFace.h"
    34 #include "inc/GlyphFace.h"
    35 #include "inc/json.h"
    36 #include "inc/SegCacheStore.h"
    37 #include "inc/Segment.h"
    38 #include "inc/NameTable.h"
    39 #include "inc/Error.h"
    41 using namespace graphite2;
    43 Face::Face(const void* appFaceHandle/*non-NULL*/, const gr_face_ops & ops)
    44 : m_appFaceHandle(appFaceHandle),
    45   m_pFileFace(NULL),
    46   m_pGlyphFaceCache(NULL),
    47   m_cmap(NULL),
    48   m_pNames(NULL),
    49   m_logger(NULL),
    50   m_error(0), m_errcntxt(0),
    51   m_silfs(NULL),
    52   m_numSilf(0),
    53   m_ascent(0),
    54   m_descent(0)
    55 {
    56     memset(&m_ops, 0, sizeof m_ops);
    57     memcpy(&m_ops, &ops, min(sizeof m_ops, ops.size));
    58 }
    61 Face::~Face()
    62 {
    63     setLogger(0);
    64     delete m_pGlyphFaceCache;
    65     delete m_cmap;
    66     delete[] m_silfs;
    67 #ifndef GRAPHITE2_NFILEFACE
    68     delete m_pFileFace;
    69 #endif
    70     delete m_pNames;
    71 }
    73 float Face::default_glyph_advance(const void* font_ptr, gr_uint16 glyphid)
    74 {
    75     const Font & font = *reinterpret_cast<const Font *>(font_ptr);
    77     return font.face().glyphs().glyph(glyphid)->theAdvance().x * font.scale();
    78 }
    80 bool Face::readGlyphs(uint32 faceOptions)
    81 {
    82     Error e;
    83 #ifdef GRAPHITE2_TELEMETRY
    84     telemetry::category _glyph_cat(tele.glyph);
    85 #endif
    86     error_context(EC_READGLYPHS);
    87     if (faceOptions & gr_face_cacheCmap)
    88         m_cmap = new CachedCmap(*this);
    89     else
    90         m_cmap = new DirectCmap(*this);
    92     m_pGlyphFaceCache = new GlyphCache(*this, faceOptions);
    93     if (e.test(!m_pGlyphFaceCache, E_OUTOFMEM)
    94         || e.test(m_pGlyphFaceCache->numGlyphs() == 0, E_NOGLYPHS)
    95         || e.test(m_pGlyphFaceCache->unitsPerEm() == 0, E_BADUPEM)
    96         || e.test(!m_cmap, E_OUTOFMEM) || e.test(!*m_cmap, E_BADCMAP))
    97     {
    98         return error(e);
    99     }
   101     if (faceOptions & gr_face_preloadGlyphs)
   102         nameTable();        // preload the name table along with the glyphs.
   104     return true;
   105 }
   107 bool Face::readGraphite(const Table & silf)
   108 {
   109 #ifdef GRAPHITE2_TELEMETRY
   110     telemetry::category _silf_cat(tele.silf);
   111 #endif
   112     Error e;
   113     error_context(EC_READSILF);
   114     const byte * p = silf;
   115     if (e.test(!p, E_NOSILF)) return error(e);
   117     const uint32 version = be::read<uint32>(p);
   118     if (e.test(version < 0x00020000, E_TOOOLD)) return error(e);
   119     if (version >= 0x00030000)
   120         be::skip<uint32>(p);        // compilerVersion
   121     m_numSilf = be::read<uint16>(p);
   122     be::skip<uint16>(p);            // reserved
   124     bool havePasses = false;
   125     m_silfs = new Silf[m_numSilf];
   126     for (int i = 0; i < m_numSilf; i++)
   127     {
   128         error_context(EC_ASILF + (i << 8));
   129         const uint32 offset = be::read<uint32>(p),
   130                      next   = i == m_numSilf - 1 ? silf.size() : be::peek<uint32>(p);
   131         if (e.test(next > silf.size() || offset >= next, E_BADSIZE))
   132             return error(e);
   134         if (!m_silfs[i].readGraphite(silf + offset, next - offset, *this, version))
   135             return false;
   137         if (m_silfs[i].numPasses())
   138             havePasses = true;
   139     }
   141     return havePasses;
   142 }
   144 bool Face::readFeatures()
   145 {
   146     return m_Sill.readFace(*this);
   147 }
   149 bool Face::runGraphite(Segment *seg, const Silf *aSilf) const
   150 {
   151 #if !defined GRAPHITE2_NTRACING
   152     json * dbgout = logger();
   153     if (dbgout)
   154     {
   155         *dbgout << json::object
   156                     << "id"         << objectid(seg)
   157                     << "passes"     << json::array;
   158     }
   159 #endif
   161     bool res = aSilf->runGraphite(seg, 0, aSilf->justificationPass(), true);
   162     if (res)
   163         res = aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false);
   165 #if !defined GRAPHITE2_NTRACING
   166     if (dbgout)
   167 {
   168         *dbgout             << json::item
   169                             << json::close // Close up the passes array
   170                 << "output" << json::array;
   171         for(Slot * s = seg->first(); s; s = s->next())
   172             *dbgout     << dslot(seg, s);
   173         seg->finalise(0);                   // Call this here to fix up charinfo back indexes.
   174         *dbgout         << json::close
   175                 << "advance" << seg->advance()
   176                 << "chars"   << json::array;
   177         for(size_t i = 0, n = seg->charInfoCount(); i != n; ++i)
   178             *dbgout     << json::flat << *seg->charinfo(i);
   179         *dbgout         << json::close  // Close up the chars array
   180                     << json::close;     // Close up the segment object
   181     }
   182 #endif
   184     return res;
   185 }
   187 void Face::setLogger(FILE * log_file GR_MAYBE_UNUSED)
   188 {
   189 #if !defined GRAPHITE2_NTRACING
   190     delete m_logger;
   191     m_logger = log_file ? new json(log_file) : 0;
   192 #endif
   193 }
   195 const Silf *Face::chooseSilf(uint32 script) const
   196 {
   197     if (m_numSilf == 0)
   198         return NULL;
   199     else if (m_numSilf == 1 || script == 0)
   200         return m_silfs;
   201     else // do more work here
   202         return m_silfs;
   203 }
   205 uint16 Face::findPseudo(uint32 uid) const
   206 {
   207     return (m_numSilf) ? m_silfs[0].findPseudo(uid) : 0;
   208 }
   210 uint16 Face::getGlyphMetric(uint16 gid, uint8 metric) const
   211 {
   212     switch (metrics(metric))
   213     {
   214         case kgmetAscent : return m_ascent;
   215         case kgmetDescent : return m_descent;
   216         default: return glyphs().glyph(gid)->getMetric(metric);
   217     }
   218 }
   220 void Face::takeFileFace(FileFace* pFileFace GR_MAYBE_UNUSED/*takes ownership*/)
   221 {
   222 #ifndef GRAPHITE2_NFILEFACE
   223     if (m_pFileFace==pFileFace)
   224       return;
   226     delete m_pFileFace;
   227     m_pFileFace = pFileFace;
   228 #endif
   229 }
   231 NameTable * Face::nameTable() const
   232 {
   233     if (m_pNames) return m_pNames;
   234     const Table name(*this, Tag::name);
   235     if (name)
   236         m_pNames = new NameTable(name, name.size());
   237     return m_pNames;
   238 }
   240 uint16 Face::languageForLocale(const char * locale) const
   241 {
   242     nameTable();
   243     if (m_pNames)
   244         return m_pNames->getLanguageId(locale);
   245     return 0;
   246 }
   248 Face::Table::Table(const Face & face, const Tag n) throw()
   249 : _f(&face)
   250 {
   251     size_t sz = 0;
   252     _p = reinterpret_cast<const byte *>((*_f->m_ops.get_table)(_f->m_appFaceHandle, n, &sz));
   253     _sz = uint32(sz);
   254     if (!TtfUtil::CheckTable(n, _p, _sz))
   255     {
   256         this->~Table();     // Make sure we release the table buffer even if the table filed it's checks
   257         _p = 0; _sz = 0;
   258     }
   259 }
   261 Face::Table & Face::Table::operator = (const Table & rhs) throw()
   262 {
   263     if (_p == rhs._p)   return *this;
   265     this->~Table();
   266     new (this) Table(rhs);
   267     return *this;
   268 }

mercurial