1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/graphite2/src/gr_face.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,282 @@ 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 "graphite2/Font.h" 1.31 +#include "inc/Face.h" 1.32 +#include "inc/FileFace.h" 1.33 +#include "inc/GlyphCache.h" 1.34 +#include "inc/CachedFace.h" 1.35 +#include "inc/CmapCache.h" 1.36 +#include "inc/Silf.h" 1.37 +#include "inc/json.h" 1.38 + 1.39 +using namespace graphite2; 1.40 + 1.41 +#if !defined GRAPHITE2_NTRACING 1.42 +extern json *global_log; 1.43 +#endif 1.44 + 1.45 +namespace 1.46 +{ 1.47 + bool load_face(Face & face, unsigned int options) 1.48 + { 1.49 +#ifdef GRAPHITE2_TELEMETRY 1.50 + telemetry::category _misc_cat(face.tele.misc); 1.51 +#endif 1.52 + Face::Table silf(face, Tag::Silf); 1.53 + if (silf) options &= ~gr_face_dumbRendering; 1.54 + else if (!(options & gr_face_dumbRendering)) 1.55 + return false; 1.56 + 1.57 + if (!face.readGlyphs(options)) 1.58 + return false; 1.59 + 1.60 + if (silf) 1.61 + { 1.62 + if (!face.readFeatures() || !face.readGraphite(silf)) 1.63 + { 1.64 +#if !defined GRAPHITE2_NTRACING 1.65 + if (global_log) 1.66 + { 1.67 + *global_log << json::object 1.68 + << "type" << "fontload" 1.69 + << "failure" << face.error() 1.70 + << "context" << face.error_context() 1.71 + << json::close; 1.72 + } 1.73 +#endif 1.74 + return false; 1.75 + } 1.76 + else 1.77 + return true; 1.78 + } 1.79 + else 1.80 + return options & gr_face_dumbRendering; 1.81 + } 1.82 +} 1.83 + 1.84 +extern "C" { 1.85 + 1.86 +gr_face* gr_make_face_with_ops(const void* appFaceHandle/*non-NULL*/, const gr_face_ops *ops, unsigned int faceOptions) 1.87 + //the appFaceHandle must stay alive all the time when the gr_face is alive. When finished with the gr_face, call destroy_face 1.88 +{ 1.89 + if (ops == 0) return 0; 1.90 + 1.91 + Face *res = new Face(appFaceHandle, *ops); 1.92 + if (res && load_face(*res, faceOptions)) 1.93 + return static_cast<gr_face *>(res); 1.94 + 1.95 + delete res; 1.96 + return 0; 1.97 +} 1.98 + 1.99 +gr_face* gr_make_face(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn tablefn, unsigned int faceOptions) 1.100 +{ 1.101 + const gr_face_ops ops = {sizeof(gr_face_ops), tablefn, NULL}; 1.102 + return gr_make_face_with_ops(appFaceHandle, &ops, faceOptions); 1.103 +} 1.104 + 1.105 +#ifndef GRAPHITE2_NSEGCACHE 1.106 +gr_face* gr_make_face_with_seg_cache_and_ops(const void* appFaceHandle/*non-NULL*/, const gr_face_ops *ops, unsigned int cacheSize, unsigned int faceOptions) 1.107 + //the appFaceHandle must stay alive all the time when the GrFace is alive. When finished with the GrFace, call destroy_face 1.108 +{ 1.109 + if (ops == 0) return 0; 1.110 + 1.111 + CachedFace *res = new CachedFace(appFaceHandle, *ops); 1.112 + if (res && load_face(*res, faceOptions) 1.113 + && res->setupCache(cacheSize)) 1.114 + return static_cast<gr_face *>(static_cast<Face *>(res)); 1.115 + 1.116 + delete res; 1.117 + return 0; 1.118 +} 1.119 + 1.120 +gr_face* gr_make_face_with_seg_cache(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn getTable, unsigned int cacheSize, unsigned int faceOptions) 1.121 +{ 1.122 + const gr_face_ops ops = {sizeof(gr_face_ops), getTable, NULL}; 1.123 + return gr_make_face_with_seg_cache_and_ops(appFaceHandle, &ops, cacheSize, faceOptions); 1.124 +} 1.125 +#endif 1.126 + 1.127 +gr_uint32 gr_str_to_tag(const char *str) 1.128 +{ 1.129 + uint32 res = 0; 1.130 + int i = strlen(str); 1.131 + if (i > 4) i = 4; 1.132 + while (--i >= 0) 1.133 + res = (res >> 8) + (str[i] << 24); 1.134 + return res; 1.135 +} 1.136 + 1.137 +void gr_tag_to_str(gr_uint32 tag, char *str) 1.138 +{ 1.139 + int i = 4; 1.140 + while (--i >= 0) 1.141 + { 1.142 + str[i] = tag & 0xFF; 1.143 + tag >>= 8; 1.144 + } 1.145 +} 1.146 + 1.147 +inline 1.148 +uint32 zeropad(const uint32 x) 1.149 +{ 1.150 + if (x == 0x20202020) return 0; 1.151 + if ((x & 0x00FFFFFF) == 0x00202020) return x & 0xFF000000; 1.152 + if ((x & 0x0000FFFF) == 0x00002020) return x & 0xFFFF0000; 1.153 + if ((x & 0x000000FF) == 0x00000020) return x & 0xFFFFFF00; 1.154 + return x; 1.155 +} 1.156 + 1.157 +gr_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 default 1.158 +{ 1.159 + assert(pFace); 1.160 + langname = zeropad(langname); 1.161 + return static_cast<gr_feature_val *>(pFace->theSill().cloneFeatures(langname)); 1.162 +} 1.163 + 1.164 + 1.165 +const gr_feature_ref* gr_face_find_fref(const gr_face* pFace, gr_uint32 featId) //When finished with the FeatureRef, call destroy_FeatureRef 1.166 +{ 1.167 + assert(pFace); 1.168 + featId = zeropad(featId); 1.169 + const FeatureRef* pRef = pFace->featureById(featId); 1.170 + return static_cast<const gr_feature_ref*>(pRef); 1.171 +} 1.172 + 1.173 +unsigned short gr_face_n_fref(const gr_face* pFace) 1.174 +{ 1.175 + assert(pFace); 1.176 + return pFace->numFeatures(); 1.177 +} 1.178 + 1.179 +const gr_feature_ref* gr_face_fref(const gr_face* pFace, gr_uint16 i) //When finished with the FeatureRef, call destroy_FeatureRef 1.180 +{ 1.181 + assert(pFace); 1.182 + const FeatureRef* pRef = pFace->feature(i); 1.183 + return static_cast<const gr_feature_ref*>(pRef); 1.184 +} 1.185 + 1.186 +unsigned short gr_face_n_languages(const gr_face* pFace) 1.187 +{ 1.188 + assert(pFace); 1.189 + return pFace->theSill().numLanguages(); 1.190 +} 1.191 + 1.192 +gr_uint32 gr_face_lang_by_index(const gr_face* pFace, gr_uint16 i) 1.193 +{ 1.194 + assert(pFace); 1.195 + return pFace->theSill().getLangName(i); 1.196 +} 1.197 + 1.198 + 1.199 +void gr_face_destroy(gr_face *face) 1.200 +{ 1.201 + delete face; 1.202 +} 1.203 + 1.204 + 1.205 +gr_uint16 gr_face_name_lang_for_locale(gr_face *face, const char * locale) 1.206 +{ 1.207 + if (face) 1.208 + { 1.209 + return face->languageForLocale(locale); 1.210 + } 1.211 + return 0; 1.212 +} 1.213 + 1.214 +unsigned short gr_face_n_glyphs(const gr_face* pFace) 1.215 +{ 1.216 + return pFace->glyphs().numGlyphs(); 1.217 +} 1.218 + 1.219 +const gr_faceinfo *gr_face_info(const gr_face *pFace, gr_uint32 script) 1.220 +{ 1.221 + if (!pFace) return 0; 1.222 + const Silf *silf = pFace->chooseSilf(script); 1.223 + if (silf) return silf->silfInfo(); 1.224 + return 0; 1.225 +} 1.226 + 1.227 +int gr_face_is_char_supported(const gr_face* pFace, gr_uint32 usv, gr_uint32 script) 1.228 +{ 1.229 + const Cmap & cmap = pFace->cmap(); 1.230 + gr_uint16 gid = cmap[usv]; 1.231 + if (!gid) 1.232 + { 1.233 + const Silf * silf = pFace->chooseSilf(script); 1.234 + gid = silf->findPseudo(usv); 1.235 + } 1.236 + return (gid != 0); 1.237 +} 1.238 + 1.239 +#ifndef GRAPHITE2_NFILEFACE 1.240 +gr_face* gr_make_file_face(const char *filename, unsigned int faceOptions) 1.241 +{ 1.242 + FileFace* pFileFace = new FileFace(filename); 1.243 + if (*pFileFace) 1.244 + { 1.245 + gr_face* pRes = gr_make_face_with_ops(pFileFace, &FileFace::ops, faceOptions); 1.246 + if (pRes) 1.247 + { 1.248 + pRes->takeFileFace(pFileFace); //takes ownership 1.249 + return pRes; 1.250 + } 1.251 + } 1.252 + 1.253 + //error when loading 1.254 + 1.255 + delete pFileFace; 1.256 + return NULL; 1.257 +} 1.258 + 1.259 +#ifndef GRAPHITE2_NSEGCACHE 1.260 +gr_face* gr_make_file_face_with_seg_cache(const char* filename, unsigned int segCacheMaxSize, unsigned int faceOptions) //returns NULL on failure. //TBD better error handling 1.261 + //when finished with, call destroy_face 1.262 +{ 1.263 + FileFace* pFileFace = new FileFace(filename); 1.264 + if (*pFileFace) 1.265 + { 1.266 + gr_face * pRes = gr_make_face_with_seg_cache_and_ops(pFileFace, &FileFace::ops, segCacheMaxSize, faceOptions); 1.267 + if (pRes) 1.268 + { 1.269 + pRes->takeFileFace(pFileFace); //takes ownership 1.270 + return pRes; 1.271 + } 1.272 + } 1.273 + 1.274 + //error when loading 1.275 + 1.276 + delete pFileFace; 1.277 + return NULL; 1.278 +} 1.279 +#endif 1.280 +#endif //!GRAPHITE2_NFILEFACE 1.281 + 1.282 + 1.283 +} // extern "C" 1.284 + 1.285 +