/[freetype]/freetype2/src/tools/glnames.py
ViewVC logotype

Diff of /freetype2/src/tools/glnames.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.5 by werner, Mon Jun 23 19:26:53 2003 UTC revision 1.6 by freetype, Wed Mar 9 17:33:03 2005 UTC
# Line 27  usage: %s <output-file> Line 27  usage: %s <output-file>
27  """  """
28    
29    
30  import sys, string  import sys, string, struct
31    
32    
33  # This table is used to name the glyphs according to the Macintosh  # This table is used to name the glyphs according to the Macintosh
# Line 412  t1_expert_encoding = \ Line 412  t1_expert_encoding = \
412  # version 2.0, 22 Sept 2002.  It is available from  # version 2.0, 22 Sept 2002.  It is available from
413  #  #
414  #   http://partners.adobe.com/asn/developer/typeforum/unicodegn.html  #   http://partners.adobe.com/asn/developer/typeforum/unicodegn.html
415    #   http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt
416  #  #
417  adobe_glyph_list = """\  adobe_glyph_list = """\
418  A;0041  A;0041
# Line 4698  zukatakana;30BA Line 4699  zukatakana;30BA
4699  """  """
4700    
4701    
4702    # string table management
4703    #
4704    class StringTable:
4705      def __init__(self,name_list):
4706        self.names   = name_list
4707        self.indices = {}
4708        index        = 0
4709        
4710        for name in name_list:
4711          self.indices[name] = index
4712          index += len(name) + 1
4713          
4714        self.total = index      
4715    
4716      def dump(self,file,table_name):
4717        write = file.write
4718        write( "static const char " + table_name + "["+repr(self.total)+"] =\n" )
4719        write( "{\n" )
4720        column = 0
4721        line   = "  "
4722        comma  = ""
4723        for name in self.names:
4724          for n in range(len(name)):
4725             line += comma
4726             line += "'%c'" % name[n]
4727             comma  = ","
4728             column += 1
4729             if column == 16:
4730               column = 0
4731               comma  = ",\n  "
4732          line += comma
4733          line += " 0 "
4734          comma = ","
4735          column += 1
4736          if column == 16:
4737            column = 0
4738            comma  = ",\n  "
4739            
4740        if column != 0:
4741          line += "\n"
4742    
4743        write( line + "};\n\n" )
4744    
4745      def dump_sublist(self,file,table_name,macro_name,sublist):
4746        write = file.write
4747        write( "#define "+macro_name+"  "+repr(len(sublist))+"\n\n" )
4748        write( "static const short " + table_name + "["+repr(len(sublist))+"] =\n" )
4749        write( "{\n" )
4750        line  = "  "
4751        comma = ""
4752        col   = 0
4753        for name in sublist:
4754          line += comma
4755          line += "%4d" % self.indices[name]
4756          col  += 1
4757          comma = ","
4758          if col == 14:
4759            col = 0
4760            comma = ",\n  "
4761          
4762        write( line + "\n};\n\n" )
4763        
4764    
4765    class StringNode:
4766      def __init__(self,letter,value):
4767        self.letter   = letter
4768        self.value    = value
4769        self.children = {}
4770    
4771      def __cmp__(self,other):
4772        return ord(self.letter[0]) - ord(other.letter[0])
4773    
4774      def add(self,word,value):
4775        if len(word) == 0:
4776          self.value = value
4777          return
4778        letter = word[0]
4779        word   = word[1:]
4780        if self.children.has_key(letter):
4781          child = self.children[letter]
4782        else:
4783          child = StringNode(letter,0)
4784          self.children[letter] = child
4785        child.add(word,value)
4786    
4787      def optimize(self):
4788        # optimize all children first
4789        children = self.children.values()
4790        self.children = {}
4791        for child in children:
4792          self.children[child.letter[0]] = child.optimize()
4793    
4794        # don't optimize if there's a value,
4795        # if we don't have any child or if we
4796        # have more than one child
4797        if (self.value != 0) or (not children) or len(children) > 1:
4798          return self
4799    
4800        child = children[0]
4801        self.letter += child.letter
4802        self.value = child.value
4803        self.children = child.children
4804        return self
4805    
4806      def dump_debug(self,write,margin):
4807        # this is used during debugging
4808        line = margin + "+-"
4809        if len(self.letter) == 0:
4810          line += "<NOLETTER>"
4811        else:
4812          line += self.letter
4813    
4814        if self.value:
4815          line += " => " + repr(self.value)
4816    
4817        write( line+"\n" )
4818        if self.children:
4819          margin += "| "
4820          for child in self.children.values():
4821            child.dump_debug(write,margin)
4822      
4823      def locate(self,index):
4824        self.index = index
4825        if len(self.letter) > 0:    
4826          index += len(self.letter)+1
4827        else:
4828          index += 2
4829          
4830        if self.value != 0:
4831          index += 2
4832          
4833        children = self.children.values()
4834        children.sort()
4835        index += 2*len(children)
4836        for child in children:
4837          index = child.locate(index)
4838    
4839        return index
4840    
4841      def store(self,storage):
4842        # write the letters
4843        l = len(self.letter)
4844        if l == 0:
4845          storage += struct.pack("B",0)
4846        else:
4847          for n in range(l):
4848            val = ord(self.letter[n])
4849            if n < l-1:
4850              val += 128
4851            storage += struct.pack("B",val)
4852    
4853        # write the count
4854        children = self.children.values()
4855        children.sort()
4856        count    = len(children)
4857        if self.value != 0:
4858          storage += struct.pack( "!BH", count+128, self.value )
4859        else:
4860          storage += struct.pack( "B", count )
4861    
4862        for child in children:
4863          storage += struct.pack( "!H", child.index )
4864    
4865        for child in children:
4866          storage = child.store(storage)
4867    
4868        return storage
4869    
4870  t1_bias    = 0  t1_bias    = 0
4871  glyph_list = []  glyph_list = []
4872    
# Line 4751  def filter_glyph_names( alist, filter ): Line 4920  def filter_glyph_names( alist, filter ):
4920    return extras    return extras
4921    
4922    
 def dump_mac_indices( file, all_glyphs ):  
   write = file.write  
   
   write( "  static const unsigned short  mac_standard_names[" + \  
          repr( len( mac_standard_names ) + 1 ) + "] =\n" )  
   write( "  {\n" )  
   
   for name in mac_standard_names:  
     write( "    " + repr( all_glyphs.index( name ) ) + ",\n" )  
   
   write( "    0\n" )  
   write( "  };\n" )  
   write( "\n" )  
   write( "\n" )  
   
   
 def dump_glyph_list( file, base_list, adobe_list ):  
   write = file.write  
   
   name_list = []  
   
   write( "  static const char* const  ps_glyph_names[] =\n" )  
   write( "  {\n" )  
   
   for name in base_list:  
     write( '    "' + name + '",\n' )  
     name_list.append( name )  
   
   write( "\n" )  
   write( "#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST\n" )  
   write( "\n" )  
   
   for name in adobe_list:  
     write( '    "' + name + '",\n' )  
     name_list.append( name )  
   
   write( "\n" )  
   write( "#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */\n" )  
   write( "\n" )  
   write( "    NULL\n" )  
   write( "  };\n" )  
   write( "\n" )  
   write( "\n" )  
   
   return name_list  
   
   
 def dump_unicode_values( file, sid_list, adobe_list ):  
   """build the glyph names to unicode values table"""  
   
   write = file.write  
   
   agl_names, agl_unicodes = adobe_glyph_values()  
   
   write( "\n" )  
   write( "  static const unsigned short  ps_names_to_unicode[" + \  
           repr( len( sid_list ) + len( adobe_list ) + 1 ) + "] =\n" )  
   write( "  {\n" )  
   
   for name in sid_list:  
     try:  
       index = agl_names.index( name )  
       write( "    0x" + agl_unicodes[index] + "U,\n" )  
     except:  
       write( "    0,\n" )  
   
   write( "\n" )  
   write( "#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST\n" )  
   write( "\n" )  
   
   for name in adobe_list:  
     try:  
       index = agl_names.index( name )  
       write( "    0x" + agl_unicodes[index] + "U,\n" )  
     except:  
       write( "    0,\n" )  
   
   write( "\n" )  
   write( "#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */\n" )  
   write( "    0\n" )  
   write( "  };\n" )  
   write( "\n" )  
   write( "\n" )  
   write( "\n" )  
   
