Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ttpost.c                                                               */
  4. /*                                                                         */
  5. /*    Postcript name table processing for TrueType and OpenType fonts      */
  6. /*    (body).                                                              */
  7. /*                                                                         */
  8. /*  Copyright 1996-2003, 2006-2010, 2013 by                                */
  9. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  10. /*                                                                         */
  11. /*  This file is part of the FreeType project, and may only be used,       */
  12. /*  modified, and distributed under the terms of the FreeType project      */
  13. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  14. /*  this file you indicate that you have read the license and              */
  15. /*  understand and accept it fully.                                        */
  16. /*                                                                         */
  17. /***************************************************************************/
  18.  
  19.   /*************************************************************************/
  20.   /*                                                                       */
  21.   /* The post table is not completely loaded by the core engine.  This     */
  22.   /* file loads the missing PS glyph names and implements an API to access */
  23.   /* them.                                                                 */
  24.   /*                                                                       */
  25.   /*************************************************************************/
  26.  
  27.  
  28. #include <ft2build.h>
  29. #include FT_INTERNAL_DEBUG_H
  30. #include FT_INTERNAL_STREAM_H
  31. #include FT_TRUETYPE_TAGS_H
  32. #include "ttpost.h"
  33.  
  34. #include "sferrors.h"
  35.  
  36.  
  37.   /*************************************************************************/
  38.   /*                                                                       */
  39.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  40.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  41.   /* messages during execution.                                            */
  42.   /*                                                                       */
  43. #undef  FT_COMPONENT
  44. #define FT_COMPONENT  trace_ttpost
  45.  
  46.  
  47.   /* If this configuration macro is defined, we rely on the `PSNames' */
  48.   /* module to grab the glyph names.                                  */
  49.  
  50. #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
  51.  
  52.  
  53. #include FT_SERVICE_POSTSCRIPT_CMAPS_H
  54.  
  55. #define MAC_NAME( x )  ( (FT_String*)psnames->macintosh_name( x ) )
  56.  
  57.  
  58. #else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
  59.  
  60.  
  61.    /* Otherwise, we ignore the `PSNames' module, and provide our own  */
  62.    /* table of Mac names.  Thus, it is possible to build a version of */
  63.    /* FreeType without the Type 1 driver & PSNames module.            */
  64.  
  65. #define MAC_NAME( x )  ( (FT_String*)tt_post_default_names[x] )
  66.  
  67.   /* the 258 default Mac PS glyph names */
  68.  
  69.   static const FT_String* const  tt_post_default_names[258] =
  70.   {
  71.     /*   0 */
  72.     ".notdef", ".null", "CR", "space", "exclam",
  73.     "quotedbl", "numbersign", "dollar", "percent", "ampersand",
  74.     /*  10 */
  75.     "quotesingle", "parenleft", "parenright", "asterisk", "plus",
  76.     "comma", "hyphen", "period", "slash", "zero",
  77.     /*  20 */
  78.     "one", "two", "three", "four", "five",
  79.     "six", "seven", "eight", "nine", "colon",
  80.     /*  30 */
  81.     "semicolon", "less", "equal", "greater", "question",
  82.     "at", "A", "B", "C", "D",
  83.     /*  40 */
  84.     "E", "F", "G", "H", "I",
  85.     "J", "K", "L", "M", "N",
  86.     /*  50 */
  87.     "O", "P", "Q", "R", "S",
  88.     "T", "U", "V", "W", "X",
  89.     /*  60 */
  90.     "Y", "Z", "bracketleft", "backslash", "bracketright",
  91.     "asciicircum", "underscore", "grave", "a", "b",
  92.     /*  70 */
  93.     "c", "d", "e", "f", "g",
  94.     "h", "i", "j", "k", "l",
  95.     /*  80 */
  96.     "m", "n", "o", "p", "q",
  97.     "r", "s", "t", "u", "v",
  98.     /*  90 */
  99.     "w", "x", "y", "z", "braceleft",
  100.     "bar", "braceright", "asciitilde", "Adieresis", "Aring",
  101.     /* 100 */
  102.     "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
  103.     "aacute", "agrave", "acircumflex", "adieresis", "atilde",
  104.     /* 110 */
  105.     "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
  106.     "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
  107.     /* 120 */
  108.     "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
  109.     "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
  110.     /* 130 */
  111.     "dagger", "degree", "cent", "sterling", "section",
  112.     "bullet", "paragraph", "germandbls", "registered", "copyright",
  113.     /* 140 */
  114.     "trademark", "acute", "dieresis", "notequal", "AE",
  115.     "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
  116.     /* 150 */
  117.     "yen", "mu", "partialdiff", "summation", "product",
  118.     "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
  119.     /* 160 */
  120.     "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
  121.     "radical", "florin", "approxequal", "Delta", "guillemotleft",
  122.     /* 170 */
  123.     "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
  124.     "Otilde", "OE", "oe", "endash", "emdash",
  125.     /* 180 */
  126.     "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
  127.     "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
  128.     /* 190 */
  129.     "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
  130.     "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
  131.     /* 200 */
  132.     "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
  133.     "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
  134.     /* 210 */
  135.     "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
  136.     "dotlessi", "circumflex", "tilde", "macron", "breve",
  137.     /* 220 */
  138.     "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
  139.     "caron", "Lslash", "lslash", "Scaron", "scaron",
  140.     /* 230 */
  141.     "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
  142.     "Yacute", "yacute", "Thorn", "thorn", "minus",
  143.     /* 240 */
  144.     "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
  145.     "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
  146.     /* 250 */
  147.     "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
  148.     "Ccaron", "ccaron", "dmacron",
  149.   };
  150.  
  151.  
  152. #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
  153.  
  154.  
  155.   static FT_Error
  156.   load_format_20( TT_Face    face,
  157.                   FT_Stream  stream,
  158.                   FT_Long    post_limit )
  159.   {
  160.     FT_Memory   memory = stream->memory;
  161.     FT_Error    error;
  162.  
  163.     FT_Int      num_glyphs;
  164.     FT_UShort   num_names;
  165.  
  166.     FT_UShort*  glyph_indices = 0;
  167.     FT_Char**   name_strings  = 0;
  168.  
  169.  
  170.     if ( FT_READ_USHORT( num_glyphs ) )
  171.       goto Exit;
  172.  
  173.     /* UNDOCUMENTED!  The number of glyphs in this table can be smaller */
  174.     /* than the value in the maxp table (cf. cyberbit.ttf).             */
  175.  
  176.     /* There already exist fonts which have more than 32768 glyph names */
  177.     /* in this table, so the test for this threshold has been dropped.  */
  178.  
  179.     if ( num_glyphs > face->max_profile.numGlyphs )
  180.     {
  181.       error = FT_THROW( Invalid_File_Format );
  182.       goto Exit;
  183.     }
  184.  
  185.     /* load the indices */
  186.     {
  187.       FT_Int  n;
  188.  
  189.  
  190.       if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) ||
  191.            FT_FRAME_ENTER( num_glyphs * 2L )          )
  192.         goto Fail;
  193.  
  194.       for ( n = 0; n < num_glyphs; n++ )
  195.         glyph_indices[n] = FT_GET_USHORT();
  196.  
  197.       FT_FRAME_EXIT();
  198.     }
  199.  
  200.     /* compute number of names stored in table */
  201.     {
  202.       FT_Int  n;
  203.  
  204.  
  205.       num_names = 0;
  206.  
  207.       for ( n = 0; n < num_glyphs; n++ )
  208.       {
  209.         FT_Int  idx;
  210.  
  211.  
  212.         idx = glyph_indices[n];
  213.         if ( idx >= 258 )
  214.         {
  215.           idx -= 257;
  216.           if ( idx > num_names )
  217.             num_names = (FT_UShort)idx;
  218.         }
  219.       }
  220.     }
  221.  
  222.     /* now load the name strings */
  223.     {
  224.       FT_UShort  n;
  225.  
  226.  
  227.       if ( FT_NEW_ARRAY( name_strings, num_names ) )
  228.         goto Fail;
  229.  
  230.       for ( n = 0; n < num_names; n++ )
  231.       {
  232.         FT_UInt  len;
  233.  
  234.  
  235.         if ( FT_STREAM_POS() >= post_limit )
  236.           break;
  237.         else
  238.         {
  239.           FT_TRACE6(( "load_format_20: %d byte left in post table\n",
  240.                       post_limit - FT_STREAM_POS() ));
  241.  
  242.           if ( FT_READ_BYTE( len ) )
  243.             goto Fail1;
  244.         }
  245.  
  246.         if ( (FT_Int)len > post_limit                   ||
  247.              FT_STREAM_POS() > post_limit - (FT_Int)len )
  248.         {
  249.           FT_ERROR(( "load_format_20:"
  250.                      " exceeding string length (%d),"
  251.                      " truncating at end of post table (%d byte left)\n",
  252.                      len, post_limit - FT_STREAM_POS() ));
  253.           len = FT_MAX( 0, post_limit - FT_STREAM_POS() );
  254.         }
  255.  
  256.         if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
  257.              FT_STREAM_READ( name_strings[n], len   ) )
  258.           goto Fail1;
  259.  
  260.         name_strings[n][len] = '\0';
  261.       }
  262.  
  263.       if ( n < num_names )
  264.       {
  265.         FT_ERROR(( "load_format_20:"
  266.                    " all entries in post table are already parsed,"
  267.                    " using NULL names for gid %d - %d\n",
  268.                     n, num_names - 1 ));
  269.         for ( ; n < num_names; n++ )
  270.           if ( FT_NEW_ARRAY( name_strings[n], 1 ) )
  271.             goto Fail1;
  272.           else
  273.             name_strings[n][0] = '\0';
  274.       }
  275.     }
  276.  
  277.     /* all right, set table fields and exit successfully */
  278.     {
  279.       TT_Post_20  table = &face->postscript_names.names.format_20;
  280.  
  281.  
  282.       table->num_glyphs    = (FT_UShort)num_glyphs;
  283.       table->num_names     = (FT_UShort)num_names;
  284.       table->glyph_indices = glyph_indices;
  285.       table->glyph_names   = name_strings;
  286.     }
  287.     return FT_Err_Ok;
  288.  
  289.   Fail1:
  290.     {
  291.       FT_UShort  n;
  292.  
  293.  
  294.       for ( n = 0; n < num_names; n++ )
  295.         FT_FREE( name_strings[n] );
  296.     }
  297.  
  298.   Fail:
  299.     FT_FREE( name_strings );
  300.     FT_FREE( glyph_indices );
  301.  
  302.   Exit:
  303.     return error;
  304.   }
  305.  
  306.  
  307.   static FT_Error
  308.   load_format_25( TT_Face    face,
  309.                   FT_Stream  stream,
  310.                   FT_Long    post_limit )
  311.   {
  312.     FT_Memory  memory = stream->memory;
  313.     FT_Error   error;
  314.  
  315.     FT_Int     num_glyphs;
  316.     FT_Char*   offset_table = 0;
  317.  
  318.     FT_UNUSED( post_limit );
  319.  
  320.  
  321.     /* UNDOCUMENTED!  This value appears only in the Apple TT specs. */
  322.     if ( FT_READ_USHORT( num_glyphs ) )
  323.       goto Exit;
  324.  
  325.     /* check the number of glyphs */
  326.     if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 )
  327.     {
  328.       error = FT_THROW( Invalid_File_Format );
  329.       goto Exit;
  330.     }
  331.  
  332.     if ( FT_NEW_ARRAY( offset_table, num_glyphs )   ||
  333.          FT_STREAM_READ( offset_table, num_glyphs ) )
  334.       goto Fail;
  335.  
  336.     /* now check the offset table */
  337.     {
  338.       FT_Int  n;
  339.  
  340.  
  341.       for ( n = 0; n < num_glyphs; n++ )
  342.       {
  343.         FT_Long  idx = (FT_Long)n + offset_table[n];
  344.  
  345.  
  346.         if ( idx < 0 || idx > num_glyphs )
  347.         {
  348.           error = FT_THROW( Invalid_File_Format );
  349.           goto Fail;
  350.         }
  351.       }
  352.     }
  353.  
  354.     /* OK, set table fields and exit successfully */
  355.     {
  356.       TT_Post_25  table = &face->postscript_names.names.format_25;
  357.  
  358.  
  359.       table->num_glyphs = (FT_UShort)num_glyphs;
  360.       table->offsets    = offset_table;
  361.     }
  362.  
  363.     return FT_Err_Ok;
  364.  
  365.   Fail:
  366.     FT_FREE( offset_table );
  367.  
  368.   Exit:
  369.     return error;
  370.   }
  371.  
  372.  
  373.   static FT_Error
  374.   load_post_names( TT_Face  face )
  375.   {
  376.     FT_Stream  stream;
  377.     FT_Error   error;
  378.     FT_Fixed   format;
  379.     FT_ULong   post_len;
  380.     FT_Long    post_limit;
  381.  
  382.  
  383.     /* get a stream for the face's resource */
  384.     stream = face->root.stream;
  385.  
  386.     /* seek to the beginning of the PS names table */
  387.     error = face->goto_table( face, TTAG_post, stream, &post_len );
  388.     if ( error )
  389.       goto Exit;
  390.  
  391.     post_limit = FT_STREAM_POS() + post_len;
  392.  
  393.     format = face->postscript.FormatType;
  394.  
  395.     /* go to beginning of subtable */
  396.     if ( FT_STREAM_SKIP( 32 ) )
  397.       goto Exit;
  398.  
  399.     /* now read postscript table */
  400.     if ( format == 0x00020000L )
  401.       error = load_format_20( face, stream, post_limit );
  402.     else if ( format == 0x00028000L )
  403.       error = load_format_25( face, stream, post_limit );
  404.     else
  405.       error = FT_THROW( Invalid_File_Format );
  406.  
  407.     face->postscript_names.loaded = 1;
  408.  
  409.   Exit:
  410.     return error;
  411.   }
  412.  
  413.  
  414.   FT_LOCAL_DEF( void )
  415.   tt_face_free_ps_names( TT_Face  face )
  416.   {
  417.     FT_Memory      memory = face->root.memory;
  418.     TT_Post_Names  names  = &face->postscript_names;
  419.     FT_Fixed       format;
  420.  
  421.  
  422.     if ( names->loaded )
  423.     {
  424.       format = face->postscript.FormatType;
  425.  
  426.       if ( format == 0x00020000L )
  427.       {
  428.         TT_Post_20  table = &names->names.format_20;
  429.         FT_UShort   n;
  430.  
  431.  
  432.         FT_FREE( table->glyph_indices );
  433.         table->num_glyphs = 0;
  434.  
  435.         for ( n = 0; n < table->num_names; n++ )
  436.           FT_FREE( table->glyph_names[n] );
  437.  
  438.         FT_FREE( table->glyph_names );
  439.         table->num_names = 0;
  440.       }
  441.       else if ( format == 0x00028000L )
  442.       {
  443.         TT_Post_25  table = &names->names.format_25;
  444.  
  445.  
  446.         FT_FREE( table->offsets );
  447.         table->num_glyphs = 0;
  448.       }
  449.     }
  450.     names->loaded = 0;
  451.   }
  452.  
  453.  
  454.   /*************************************************************************/
  455.   /*                                                                       */
  456.   /* <Function>                                                            */
  457.   /*    tt_face_get_ps_name                                                */
  458.   /*                                                                       */
  459.   /* <Description>                                                         */
  460.   /*    Get the PostScript glyph name of a glyph.                          */
  461.   /*                                                                       */
  462.   /* <Input>                                                               */
  463.   /*    face   :: A handle to the parent face.                             */
  464.   /*                                                                       */
  465.   /*    idx    :: The glyph index.                                         */
  466.   /*                                                                       */
  467.   /* <InOut>                                                               */
  468.   /*    PSname :: The address of a string pointer.  Will be NULL in case   */
  469.   /*              of error, otherwise it is a pointer to the glyph name.   */
  470.   /*                                                                       */
  471.   /*              You must not modify the returned string!                 */
  472.   /*                                                                       */
  473.   /* <Output>                                                              */
  474.   /*    FreeType error code.  0 means success.                             */
  475.   /*                                                                       */
  476.   FT_LOCAL_DEF( FT_Error )
  477.   tt_face_get_ps_name( TT_Face      face,
  478.                        FT_UInt      idx,
  479.                        FT_String**  PSname )
  480.   {
  481.     FT_Error       error;
  482.     TT_Post_Names  names;
  483.     FT_Fixed       format;
  484.  
  485. #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
  486.     FT_Service_PsCMaps  psnames;
  487. #endif
  488.  
  489.  
  490.     if ( !face )
  491.       return FT_THROW( Invalid_Face_Handle );
  492.  
  493.     if ( idx >= (FT_UInt)face->max_profile.numGlyphs )
  494.       return FT_THROW( Invalid_Glyph_Index );
  495.  
  496. #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
  497.     psnames = (FT_Service_PsCMaps)face->psnames;
  498.     if ( !psnames )
  499.       return FT_THROW( Unimplemented_Feature );
  500. #endif
  501.  
  502.     names = &face->postscript_names;
  503.  
  504.     /* `.notdef' by default */
  505.     *PSname = MAC_NAME( 0 );
  506.  
  507.     format = face->postscript.FormatType;
  508.  
  509.     if ( format == 0x00010000L )
  510.     {
  511.       if ( idx < 258 )                    /* paranoid checking */
  512.         *PSname = MAC_NAME( idx );
  513.     }
  514.     else if ( format == 0x00020000L )
  515.     {
  516.       TT_Post_20  table = &names->names.format_20;
  517.  
  518.  
  519.       if ( !names->loaded )
  520.       {
  521.         error = load_post_names( face );
  522.         if ( error )
  523.           goto End;
  524.       }
  525.  
  526.       if ( idx < (FT_UInt)table->num_glyphs )
  527.       {
  528.         FT_UShort  name_index = table->glyph_indices[idx];
  529.  
  530.  
  531.         if ( name_index < 258 )
  532.           *PSname = MAC_NAME( name_index );
  533.         else
  534.           *PSname = (FT_String*)table->glyph_names[name_index - 258];
  535.       }
  536.     }
  537.     else if ( format == 0x00028000L )
  538.     {
  539.       TT_Post_25  table = &names->names.format_25;
  540.  
  541.  
  542.       if ( !names->loaded )
  543.       {
  544.         error = load_post_names( face );
  545.         if ( error )
  546.           goto End;
  547.       }
  548.  
  549.       if ( idx < (FT_UInt)table->num_glyphs )    /* paranoid checking */
  550.       {
  551.         idx    += table->offsets[idx];
  552.         *PSname = MAC_NAME( idx );
  553.       }
  554.     }
  555.  
  556.     /* nothing to do for format == 0x00030000L */
  557.  
  558.   End:
  559.     return FT_Err_Ok;
  560.   }
  561.  
  562.  
  563. /* END */
  564.