gfx/graphite2/src/FeatureMap.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>
    29 #include "inc/Main.h"
    30 #include "inc/bits.h"
    31 #include "inc/Endian.h"
    32 #include "inc/FeatureMap.h"
    33 #include "inc/FeatureVal.h"
    34 #include "graphite2/Font.h"
    35 #include "inc/TtfUtil.h"
    36 #include <cstdlib>
    37 #include "inc/Face.h"
    40 using namespace graphite2;
    42 namespace
    43 {
    44     static int cmpNameAndFeatures(const void *ap, const void *bp)
    45     {
    46         const NameAndFeatureRef & a = *static_cast<const NameAndFeatureRef *>(ap),
    47                                 & b = *static_cast<const NameAndFeatureRef *>(bp);
    48         return (a < b ? -1 : (b < a ? 1 : 0));
    49     }
    51     const size_t    FEAT_HEADER     = sizeof(uint32) + 2*sizeof(uint16) + sizeof(uint32),
    52                     FEATURE_SIZE    = sizeof(uint32)
    53                                     + 2*sizeof(uint16)
    54                                     + sizeof(uint32)
    55                                     + 2*sizeof(uint16),
    56                     FEATURE_SETTING_SIZE = sizeof(int16) + sizeof(uint16);
    58     uint16 readFeatureSettings(const byte * p, FeatureSetting * s, size_t num_settings)
    59     {
    60         uint16 max_val = 0;
    61         for (FeatureSetting * const end = s + num_settings; s != end; ++s)
    62         {
    63             const int16 value = be::read<int16>(p);
    64             ::new (s) FeatureSetting(value, be::read<uint16>(p));
    65             if (uint16(value) > max_val)    max_val = value;
    66         }
    68         return max_val;
    69     }
    70 }
    72 FeatureRef::FeatureRef(const Face & face,
    73     unsigned short & bits_offset, uint32 max_val,
    74     uint32 name, uint16 uiName, uint16 flags,
    75     FeatureSetting *settings, uint16 num_set) throw()
    76 : m_pFace(&face),
    77   m_nameValues(settings),
    78   m_mask(mask_over_val(max_val)),
    79   m_max(max_val),
    80   m_id(name),
    81   m_nameid(uiName),
    82   m_flags(flags),
    83   m_numSet(num_set)
    84 {
    85     const uint8 need_bits = bit_set_count(m_mask);
    86     m_index = (bits_offset + need_bits) / SIZEOF_CHUNK;
    87     if (m_index > bits_offset / SIZEOF_CHUNK)
    88         bits_offset = m_index*SIZEOF_CHUNK;
    89     m_bits = bits_offset % SIZEOF_CHUNK;
    90     bits_offset += need_bits;
    91     m_mask <<= m_bits;
    92 }
    94 FeatureRef::~FeatureRef() throw()
    95 {
    96     free(m_nameValues);
    97 }
    99 bool FeatureMap::readFeats(const Face & face)
   100 {
   101     const Face::Table feat(face, TtfUtil::Tag::Feat);
   102     const byte * p = feat;
   103     if (!p) return true;
   104     if (feat.size() < FEAT_HEADER) return false;
   106     const byte *const feat_start = p,
   107                *const feat_end = p + feat.size();
   109     const uint32 version = be::read<uint32>(p);
   110     m_numFeats = be::read<uint16>(p);
   111     be::skip<uint16>(p);
   112     be::skip<uint32>(p);
   114     // Sanity checks
   115     if (m_numFeats == 0)    return true;
   116     if (version < 0x00010000 ||
   117         p + m_numFeats*FEATURE_SIZE > feat_end)
   118     {   //defensive
   119         m_numFeats = 0;
   120         return false;
   121     }
   123     m_feats = new FeatureRef [m_numFeats];
   124     uint16 * const  defVals = gralloc<uint16>(m_numFeats);
   125     if (!defVals || !m_feats) return false;
   126     unsigned short bits = 0;     //to cause overflow on first Feature
   128     for (int i = 0, ie = m_numFeats; i != ie; i++)
   129     {
   130         const uint32    label   = version < 0x00020000 ? be::read<uint16>(p) : be::read<uint32>(p);
   131         const uint16    num_settings = be::read<uint16>(p);
   132         if (version >= 0x00020000)
   133             be::skip<uint16>(p);
   134         const byte * const feat_setts = feat_start + be::read<uint32>(p);
   135         const uint16    flags  = be::read<uint16>(p),
   136                         uiName = be::read<uint16>(p);
   138         if (feat_setts + num_settings * FEATURE_SETTING_SIZE > feat_end)
   139         {
   140             free(defVals);
   141             return false;
   142         }
   144         FeatureSetting *uiSet;
   145         uint32 maxVal;
   146         if (num_settings != 0)
   147         {
   148             uiSet = gralloc<FeatureSetting>(num_settings);
   149             if (!uiSet)
   150             {
   151                 free(defVals);
   152                 return false;
   153             }
   154             maxVal = readFeatureSettings(feat_setts, uiSet, num_settings);
   155             defVals[i] = uiSet[0].value();
   156         }
   157         else
   158         {
   159             uiSet = 0;
   160             maxVal = 0xffffffff;
   161             defVals[i] = 0;
   162         }
   164         ::new (m_feats + i) FeatureRef (face, bits, maxVal,
   165                                        label, uiName, flags,
   166                                        uiSet, num_settings);
   167     }
   168     m_defaultFeatures = new Features(bits/(sizeof(uint32)*8) + 1, *this);
   169     m_pNamedFeats = new NameAndFeatureRef[m_numFeats];
   170     if (!m_defaultFeatures || !m_pNamedFeats)
   171     {
   172         free(defVals);
   173         return false;
   174     }
   175     for (int i = 0; i < m_numFeats; ++i)
   176     {
   177         m_feats[i].applyValToFeature(defVals[i], *m_defaultFeatures);
   178         m_pNamedFeats[i] = m_feats+i;
   179     }
   181     free(defVals);
   183     qsort(m_pNamedFeats, m_numFeats, sizeof(NameAndFeatureRef), &cmpNameAndFeatures);
   185     return true;
   186 }
   188 bool SillMap::readFace(const Face & face)
   189 {
   190     if (!m_FeatureMap.readFeats(face)) return false;
   191     if (!readSill(face)) return false;
   192     return true;
   193 }
   196 bool SillMap::readSill(const Face & face)
   197 {
   198     const Face::Table sill(face, TtfUtil::Tag::Sill);
   199     const byte *p = sill;
   201     if (!p) return true;
   202     if (sill.size() < 12) return false;
   203     if (be::read<uint32>(p) != 0x00010000UL) return false;
   204     m_numLanguages = be::read<uint16>(p);
   205     m_langFeats = new LangFeaturePair[m_numLanguages];
   206     if (!m_langFeats || !m_FeatureMap.m_numFeats) { m_numLanguages = 0; return true; }        //defensive
   208     p += 6;     // skip the fast search
   209     if (sill.size() < m_numLanguages * 8U + 12) return false;
   211     for (int i = 0; i < m_numLanguages; i++)
   212     {
   213         uint32 langid = be::read<uint32>(p);
   214         uint16 numSettings = be::read<uint16>(p);
   215         uint16 offset = be::read<uint16>(p);
   216         if (offset + 8U * numSettings > sill.size() && numSettings > 0) return false;
   217         Features* feats = new Features(*m_FeatureMap.m_defaultFeatures);
   218         if (!feats) return false;
   219         const byte *pLSet = sill + offset;
   221         // Apply langauge specific settings
   222         for (int j = 0; j < numSettings; j++)
   223         {
   224             uint32 name = be::read<uint32>(pLSet);
   225             uint16 val = be::read<uint16>(pLSet);
   226             pLSet += 2;
   227             const FeatureRef* pRef = m_FeatureMap.findFeatureRef(name);
   228             if (pRef)   pRef->applyValToFeature(val, *feats);
   229         }
   230         // Add the language id feature which is always feature id 1
   231         const FeatureRef* pRef = m_FeatureMap.findFeatureRef(1);
   232         if (pRef)   pRef->applyValToFeature(langid, *feats);
   234         m_langFeats[i].m_lang = langid;
   235         m_langFeats[i].m_pFeatures = feats;
   236     }
   237     return true;
   238 }
   241 Features* SillMap::cloneFeatures(uint32 langname/*0 means default*/) const
   242 {
   243     if (langname)
   244     {
   245         // the number of languages in a font is usually small e.g. 8 in Doulos
   246         // so this loop is not very expensive
   247         for (uint16 i = 0; i < m_numLanguages; i++)
   248         {
   249             if (m_langFeats[i].m_lang == langname)
   250                 return new Features(*m_langFeats[i].m_pFeatures);
   251         }
   252     }
   253     return new Features (*m_FeatureMap.m_defaultFeatures);
   254 }
   258 const FeatureRef *FeatureMap::findFeatureRef(uint32 name) const
   259 {
   260     NameAndFeatureRef *it;
   262     for (it = m_pNamedFeats; it < m_pNamedFeats + m_numFeats; ++it)
   263         if (it->m_name == name)
   264             return it->m_pFRef;
   265     return NULL;
   266 }
   268 bool FeatureRef::applyValToFeature(uint32 val, Features & pDest) const
   269 { 
   270     if (val>maxVal() || !m_pFace)
   271       return false;
   272     if (pDest.m_pMap==NULL)
   273       pDest.m_pMap = &m_pFace->theSill().theFeatureMap();
   274     else
   275       if (pDest.m_pMap!=&m_pFace->theSill().theFeatureMap())
   276         return false;       //incompatible
   277     pDest.reserve(m_index);
   278     pDest[m_index] &= ~m_mask;
   279     pDest[m_index] |= (uint32(val) << m_bits);
   280     return true;
   281 }
   283 uint32 FeatureRef::getFeatureVal(const Features& feats) const
   284 { 
   285   if (m_index < feats.size() && &m_pFace->theSill().theFeatureMap()==feats.m_pMap) 
   286     return (feats[m_index] & m_mask) >> m_bits; 
   287   else
   288     return 0;
   289 }

mercurial