4923    
4924  def dump_encoding( file, encoding_name, encoding_list ):  def dump_encoding( file, encoding_name, encoding_list ):
4925    """dumps a given encoding"""    """dumps a given encoding"""
4926    
4927    write = file.write    write = file.write
4928      write( "/* the following are indices into the SID name table */\n" )
4929      write( "static const unsigned short  " + encoding_name + "[" + \
4930              repr( len( encoding_list ) ) + "] =\n" )
4931      write( "{\n" )
4932    
4933      line  = "  "
4934      comma = ""
4935      col   = 0
4936      for value in encoding_list:
4937        line += comma
4938        line += "%3d" % value
4939        comma = ","
4940        col  += 1
4941        if col == 16:
4942          col = 0
4943          comma = ",\n  "
4944          
4945      write( line + "\n};\n\n" )  
4946    
4947      
4948    def dump_array( the_array, write, array_name ):
4949      """dumps a given encoding"""
4950    
4951    write( "  static const unsigned short  " + encoding_name + "[" + \    write( "static const unsigned char  " + array_name + "[" + \
4952            repr( len( encoding_list ) + 1 ) + "] =\n" )            repr(len(the_array)) + "] =\n" )
4953    write( "  {\n" )    write( "{\n" )
4954      line  = ""
4955    for value in encoding_list:    comma = "  "
4956      write( "    " + repr( value ) + ",\n" )    col   = 0
4957    write( "    0\n" )    for value in the_array:
4958    write( "  };\n" )      line += comma
4959    write( "\n" )      line += "%3d" % ord(value)
4960    write( "\n" )      comma = ","
4961        col  += 1
4962        if col == 16:
4963          col = 0
4964          comma = ",\n  "
4965          
4966        if len(line) > 1024:
4967          write( line )
4968          line = ""
4969    
4970      write( line + "\n};\n\n" )  
4971    
4972    
4973    
4974  def main():  def main():
4975    """main program body"""    """main program body"""
# Line 4867  def main(): Line 4984  def main():
4984    count_sid = len( sid_standard_names )    count_sid = len( sid_standard_names )
4985    
4986    # 'mac_extras' contains the list of glyph names in the Macintosh standard    # 'mac_extras' contains the list of glyph names in the Macintosh standard
4987    # encoding which are not in either the Adobe Glyph List or the SID    # encoding which are not in the SID Standard Names.
   # Standard Names.  
