/// // Copyright (C) 2003, 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING /// // to build as stand-alone program: // g++ -Wall -DUNICODE_STANDALONE -o unicode $(pkg-config --cflags --libs glibmm-2.0) glyphs.cc unicode.cc #include "unicode.h" #include #include #ifdef UNICODE_STANDALONE #include #endif // look up glyph in ZapfDingbats list bool PS::Unicode::get_dingbat(const std::string &glyph, Glib::ustring &answer){ if(dingbats.namemap.find(glyph) == dingbats.namemap.end()) return false; answer = *(dingbats.namemap.find(glyph)->second); return true; } // look up glyph in Adobe Glyph list bool PS::Unicode::get_adobe(const std::string &glyph, Glib::ustring &answer){ if(glyphlist.namemap.find(glyph) == glyphlist.namemap.end()) return false; answer = *(glyphlist.namemap.find(glyph)->second); return true; } namespace { bool uppercase_hex(const std::string s) { for(std::string::const_iterator i = s.begin(); i != s.end(); i++) if(!((*i >= 'A' && *i <= 'F') || (*i >= '0' && *i <= '9'))) return false; return true; } }; // try to parse glyph as "uni" + hex bool PS::Unicode::get_uniform(const std::string &glyph, Glib::ustring &answer){ unsigned int l = glyph.length(); if(glyph.substr(0, 3) != "uni") return false; if(l < 7 || ((l - 3) % 4) != 0) // must be groups of four hex digits return false; if(!uppercase_hex(glyph.substr(3))) // must be hex return false; // We're in business! answer = ""; unsigned int i = 3; while(i < l) { std::stringstream s(glyph.substr(i, 4)); s.setf(std::ios::hex, std::ios::basefield); gunichar c; s >> c; answer += c; i += 4; } return true; } // try to parse glyph as "u" + hex bool PS::Unicode::get_uform(const std::string &glyph, Glib::ustring &answer){ unsigned int l = glyph.length(); if(glyph[0] != 'u') return false; if(l != 5 && l != 7) // must have 4 or six digits return false; if(!uppercase_hex(glyph.substr(1))) // must be hex return false; // We're in business! std::stringstream s(glyph.substr(1)); s.setf(std::ios::hex, std::ios::basefield); gunichar c; s >> c; answer = c; return true; } Glib::ustring PS::Unicode::chars_of_glyph(const std::string &glyph_name, bool dingbats) { // According to the Unicode and Glyph Names specification // (http://partners.adobe.com/asn/developer/type/unicodegn.html) Glib::ustring result; // strip everything after '.' std::string g = glyph_name.substr(0, glyph_name.find_first_of('.')); unsigned int length = g.length(); // split string into components, separated by '_' // and process them individually unsigned int i = 0, m; do { m = g.find_first_of('_', i); std::string comp = g.substr(i, m); Glib::ustring part; if((dingbats && get_dingbat(comp, part)) || get_adobe(comp, part) || get_uniform(comp, part) || get_uform(comp, part)) result += part; // else add the empty string to result, i.e. do nothing i = m + 1; } while(i < length && m < length); return result; // Note: Most fonts dont have glyph names with '.' or '_' in them. // Also, most fonts encountered by the developers does not use the // unicode form, so the code above has not been thoroughly tested. } std::string PS::Unicode::glyph_name_of_chars(Glib::ustring chars) { std::string tmp; typedef Glyphs::CodeMap::const_iterator I; std::pair range = glyphlist.codemap.equal_range(chars); for(I i = range.first; i != range.second; i++) tmp += " " + *(i->second); range = dingbats.codemap.equal_range(chars); for(I i = range.first; i != range.second; i++) tmp += " " + *(i->second); if(tmp.length() > 1) return tmp.substr(1); return ""; } #ifdef UNICODE_STANDALONE int main(int argc, char **argv) { using namespace std; unsigned char foo; while(cin >> foo) { cout << "\"" << PS::Unicode::glyph_name_of_chars(Glib::ustring(Glib::ustring::size_type(1), gunichar(foo))) << "\"" << endl; } // using namespace std; // string foo; // while(cin >> foo) { // const Glib::ustring bar = PS::Unicode::chars_of_glyph(foo, true); // cerr << "\"" << bar.raw() << "\"" << endl; // if(bar.empty()) // cerr << "No match: " << foo << endl; // for(Glib::ustring::const_iterator i = bar.begin(); i != bar.end(); i++) // cout << *i << " "; // cout << endl; // } return 0; } #endif