Logo Search packages:      
Sourcecode: passepartout version File versions  Download package

unicode.cc

///
// 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 <sstream>
#include <iomanip>
#ifdef UNICODE_STANDALONE
#include <iostream>
#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<I, I> 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

Generated by  Doxygen 1.6.0   Back to index