Path: blob/master/thirdparty/graphite/src/gr_face.cpp
9902 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 "graphite2/Font.h"4#include "inc/Face.h"5#include "inc/FileFace.h"6#include "inc/GlyphCache.h"7#include "inc/CmapCache.h"8#include "inc/Silf.h"9#include "inc/json.h"1011using namespace graphite2;1213#if !defined GRAPHITE2_NTRACING14extern json *global_log;15#endif1617namespace18{19bool load_face(Face & face, unsigned int options)20{21#ifdef GRAPHITE2_TELEMETRY22telemetry::category _misc_cat(face.tele.misc);23#endif24Face::Table silf(face, Tag::Silf, 0x00050000);25if (!silf)26return false;2728if (!face.readGlyphs(options))29return false;3031if (silf)32{33if (!face.readFeatures() || !face.readGraphite(silf))34{35#if !defined GRAPHITE2_NTRACING36if (global_log)37{38*global_log << json::object39<< "type" << "fontload"40<< "failure" << face.error()41<< "context" << face.error_context()42<< json::close;43}44#endif45return false;46}47else48return true;49}50else51return false;52}5354inline55uint32 zeropad(const uint32 x)56{57if (x == 0x20202020) return 0;58if ((x & 0x00FFFFFF) == 0x00202020) return x & 0xFF000000;59if ((x & 0x0000FFFF) == 0x00002020) return x & 0xFFFF0000;60if ((x & 0x000000FF) == 0x00000020) return x & 0xFFFFFF00;61return x;62}63}6465extern "C" {6667gr_face* gr_make_face_with_ops(const void* appFaceHandle/*non-NULL*/, const gr_face_ops *ops, unsigned int faceOptions)68//the appFaceHandle must stay alive all the time when the gr_face is alive. When finished with the gr_face, call destroy_face69{70if (ops == 0) return 0;7172Face *res = new Face(appFaceHandle, *ops);73if (res && load_face(*res, faceOptions))74return static_cast<gr_face *>(res);7576delete res;77return 0;78}7980gr_face* gr_make_face(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn tablefn, unsigned int faceOptions)81{82const gr_face_ops ops = {sizeof(gr_face_ops), tablefn, NULL};83return gr_make_face_with_ops(appFaceHandle, &ops, faceOptions);84}858687gr_face* gr_make_face_with_seg_cache_and_ops(const void* appFaceHandle/*non-NULL*/, const gr_face_ops *ops, unsigned int , unsigned int faceOptions)88{89return gr_make_face_with_ops(appFaceHandle, ops, faceOptions);90}9192gr_face* gr_make_face_with_seg_cache(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn tablefn, unsigned int, unsigned int faceOptions)93{94const gr_face_ops ops = {sizeof(gr_face_ops), tablefn, NULL};95return gr_make_face_with_ops(appFaceHandle, &ops, faceOptions);96}9798gr_uint32 gr_str_to_tag(const char *str)99{100uint32 res = 0;101switch(max(strlen(str),size_t(4)))102{103case 4: res |= str[3]; GR_FALLTHROUGH;104case 3: res |= str[2] << 8; GR_FALLTHROUGH;105case 2: res |= str[1] << 16; GR_FALLTHROUGH;106case 1: res |= str[0] << 24; GR_FALLTHROUGH;107default: break;108}109return res;110}111112void gr_tag_to_str(gr_uint32 tag, char *str)113{114if (!str) return;115116*str++ = char(tag >> 24);117*str++ = char(tag >> 16);118*str++ = char(tag >> 8);119*str++ = char(tag);120*str = '\0';121}122123gr_feature_val* gr_face_featureval_for_lang(const gr_face* pFace, gr_uint32 langname/*0 means clone default*/) //clones the features. if none for language, clones the default124{125assert(pFace);126langname = zeropad(langname);127return static_cast<gr_feature_val *>(pFace->theSill().cloneFeatures(langname));128}129130131const gr_feature_ref* gr_face_find_fref(const gr_face* pFace, gr_uint32 featId) //When finished with the FeatureRef, call destroy_FeatureRef132{133assert(pFace);134featId = zeropad(featId);135const FeatureRef* pRef = pFace->featureById(featId);136return static_cast<const gr_feature_ref*>(pRef);137}138139unsigned short gr_face_n_fref(const gr_face* pFace)140{141assert(pFace);142int res = 0;143for (int i = 0; i < pFace->numFeatures(); ++i)144if (!(pFace->feature(i)->getFlags() & FeatureRef::HIDDEN))145++res;146return res;147}148149const gr_feature_ref* gr_face_fref(const gr_face* pFace, gr_uint16 i) //When finished with the FeatureRef, call destroy_FeatureRef150{151assert(pFace);152int count = 0;153for (int j = 0; j < pFace->numFeatures(); ++j)154{155const FeatureRef* pRef = pFace->feature(j);156if (!(pRef->getFlags() & FeatureRef::HIDDEN))157if (count++ == i)158return static_cast<const gr_feature_ref*>(pRef);159}160return 0;161}162163unsigned short gr_face_n_languages(const gr_face* pFace)164{165assert(pFace);166return pFace->theSill().numLanguages();167}168169gr_uint32 gr_face_lang_by_index(const gr_face* pFace, gr_uint16 i)170{171assert(pFace);172return pFace->theSill().getLangName(i);173}174175176void gr_face_destroy(gr_face *face)177{178delete static_cast<Face*>(face);179}180181182gr_uint16 gr_face_name_lang_for_locale(gr_face *face, const char * locale)183{184if (face)185{186return face->languageForLocale(locale);187}188return 0;189}190191unsigned short gr_face_n_glyphs(const gr_face* pFace)192{193return pFace->glyphs().numGlyphs();194}195196const gr_faceinfo *gr_face_info(const gr_face *pFace, gr_uint32 script)197{198if (!pFace) return 0;199const Silf *silf = pFace->chooseSilf(script);200if (silf) return silf->silfInfo();201return 0;202}203204int gr_face_is_char_supported(const gr_face* pFace, gr_uint32 usv, gr_uint32 script)205{206const Cmap & cmap = pFace->cmap();207gr_uint16 gid = cmap[usv];208if (!gid)209{210const Silf * silf = pFace->chooseSilf(script);211gid = silf->findPseudo(usv);212}213return (gid != 0);214}215216#ifndef GRAPHITE2_NFILEFACE217gr_face* gr_make_file_face(const char *filename, unsigned int faceOptions)218{219FileFace* pFileFace = new FileFace(filename);220if (*pFileFace)221{222gr_face* pRes = gr_make_face_with_ops(pFileFace, &FileFace::ops, faceOptions);223if (pRes)224{225pRes->takeFileFace(pFileFace); //takes ownership226return pRes;227}228}229230//error when loading231232delete pFileFace;233return NULL;234}235236gr_face* gr_make_file_face_with_seg_cache(const char* filename, unsigned int, unsigned int faceOptions) //returns NULL on failure. //TBD better error handling237//when finished with, call destroy_face238{239return gr_make_file_face(filename, faceOptions);240}241#endif //!GRAPHITE2_NFILEFACE242243} // extern "C"244245246