4988    #    #
4989    mac_extras = filter_glyph_names( mac_standard_names, adobe_glyph_names() )    mac_extras = filter_glyph_names( mac_standard_names, sid_standard_names )
   mac_extras = filter_glyph_names( mac_extras, sid_standard_names )  
4990    
4991    # 'base_list' contains the first names of our final glyph names table.    # 'base_list' contains the names of our final glyph names table.
4992    # It consists of the 'mac_extras' glyph names, followed by the SID    # It consists of the 'mac_extras' glyph names, followed by the SID
4993    # Standard names.    # Standard names.
4994    #    #
# Line 4881  def main(): Line 4996  def main():
4996    t1_bias          = mac_extras_count    t1_bias          = mac_extras_count
4997    base_list        = mac_extras + sid_standard_names    base_list        = mac_extras + sid_standard_names
4998    
   # 'adobe_list' contains the glyph names that are in the AGL, but not in  
   # the base_list; they will be placed after base_list glyph names in  
   # our final table.  
   #  
   adobe_list  = filter_glyph_names( adobe_glyph_names(), base_list )  
   adobe_count = len( adobe_list )  
   
4999    write( "/***************************************************************************/\n" )    write( "/***************************************************************************/\n" )
5000    write( "/*                                                                         */\n" )    write( "/*                                                                         */\n" )
5001    
5002    write( "/*  %-71s*/\n" % sys.argv[1] )    write( "/*  %-71s*/\n" % sys.argv[1] )
5003    
5004    write( "/*                                                                         */\n" )    write( "/*                                                                         */\n" )
5005    write( "/*    PostScript glyph names (specification only).                         */\n" )    write( "/*    PostScript glyph names.                                              */\n" )
5006    write( "/*                                                                         */\n" )    write( "/*                                                                         */\n" )
5007    write( "/*  Copyright 2000-2001, 2003 by                                           */\n" )    write( "/*  Copyright 2005 by                                                      */\n" )
5008    write( "/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */\n" )    write( "/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */\n" )
5009    write( "/*                                                                         */\n" )    write( "/*                                                                         */\n" )
5010    write( "/*  This file is part of the FreeType project, and may only be used,       */\n" )    write( "/*  This file is part of the FreeType project, and may only be used,       */\n" )
# Line 4908  def main(): Line 5016  def main():
5016    write( "/***************************************************************************/\n" )    write( "/***************************************************************************/\n" )
5017    write( "\n" )    write( "\n" )
5018    write( "\n" )    write( "\n" )
5019    write( "  /* this file has been generated automatically -- do not edit! */\n" )    write( "  /* ALL of this file has been generated automatically -- do not edit! */\n"  )
5020    write( "\n" )    write( "\n" )
5021    write( "\n" )    write( "\n" )
5022    
5023    # dump final glyph list (mac extras + sid standard names + AGL glyph names)    # dump final glyph list (mac extras + sid standard names)
5024    #    #
5025    name_list = dump_glyph_list( file, base_list, adobe_list )    st = StringTable(base_list)
5026      
5027    # dump t1_standard_list    st.dump(file,"ft_standard_glyph_names")
5028    write( "  static const char* const * const  sid_standard_names = " \    st.dump_sublist(file,"ft_mac_names","FT_NUM_MAC_NAMES",mac_standard_names)
5029            + "ps_glyph_names + " + repr( t1_bias ) + ";\n" )    st.dump_sublist(file,"ft_sid_names","FT_NUM_SID_NAMES",sid_standard_names)
   write( "\n" )  
   write( "\n" )  
   
   write( "#define NUM_SID_GLYPHS " + repr( len( sid_standard_names ) ) + "\n" )  
   write( "\n" )  
   write( "#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST\n" )  
   write( "#define NUM_ADOBE_GLYPHS " + \  
           repr( len( base_list ) + len( adobe_list ) - t1_bias ) + "\n" )  
   write( "#else\n" )  
   write( "#define NUM_ADOBE_GLYPHS " + \  
           repr( len( base_list ) - t1_bias )  + "\n" )  
   write( "#endif\n" )  
   write( "\n" )  
   write( "\n" )  
   
   # dump mac indices table  
   dump_mac_indices( file, name_list )  
   
   # dump unicode values table  
   dump_unicode_values( file, sid_standard_names, adobe_list )  
