gfx/graphite2/src/Face.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/graphite2/src/Face.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,269 @@
     1.4 +/*  GRAPHITE2 LICENSING
     1.5 +
     1.6 +    Copyright 2010, SIL International
     1.7 +    All rights reserved.
     1.8 +
     1.9 +    This library is free software; you can redistribute it and/or modify
    1.10 +    it under the terms of the GNU Lesser General Public License as published
    1.11 +    by the Free Software Foundation; either version 2.1 of License, or
    1.12 +    (at your option) any later version.
    1.13 +
    1.14 +    This program is distributed in the hope that it will be useful,
    1.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    1.17 +    Lesser General Public License for more details.
    1.18 +
    1.19 +    You should also have received a copy of the GNU Lesser General Public
    1.20 +    License along with this library in the file named "LICENSE".
    1.21 +    If not, write to the Free Software Foundation, 51 Franklin Street, 
    1.22 +    Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
    1.23 +    internet at http://www.fsf.org/licenses/lgpl.html.
    1.24 +
    1.25 +Alternatively, the contents of this file may be used under the terms of the
    1.26 +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
    1.27 +License, as published by the Free Software Foundation, either version 2
    1.28 +of the License or (at your option) any later version.
    1.29 +*/
    1.30 +#include <cstring>
    1.31 +#include "graphite2/Segment.h"
    1.32 +#include "inc/CmapCache.h"
    1.33 +#include "inc/debug.h"
    1.34 +#include "inc/Endian.h"
    1.35 +#include "inc/Face.h"
    1.36 +#include "inc/FileFace.h"
    1.37 +#include "inc/GlyphFace.h"
    1.38 +#include "inc/json.h"
    1.39 +#include "inc/SegCacheStore.h"
    1.40 +#include "inc/Segment.h"
    1.41 +#include "inc/NameTable.h"
    1.42 +#include "inc/Error.h"
    1.43 +
    1.44 +using namespace graphite2;
    1.45 +
    1.46 +Face::Face(const void* appFaceHandle/*non-NULL*/, const gr_face_ops & ops)
    1.47 +: m_appFaceHandle(appFaceHandle),
    1.48 +  m_pFileFace(NULL),
    1.49 +  m_pGlyphFaceCache(NULL),
    1.50 +  m_cmap(NULL),
    1.51 +  m_pNames(NULL),
    1.52 +  m_logger(NULL),
    1.53 +  m_error(0), m_errcntxt(0),
    1.54 +  m_silfs(NULL),
    1.55 +  m_numSilf(0),
    1.56 +  m_ascent(0),
    1.57 +  m_descent(0)
    1.58 +{
    1.59 +    memset(&m_ops, 0, sizeof m_ops);
    1.60 +    memcpy(&m_ops, &ops, min(sizeof m_ops, ops.size));
    1.61 +}
    1.62 +
    1.63 +
    1.64 +Face::~Face()
    1.65 +{
    1.66 +    setLogger(0);
    1.67 +    delete m_pGlyphFaceCache;
    1.68 +    delete m_cmap;
    1.69 +    delete[] m_silfs;
    1.70 +#ifndef GRAPHITE2_NFILEFACE
    1.71 +    delete m_pFileFace;
    1.72 +#endif
    1.73 +    delete m_pNames;
    1.74 +}
    1.75 +
    1.76 +float Face::default_glyph_advance(const void* font_ptr, gr_uint16 glyphid)
    1.77 +{
    1.78 +    const Font & font = *reinterpret_cast<const Font *>(font_ptr);
    1.79 +
    1.80 +    return font.face().glyphs().glyph(glyphid)->theAdvance().x * font.scale();
    1.81 +}
    1.82 +
    1.83 +bool Face::readGlyphs(uint32 faceOptions)
    1.84 +{
    1.85 +    Error e;
    1.86 +#ifdef GRAPHITE2_TELEMETRY
    1.87 +    telemetry::category _glyph_cat(tele.glyph);
    1.88 +#endif
    1.89 +    error_context(EC_READGLYPHS);
    1.90 +    if (faceOptions & gr_face_cacheCmap)
    1.91 +        m_cmap = new CachedCmap(*this);
    1.92 +    else
    1.93 +        m_cmap = new DirectCmap(*this);
    1.94 +
    1.95 +    m_pGlyphFaceCache = new GlyphCache(*this, faceOptions);
    1.96 +    if (e.test(!m_pGlyphFaceCache, E_OUTOFMEM)
    1.97 +        || e.test(m_pGlyphFaceCache->numGlyphs() == 0, E_NOGLYPHS)
    1.98 +        || e.test(m_pGlyphFaceCache->unitsPerEm() == 0, E_BADUPEM)
    1.99 +        || e.test(!m_cmap, E_OUTOFMEM) || e.test(!*m_cmap, E_BADCMAP))
   1.100 +    {
   1.101 +        return error(e);
   1.102 +    }
   1.103 +
   1.104 +    if (faceOptions & gr_face_preloadGlyphs)
   1.105 +        nameTable();        // preload the name table along with the glyphs.
   1.106 +
   1.107 +    return true;
   1.108 +}
   1.109 +
   1.110 +bool Face::readGraphite(const Table & silf)
   1.111 +{
   1.112 +#ifdef GRAPHITE2_TELEMETRY
   1.113 +    telemetry::category _silf_cat(tele.silf);
   1.114 +#endif
   1.115 +    Error e;
   1.116 +    error_context(EC_READSILF);
   1.117 +    const byte * p = silf;
   1.118 +    if (e.test(!p, E_NOSILF)) return error(e);
   1.119 +
   1.120 +    const uint32 version = be::read<uint32>(p);
   1.121 +    if (e.test(version < 0x00020000, E_TOOOLD)) return error(e);
   1.122 +    if (version >= 0x00030000)
   1.123 +        be::skip<uint32>(p);        // compilerVersion
   1.124 +    m_numSilf = be::read<uint16>(p);
   1.125 +    be::skip<uint16>(p);            // reserved
   1.126 +
   1.127 +    bool havePasses = false;
   1.128 +    m_silfs = new Silf[m_numSilf];
   1.129 +    for (int i = 0; i < m_numSilf; i++)
   1.130 +    {
   1.131 +        error_context(EC_ASILF + (i << 8));
   1.132 +        const uint32 offset = be::read<uint32>(p),
   1.133 +                     next   = i == m_numSilf - 1 ? silf.size() : be::peek<uint32>(p);
   1.134 +        if (e.test(next > silf.size() || offset >= next, E_BADSIZE))
   1.135 +            return error(e);
   1.136 +
   1.137 +        if (!m_silfs[i].readGraphite(silf + offset, next - offset, *this, version))
   1.138 +            return false;
   1.139 +
   1.140 +        if (m_silfs[i].numPasses())
   1.141 +            havePasses = true;
   1.142 +    }
   1.143 +
   1.144 +    return havePasses;
   1.145 +}
   1.146 +
   1.147 +bool Face::readFeatures()
   1.148 +{
   1.149 +    return m_Sill.readFace(*this);
   1.150 +}
   1.151 +
   1.152 +bool Face::runGraphite(Segment *seg, const Silf *aSilf) const
   1.153 +{
   1.154 +#if !defined GRAPHITE2_NTRACING
   1.155 +    json * dbgout = logger();
   1.156 +    if (dbgout)
   1.157 +    {
   1.158 +        *dbgout << json::object
   1.159 +                    << "id"         << objectid(seg)
   1.160 +                    << "passes"     << json::array;
   1.161 +    }
   1.162 +#endif
   1.163 +
   1.164 +    bool res = aSilf->runGraphite(seg, 0, aSilf->justificationPass(), true);
   1.165 +    if (res)
   1.166 +        res = aSilf->runGraphite(seg, aSilf->positionPass(), aSilf->numPasses(), false);
   1.167 +
   1.168 +#if !defined GRAPHITE2_NTRACING
   1.169 +    if (dbgout)
   1.170 +{
   1.171 +        *dbgout             << json::item
   1.172 +                            << json::close // Close up the passes array
   1.173 +                << "output" << json::array;
   1.174 +        for(Slot * s = seg->first(); s; s = s->next())
   1.175 +            *dbgout     << dslot(seg, s);
   1.176 +        seg->finalise(0);                   // Call this here to fix up charinfo back indexes.
   1.177 +        *dbgout         << json::close
   1.178 +                << "advance" << seg->advance()
   1.179 +                << "chars"   << json::array;
   1.180 +        for(size_t i = 0, n = seg->charInfoCount(); i != n; ++i)
   1.181 +            *dbgout     << json::flat << *seg->charinfo(i);
   1.182 +        *dbgout         << json::close  // Close up the chars array
   1.183 +                    << json::close;     // Close up the segment object
   1.184 +    }
   1.185 +#endif
   1.186 +
   1.187 +    return res;
   1.188 +}
   1.189 +
   1.190 +void Face::setLogger(FILE * log_file GR_MAYBE_UNUSED)
   1.191 +{
   1.192 +#if !defined GRAPHITE2_NTRACING
   1.193 +    delete m_logger;
   1.194 +    m_logger = log_file ? new json(log_file) : 0;
   1.195 +#endif
   1.196 +}
   1.197 +
   1.198 +const Silf *Face::chooseSilf(uint32 script) const
   1.199 +{
   1.200 +    if (m_numSilf == 0)
   1.201 +        return NULL;
   1.202 +    else if (m_numSilf == 1 || script == 0)
   1.203 +        return m_silfs;
   1.204 +    else // do more work here
   1.205 +        return m_silfs;
   1.206 +}
   1.207 +
   1.208 +uint16 Face::findPseudo(uint32 uid) const
   1.209 +{
   1.210 +    return (m_numSilf) ? m_silfs[0].findPseudo(uid) : 0;
   1.211 +}
   1.212 +
   1.213 +uint16 Face::getGlyphMetric(uint16 gid, uint8 metric) const
   1.214 +{
   1.215 +    switch (metrics(metric))
   1.216 +    {
   1.217 +        case kgmetAscent : return m_ascent;
   1.218 +        case kgmetDescent : return m_descent;
   1.219 +        default: return glyphs().glyph(gid)->getMetric(metric);
   1.220 +    }
   1.221 +}
   1.222 +
   1.223 +void Face::takeFileFace(FileFace* pFileFace GR_MAYBE_UNUSED/*takes ownership*/)
   1.224 +{
   1.225 +#ifndef GRAPHITE2_NFILEFACE
   1.226 +    if (m_pFileFace==pFileFace)
   1.227 +      return;
   1.228 +    
   1.229 +    delete m_pFileFace;
   1.230 +    m_pFileFace = pFileFace;
   1.231 +#endif
   1.232 +}
   1.233 +
   1.234 +NameTable * Face::nameTable() const
   1.235 +{
   1.236 +    if (m_pNames) return m_pNames;
   1.237 +    const Table name(*this, Tag::name);
   1.238 +    if (name)
   1.239 +        m_pNames = new NameTable(name, name.size());
   1.240 +    return m_pNames;
   1.241 +}
   1.242 +
   1.243 +uint16 Face::languageForLocale(const char * locale) const
   1.244 +{
   1.245 +    nameTable();
   1.246 +    if (m_pNames)
   1.247 +        return m_pNames->getLanguageId(locale);
   1.248 +    return 0;
   1.249 +}
   1.250 +
   1.251 +Face::Table::Table(const Face & face, const Tag n) throw()
   1.252 +: _f(&face)
   1.253 +{
   1.254 +    size_t sz = 0;
   1.255 +    _p = reinterpret_cast<const byte *>((*_f->m_ops.get_table)(_f->m_appFaceHandle, n, &sz));
   1.256 +    _sz = uint32(sz);
   1.257 +    if (!TtfUtil::CheckTable(n, _p, _sz))
   1.258 +    {
   1.259 +        this->~Table();     // Make sure we release the table buffer even if the table filed it's checks
   1.260 +        _p = 0; _sz = 0;
   1.261 +    }
   1.262 +}
   1.263 +
   1.264 +Face::Table & Face::Table::operator = (const Table & rhs) throw()
   1.265 +{
   1.266 +    if (_p == rhs._p)   return *this;
   1.267 +
   1.268 +    this->~Table();
   1.269 +    new (this) Table(rhs);
   1.270 +    return *this;
   1.271 +}
   1.272 +

mercurial