Path: blob/master/thirdparty/graphite/src/FeatureMap.cpp
9903 views
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later1// Copyright 2010, SIL International, All rights reserved.23#include <cstring>45#include "inc/Main.h"6#include "inc/bits.h"7#include "inc/Endian.h"8#include "inc/FeatureMap.h"9#include "inc/FeatureVal.h"10#include "graphite2/Font.h"11#include "inc/TtfUtil.h"12#include <cstdlib>13#include "inc/Face.h"141516using namespace graphite2;1718namespace19{20static int cmpNameAndFeatures(const void *ap, const void *bp)21{22const NameAndFeatureRef & a = *static_cast<const NameAndFeatureRef *>(ap),23& b = *static_cast<const NameAndFeatureRef *>(bp);24return (a < b ? -1 : (b < a ? 1 : 0));25}2627const size_t FEAT_HEADER = sizeof(uint32) + 2*sizeof(uint16) + sizeof(uint32),28FEATURE_SIZE = sizeof(uint32)29+ 2*sizeof(uint16)30+ sizeof(uint32)31+ 2*sizeof(uint16),32FEATURE_SETTING_SIZE = sizeof(int16) + sizeof(uint16);3334uint16 readFeatureSettings(const byte * p, FeatureSetting * s, size_t num_settings)35{36uint16 max_val = 0;37for (FeatureSetting * const end = s + num_settings; s != end; ++s)38{39const int16 value = be::read<int16>(p);40::new (s) FeatureSetting(value, be::read<uint16>(p));41if (uint16(value) > max_val) max_val = value;42}4344return max_val;45}46}4748FeatureRef::FeatureRef(const Face & face,49unsigned short & bits_offset, uint32 max_val,50uint32 name, uint16 uiName, flags_t flags,51FeatureSetting *settings, uint16 num_set) throw()52: m_face(&face),53m_nameValues(settings),54m_mask(mask_over_val(max_val)),55m_max(max_val),56m_id(name),57m_nameid(uiName),58m_numSet(num_set),59m_flags(flags)60{61const uint8 need_bits = bit_set_count(m_mask);62m_index = (bits_offset + need_bits) / SIZEOF_CHUNK;63if (m_index > bits_offset / SIZEOF_CHUNK)64bits_offset = m_index*SIZEOF_CHUNK;65m_bits = bits_offset % SIZEOF_CHUNK;66bits_offset += need_bits;67m_mask <<= m_bits;68}6970FeatureRef::~FeatureRef() throw()71{72free(m_nameValues);73}7475bool FeatureMap::readFeats(const Face & face)76{77const Face::Table feat(face, TtfUtil::Tag::Feat);78const byte * p = feat;79if (!p) return true;80if (feat.size() < FEAT_HEADER) return false;8182const byte *const feat_start = p,83*const feat_end = p + feat.size();8485const uint32 version = be::read<uint32>(p);86m_numFeats = be::read<uint16>(p);87be::skip<uint16>(p);88be::skip<uint32>(p);8990// Sanity checks91if (m_numFeats == 0) return true;92if (version < 0x00010000 ||93p + m_numFeats*FEATURE_SIZE > feat_end)94{ //defensive95m_numFeats = 0;96return false;97}9899m_feats = new FeatureRef [m_numFeats];100uint16 * const defVals = gralloc<uint16>(m_numFeats);101if (!defVals || !m_feats) return false;102unsigned short bits = 0; //to cause overflow on first Feature103104for (int i = 0, ie = m_numFeats; i != ie; i++)105{106const uint32 label = version < 0x00020000 ? be::read<uint16>(p) : be::read<uint32>(p);107const uint16 num_settings = be::read<uint16>(p);108if (version >= 0x00020000)109be::skip<uint16>(p);110const uint32 settings_offset = be::read<uint32>(p);111const uint16 flags = be::read<uint16>(p),112uiName = be::read<uint16>(p);113114if (settings_offset > size_t(feat_end - feat_start)115|| settings_offset + num_settings * FEATURE_SETTING_SIZE > size_t(feat_end - feat_start))116{117free(defVals);118return false;119}120121FeatureSetting *uiSet;122uint32 maxVal;123if (num_settings != 0)124{125uiSet = gralloc<FeatureSetting>(num_settings);126if (!uiSet)127{128free(defVals);129return false;130}131maxVal = readFeatureSettings(feat_start + settings_offset, uiSet, num_settings);132defVals[i] = uiSet[0].value();133}134else135{136uiSet = 0;137maxVal = 0xffffffff;138defVals[i] = 0;139}140141::new (m_feats + i) FeatureRef (face, bits, maxVal,142label, uiName,143FeatureRef::flags_t(flags),144uiSet, num_settings);145}146new (&m_defaultFeatures) Features(bits/(sizeof(uint32)*8) + 1, *this);147m_pNamedFeats = new NameAndFeatureRef[m_numFeats];148if (!m_pNamedFeats)149{150free(defVals);151return false;152}153for (int i = 0; i < m_numFeats; ++i)154{155m_feats[i].applyValToFeature(defVals[i], m_defaultFeatures);156m_pNamedFeats[i] = m_feats[i];157}158159free(defVals);160161qsort(m_pNamedFeats, m_numFeats, sizeof(NameAndFeatureRef), &cmpNameAndFeatures);162163return true;164}165166bool SillMap::readFace(const Face & face)167{168if (!m_FeatureMap.readFeats(face)) return false;169if (!readSill(face)) return false;170return true;171}172173174bool SillMap::readSill(const Face & face)175{176const Face::Table sill(face, TtfUtil::Tag::Sill);177const byte *p = sill;178179if (!p) return true;180if (sill.size() < 12) return false;181if (be::read<uint32>(p) != 0x00010000UL) return false;182m_numLanguages = be::read<uint16>(p);183m_langFeats = new LangFeaturePair[m_numLanguages];184if (!m_langFeats || !m_FeatureMap.m_numFeats) { m_numLanguages = 0; return true; } //defensive185186p += 6; // skip the fast search187if (sill.size() < m_numLanguages * 8U + 12) return false;188189for (int i = 0; i < m_numLanguages; i++)190{191uint32 langid = be::read<uint32>(p);192uint16 numSettings = be::read<uint16>(p);193uint16 offset = be::read<uint16>(p);194if (offset + 8U * numSettings > sill.size() && numSettings > 0) return false;195Features* feats = new Features(m_FeatureMap.m_defaultFeatures);196if (!feats) return false;197const byte *pLSet = sill + offset;198199// Apply langauge specific settings200for (int j = 0; j < numSettings; j++)201{202uint32 name = be::read<uint32>(pLSet);203uint16 val = be::read<uint16>(pLSet);204pLSet += 2;205const FeatureRef* pRef = m_FeatureMap.findFeatureRef(name);206if (pRef) pRef->applyValToFeature(val, *feats);207}208// Add the language id feature which is always feature id 1209const FeatureRef* pRef = m_FeatureMap.findFeatureRef(1);210if (pRef) pRef->applyValToFeature(langid, *feats);211212m_langFeats[i].m_lang = langid;213m_langFeats[i].m_pFeatures = feats;214}215return true;216}217218219Features* SillMap::cloneFeatures(uint32 langname/*0 means default*/) const220{221if (langname)222{223// the number of languages in a font is usually small e.g. 8 in Doulos224// so this loop is not very expensive225for (uint16 i = 0; i < m_numLanguages; i++)226{227if (m_langFeats[i].m_lang == langname)228return new Features(*m_langFeats[i].m_pFeatures);229}230}231return new Features (m_FeatureMap.m_defaultFeatures);232}233234235236const FeatureRef *FeatureMap::findFeatureRef(uint32 name) const237{238NameAndFeatureRef *it;239240for (it = m_pNamedFeats; it < m_pNamedFeats + m_numFeats; ++it)241if (it->m_name == name)242return it->m_pFRef;243return NULL;244}245246bool FeatureRef::applyValToFeature(uint32 val, Features & pDest) const247{248if (val>maxVal() || !m_face)249return false;250if (pDest.m_pMap==NULL)251pDest.m_pMap = &m_face->theSill().theFeatureMap();252else253if (pDest.m_pMap!=&m_face->theSill().theFeatureMap())254return false; //incompatible255if (m_index >= pDest.size())256pDest.resize(m_index+1);257pDest[m_index] &= ~m_mask;258pDest[m_index] |= (uint32(val) << m_bits);259return true;260}261262uint32 FeatureRef::getFeatureVal(const Features& feats) const263{264if (m_index < feats.size() && m_face265&& &m_face->theSill().theFeatureMap()==feats.m_pMap)266return (feats[m_index] & m_mask) >> m_bits;267else268return 0;269}270271272