gr_face.cpp (7804B)
1 /* GRAPHITE2 LICENSING 2 3 Copyright 2010, SIL International 4 All rights reserved. 5 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. 10 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. 15 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. 21 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 "graphite2/Font.h" 28 #include "inc/Face.h" 29 #include "inc/FileFace.h" 30 #include "inc/GlyphCache.h" 31 #include "inc/CmapCache.h" 32 #include "inc/Silf.h" 33 #include "inc/json.h" 34 35 using namespace graphite2; 36 37 #if !defined GRAPHITE2_NTRACING 38 extern json *global_log; 39 #endif 40 41 namespace 42 { 43 bool load_face(Face & face, unsigned int options) 44 { 45 #ifdef GRAPHITE2_TELEMETRY 46 telemetry::category _misc_cat(face.tele.misc); 47 #endif 48 Face::Table silf(face, Tag::Silf, 0x00050000); 49 if (!silf) 50 return false; 51 52 if (!face.readGlyphs(options)) 53 return false; 54 55 if (silf) 56 { 57 if (!face.readFeatures() || !face.readGraphite(silf)) 58 { 59 #if !defined GRAPHITE2_NTRACING 60 if (global_log) 61 { 62 *global_log << json::object 63 << "type" << "fontload" 64 << "failure" << face.error() 65 << "context" << face.error_context() 66 << json::close; 67 } 68 #endif 69 return false; 70 } 71 else 72 return true; 73 } 74 else 75 return false; 76 } 77 78 inline 79 uint32 zeropad(const uint32 x) 80 { 81 if (x == 0x20202020) return 0; 82 if ((x & 0x00FFFFFF) == 0x00202020) return x & 0xFF000000; 83 if ((x & 0x0000FFFF) == 0x00002020) return x & 0xFFFF0000; 84 if ((x & 0x000000FF) == 0x00000020) return x & 0xFFFFFF00; 85 return x; 86 } 87 } 88 89 extern "C" { 90 91 gr_face* gr_make_face_with_ops(const void* appFaceHandle/*non-NULL*/, const gr_face_ops *ops, unsigned int faceOptions) 92 //the appFaceHandle must stay alive all the time when the gr_face is alive. When finished with the gr_face, call destroy_face 93 { 94 if (ops == 0) return 0; 95 96 Face *res = new Face(appFaceHandle, *ops); 97 if (res && load_face(*res, faceOptions)) 98 return static_cast<gr_face *>(res); 99 100 delete res; 101 return 0; 102 } 103 104 gr_face* gr_make_face(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn tablefn, unsigned int faceOptions) 105 { 106 const gr_face_ops ops = {sizeof(gr_face_ops), tablefn, NULL}; 107 return gr_make_face_with_ops(appFaceHandle, &ops, faceOptions); 108 } 109 110 111 gr_face* gr_make_face_with_seg_cache_and_ops(const void* appFaceHandle/*non-NULL*/, const gr_face_ops *ops, unsigned int , unsigned int faceOptions) 112 { 113 return gr_make_face_with_ops(appFaceHandle, ops, faceOptions); 114 } 115 116 gr_face* gr_make_face_with_seg_cache(const void* appFaceHandle/*non-NULL*/, gr_get_table_fn tablefn, unsigned int, unsigned int faceOptions) 117 { 118 const gr_face_ops ops = {sizeof(gr_face_ops), tablefn, NULL}; 119 return gr_make_face_with_ops(appFaceHandle, &ops, faceOptions); 120 } 121 122 gr_uint32 gr_str_to_tag(const char *str) 123 { 124 uint32 res = 0; 125 switch(max(strlen(str),size_t(4))) 126 { 127 case 4: res |= str[3]; GR_FALLTHROUGH; 128 case 3: res |= str[2] << 8; GR_FALLTHROUGH; 129 case 2: res |= str[1] << 16; GR_FALLTHROUGH; 130 case 1: res |= str[0] << 24; GR_FALLTHROUGH; 131 default: break; 132 } 133 return res; 134 } 135 136 void gr_tag_to_str(gr_uint32 tag, char *str) 137 { 138 if (!str) return; 139 140 *str++ = char(tag >> 24); 141 *str++ = char(tag >> 16); 142 *str++ = char(tag >> 8); 143 *str++ = char(tag); 144 *str = '\0'; 145 } 146 147 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 148 { 149 assert(pFace); 150 langname = zeropad(langname); 151 return static_cast<gr_feature_val *>(pFace->theSill().cloneFeatures(langname)); 152 } 153 154 155 const gr_feature_ref* gr_face_find_fref(const gr_face* pFace, gr_uint32 featId) //When finished with the FeatureRef, call destroy_FeatureRef 156 { 157 assert(pFace); 158 featId = zeropad(featId); 159 const FeatureRef* pRef = pFace->featureById(featId); 160 return static_cast<const gr_feature_ref*>(pRef); 161 } 162 163 unsigned short gr_face_n_fref(const gr_face* pFace) 164 { 165 assert(pFace); 166 int res = 0; 167 for (int i = 0; i < pFace->numFeatures(); ++i) 168 if (!(pFace->feature(i)->getFlags() & FeatureRef::HIDDEN)) 169 ++res; 170 return res; 171 } 172 173 const gr_feature_ref* gr_face_fref(const gr_face* pFace, gr_uint16 i) //When finished with the FeatureRef, call destroy_FeatureRef 174 { 175 assert(pFace); 176 int count = 0; 177 for (int j = 0; j < pFace->numFeatures(); ++j) 178 { 179 const FeatureRef* pRef = pFace->feature(j); 180 if (!(pRef->getFlags() & FeatureRef::HIDDEN)) 181 if (count++ == i) 182 return static_cast<const gr_feature_ref*>(pRef); 183 } 184 return 0; 185 } 186 187 unsigned short gr_face_n_languages(const gr_face* pFace) 188 { 189 assert(pFace); 190 return pFace->theSill().numLanguages(); 191 } 192 193 gr_uint32 gr_face_lang_by_index(const gr_face* pFace, gr_uint16 i) 194 { 195 assert(pFace); 196 return pFace->theSill().getLangName(i); 197 } 198 199 200 void gr_face_destroy(gr_face *face) 201 { 202 delete static_cast<Face*>(face); 203 } 204 205 206 gr_uint16 gr_face_name_lang_for_locale(gr_face *face, const char * locale) 207 { 208 if (face) 209 { 210 return face->languageForLocale(locale); 211 } 212 return 0; 213 } 214 215 unsigned short gr_face_n_glyphs(const gr_face* pFace) 216 { 217 return pFace->glyphs().numGlyphs(); 218 } 219 220 const gr_faceinfo *gr_face_info(const gr_face *pFace, gr_uint32 script) 221 { 222 if (!pFace) return 0; 223 const Silf *silf = pFace->chooseSilf(script); 224 if (silf) return silf->silfInfo(); 225 return 0; 226 } 227 228 int gr_face_is_char_supported(const gr_face* pFace, gr_uint32 usv, gr_uint32 script) 229 { 230 const Cmap & cmap = pFace->cmap(); 231 gr_uint16 gid = cmap[usv]; 232 if (!gid) 233 { 234 const Silf * silf = pFace->chooseSilf(script); 235 gid = silf->findPseudo(usv); 236 } 237 return (gid != 0); 238 } 239 240 #ifndef GRAPHITE2_NFILEFACE 241 gr_face* gr_make_file_face(const char *filename, unsigned int faceOptions) 242 { 243 FileFace* pFileFace = new FileFace(filename); 244 if (*pFileFace) 245 { 246 gr_face* pRes = gr_make_face_with_ops(pFileFace, &FileFace::ops, faceOptions); 247 if (pRes) 248 { 249 pRes->takeFileFace(pFileFace); //takes ownership 250 return pRes; 251 } 252 } 253 254 //error when loading 255 256 delete pFileFace; 257 return NULL; 258 } 259 260 gr_face* gr_make_file_face_with_seg_cache(const char* filename, unsigned int, unsigned int faceOptions) //returns NULL on failure. //TBD better error handling 261 //when finished with, call destroy_face 262 { 263 return gr_make_file_face(filename, faceOptions); 264 } 265 #endif //!GRAPHITE2_NFILEFACE 266 267 } // extern "C"