5030    
5031    dump_encoding( file, "t1_standard_encoding", t1_standard_encoding )    dump_encoding( file, "t1_standard_encoding", t1_standard_encoding )
5032    dump_encoding( file, "t1_expert_encoding", t1_expert_encoding )    dump_encoding( file, "t1_expert_encoding", t1_expert_encoding )
5033    
5034    write( "/* END */\n" )    # dump the AGL in its compressed form
5035      #
5036      agl_glyphs, agl_values = adobe_glyph_values()
5037      dict = StringNode( "", 0 )
5038      for g in range(len(agl_glyphs)):
5039        dict.add(agl_glyphs[g],eval("0x"+agl_values[g]))
5040    
5041      dict = dict.optimize()
5042      dict_len   = dict.locate(0)
5043      dict_array = dict.store("")
5044    
5045      write( """
5046     /* this table is a compressed version of the Adobe Glyph List
5047      * which has been optimized for efficient searching. It has
5048      * been generated by the 'glnames.py' python script located
5049      * in the 'src/tools' directory.
5050      *
5051      * the corresponding lookup function is defined just below
5052      * the table (several pages down this text :-)
5053      */
5054    """ )
5055      
5056      dump_array(dict_array,write,"ft_adobe_glyph_list")
5057    
5058      # write the lookup routine now
5059      #
5060      write( """
5061     /* this is the wicked routine used to search our compressed
5062      * table efficiently
5063      */
5064      static unsigned long
5065      ft_get_adobe_glyph_index( const char*  name,
5066                                const char*  limit )
5067      {
5068        int                   c = 0;
5069        int                   count, min, max;
5070        const unsigned char*  p = ft_adobe_glyph_list;
5071    
5072        if ( name == 0 || name >= limit )
5073          goto NotFound;
5074    
5075        c     = *name++;
5076        count = p[1];
5077        p    += 2;
5078    
5079        min = 0;
5080        max = count;
5081    
5082        while ( min < max )
5083        {
5084          int                   mid    = (min+max) >> 1;
5085          const unsigned char*  q      = p + mid*2;
5086          int                   c2;
5087    
5088          q = ft_adobe_glyph_list + (((int)q[0] << 8) | q[1]);
5089    
5090          c2 = q[0] & 127;
5091          if ( c2 == c )
5092          {
5093            p = q;
5094            goto Found;
5095          }
5096          if ( c2 < c )
5097            min = mid+1;
5098          else
5099            max = mid;
5100        }
5101        goto NotFound;
5102    
5103      Found:
5104        for (;;)
5105        {
5106          /* assert (*p & 127) == c */
5107    
5108          if ( name >= limit )
5109          {
5110            if ( (p[0] & 128) == 0 &&
5111                 (p[1] & 128) != 0 )
5112              return (unsigned long)(((int)p[2] << 8) | p[3]);
5113    
5114            goto NotFound;
5115          }
5116          c = *name++;
5117          if ( p[0] & 128 )
5118          {
5119            p++;
5120            if ( c != (p[0] & 127) )
5121              goto NotFound;
5122    
5123            continue;
5124          }
5125    
5126          p++;
5127          count = p[0] & 127;
5128          if ( p[0] & 128 )
5129            p += 2;
5130    
5131          p++;
5132    
5133          for ( ; count > 0; count--, p += 2 )
5134          {
5135            int                   offset = ((int)p[0] << 8) | p[1];
5136            const unsigned char*  q      = ft_adobe_glyph_list + offset;
5137    
5138            if ( c == (q[0] & 127) )
5139            {
5140              p = q;
5141              goto NextIter;
5142            }
5143          }
5144          goto NotFound;
5145    
5146        NextIter:
5147          ;
5148        }
5149    
5150      NotFound:
5151        return 0;
5152      }
5153      
5154    """ )
5155    
5156      if 0:  # generate unit test, or don't
5157        #
5158        # now write the unit test to check that everything works OK
5159        #
5160        write( "#ifdef TEST\n\n" )
5161    
5162        write( "static const char* const the_names[] = {\n" )
5163        for name in agl_glyphs:
5164          write( '  "'+name+'",\n' )
5165        write( "  0\n};\n" )
5166    
5167        write( "static const unsigned long the_values[] = {\n" )
5168        for val in agl_values:
5169          write( '  0x'+val+',\n' )
5170        write( "  0\n};\n" )
5171    
5172        write( """
5173    #include <stdlib.h>
5174    #include <stdio.h>
5175    
5176      int  main( void )
5177      {
5178        int                   result = 0;
5179        const char* const*    names  = the_names;
5180        const unsigned long*  values = the_values;
5181        
5182        for ( ; *names; names++, values++ )
5183        {
5184          const char*    name      = *names;
5185          unsigned long  reference = *values;
5186          unsigned long  value;
5187    
5188          value     = ft_get_adobe_glyph_index( name, name + strlen(name) );
5189          if ( value != reference )
5190          {
5191            result = 1;
5192            fprintf( stderr, "name '%s' => %04x instead of %04x\\n",
5193                             name, value, reference );
5194          }
5195        }
5196        
5197        return result;
5198      }
5199    """ )
5200        write( "#endif /* TEST */\n" )
5201      
5202      write("/* END */\n")
5203    
5204    
5205  # Now run the main routine  # Now run the main routine

Legend:
Removed from v.1.5  
changed lines
  Added in v.1.6

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26