Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  psmodule.c                                                             */
  4. /*                                                                         */
  5. /*    PSNames module implementation (body).                                */
  6. /*                                                                         */
  7. /*  Copyright 1996-2003, 2005-2008, 2012, 2013 by                          */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19. #include <ft2build.h>
  20. #include FT_INTERNAL_DEBUG_H
  21. #include FT_INTERNAL_OBJECTS_H
  22. #include FT_SERVICE_POSTSCRIPT_CMAPS_H
  23.  
  24. #include "psmodule.h"
  25. #include "pstables.h"
  26.  
  27. #include "psnamerr.h"
  28. #include "pspic.h"
  29.  
  30.  
  31. #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
  32.  
  33.  
  34. #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
  35.  
  36.  
  37. #define VARIANT_BIT         0x80000000UL
  38. #define BASE_GLYPH( code )  ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
  39.  
  40.  
  41.   /* Return the Unicode value corresponding to a given glyph.  Note that */
  42.   /* we do deal with glyph variants by detecting a non-initial dot in    */
  43.   /* the name, as in `A.swash' or `e.final'; in this case, the           */
  44.   /* VARIANT_BIT is set in the return value.                             */
  45.   /*                                                                     */
  46.   static FT_UInt32
  47.   ps_unicode_value( const char*  glyph_name )
  48.   {
  49.     /* If the name begins with `uni', then the glyph name may be a */
  50.     /* hard-coded unicode character code.                          */
  51.     if ( glyph_name[0] == 'u' &&
  52.          glyph_name[1] == 'n' &&
  53.          glyph_name[2] == 'i' )
  54.     {
  55.       /* determine whether the next four characters following are */
  56.       /* hexadecimal.                                             */
  57.  
  58.       /* XXX: Add code to deal with ligatures, i.e. glyph names like */
  59.       /*      `uniXXXXYYYYZZZZ'...                                   */
  60.  
  61.       FT_Int       count;
  62.       FT_UInt32    value = 0;
  63.       const char*  p     = glyph_name + 3;
  64.  
  65.  
  66.       for ( count = 4; count > 0; count--, p++ )
  67.       {
  68.         char          c = *p;
  69.         unsigned int  d;
  70.  
  71.  
  72.         d = (unsigned char)c - '0';
  73.         if ( d >= 10 )
  74.         {
  75.           d = (unsigned char)c - 'A';
  76.           if ( d >= 6 )
  77.             d = 16;
  78.           else
  79.             d += 10;
  80.         }
  81.  
  82.         /* Exit if a non-uppercase hexadecimal character was found   */
  83.         /* -- this also catches character codes below `0' since such */
  84.         /* negative numbers cast to `unsigned int' are far too big.  */
  85.         if ( d >= 16 )
  86.           break;
  87.  
  88.         value = ( value << 4 ) + d;
  89.       }
  90.  
  91.       /* there must be exactly four hex digits */
  92.       if ( count == 0 )
  93.       {
  94.         if ( *p == '\0' )
  95.           return value;
  96.         if ( *p == '.' )
  97.           return (FT_UInt32)( value | VARIANT_BIT );
  98.       }
  99.     }
  100.  
  101.     /* If the name begins with `u', followed by four to six uppercase */
  102.     /* hexadecimal digits, it is a hard-coded unicode character code. */
  103.     if ( glyph_name[0] == 'u' )
  104.     {
  105.       FT_Int       count;
  106.       FT_UInt32    value = 0;
  107.       const char*  p     = glyph_name + 1;
  108.  
  109.  
  110.       for ( count = 6; count > 0; count--, p++ )
  111.       {
  112.         char          c = *p;
  113.         unsigned int  d;
  114.  
  115.  
  116.         d = (unsigned char)c - '0';
  117.         if ( d >= 10 )
  118.         {
  119.           d = (unsigned char)c - 'A';
  120.           if ( d >= 6 )
  121.             d = 16;
  122.           else
  123.             d += 10;
  124.         }
  125.  
  126.         if ( d >= 16 )
  127.           break;
  128.  
  129.         value = ( value << 4 ) + d;
  130.       }
  131.  
  132.       if ( count <= 2 )
  133.       {
  134.         if ( *p == '\0' )
  135.           return value;
  136.         if ( *p == '.' )
  137.           return (FT_UInt32)( value | VARIANT_BIT );
  138.       }
  139.     }
  140.  
  141.     /* Look for a non-initial dot in the glyph name in order to */
  142.     /* find variants like `A.swash', `e.final', etc.            */
  143.     {
  144.       const char*  p   = glyph_name;
  145.       const char*  dot = NULL;
  146.  
  147.  
  148.       for ( ; *p; p++ )
  149.       {
  150.         if ( *p == '.' && p > glyph_name )
  151.         {
  152.           dot = p;
  153.           break;
  154.         }
  155.       }
  156.  
  157.       /* now look up the glyph in the Adobe Glyph List */
  158.       if ( !dot )
  159.         return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
  160.       else
  161.         return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) |
  162.                             VARIANT_BIT );
  163.     }
  164.   }
  165.  
  166.  
  167.   /* ft_qsort callback to sort the unicode map */
  168.   FT_CALLBACK_DEF( int )
  169.   compare_uni_maps( const void*  a,
  170.                     const void*  b )
  171.   {
  172.     PS_UniMap*  map1 = (PS_UniMap*)a;
  173.     PS_UniMap*  map2 = (PS_UniMap*)b;
  174.     FT_UInt32   unicode1 = BASE_GLYPH( map1->unicode );
  175.     FT_UInt32   unicode2 = BASE_GLYPH( map2->unicode );
  176.  
  177.  
  178.     /* sort base glyphs before glyph variants */
  179.     if ( unicode1 == unicode2 )
  180.     {
  181.       if ( map1->unicode > map2->unicode )
  182.         return 1;
  183.       else if ( map1->unicode < map2->unicode )
  184.         return -1;
  185.       else
  186.         return 0;
  187.     }
  188.     else
  189.     {
  190.       if ( unicode1 > unicode2 )
  191.         return 1;
  192.       else if ( unicode1 < unicode2 )
  193.         return -1;
  194.       else
  195.         return 0;
  196.     }
  197.   }
  198.  
  199.  
  200.   /* support for extra glyphs not handled (well) in AGL; */
  201.   /* we add extra mappings for them if necessary         */
  202.  
  203. #define EXTRA_GLYPH_LIST_SIZE  10
  204.  
  205.   static const FT_UInt32  ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
  206.   {
  207.     /* WGL 4 */
  208.     0x0394,
  209.     0x03A9,
  210.     0x2215,
  211.     0x00AD,
  212.     0x02C9,
  213.     0x03BC,
  214.     0x2219,
  215.     0x00A0,
  216.     /* Romanian */
  217.     0x021A,
  218.     0x021B
  219.   };
  220.  
  221.   static const char  ft_extra_glyph_names[] =
  222.   {
  223.     'D','e','l','t','a',0,
  224.     'O','m','e','g','a',0,
  225.     'f','r','a','c','t','i','o','n',0,
  226.     'h','y','p','h','e','n',0,
  227.     'm','a','c','r','o','n',0,
  228.     'm','u',0,
  229.     'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
  230.     's','p','a','c','e',0,
  231.     'T','c','o','m','m','a','a','c','c','e','n','t',0,
  232.     't','c','o','m','m','a','a','c','c','e','n','t',0
  233.   };
  234.  
  235.   static const FT_Int
  236.   ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
  237.   {
  238.      0,
  239.      6,
  240.     12,
  241.     21,
  242.     28,
  243.     35,
  244.     38,
  245.     53,
  246.     59,
  247.     72
  248.   };
  249.  
  250.  
  251.   static void
  252.   ps_check_extra_glyph_name( const char*  gname,
  253.                              FT_UInt      glyph,
  254.                              FT_UInt*     extra_glyphs,
  255.                              FT_UInt     *states )
  256.   {
  257.     FT_UInt  n;
  258.  
  259.  
  260.     for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
  261.     {
  262.       if ( ft_strcmp( ft_extra_glyph_names +
  263.                         ft_extra_glyph_name_offsets[n], gname ) == 0 )
  264.       {
  265.         if ( states[n] == 0 )
  266.         {
  267.           /* mark this extra glyph as a candidate for the cmap */
  268.           states[n]     = 1;
  269.           extra_glyphs[n] = glyph;
  270.         }
  271.  
  272.         return;
  273.       }
  274.     }
  275.   }
  276.  
  277.  
  278.   static void
  279.   ps_check_extra_glyph_unicode( FT_UInt32  uni_char,
  280.                                 FT_UInt   *states )
  281.   {
  282.     FT_UInt  n;
  283.  
  284.  
  285.     for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
  286.     {
  287.       if ( uni_char == ft_extra_glyph_unicodes[n] )
  288.       {
  289.         /* disable this extra glyph from being added to the cmap */
  290.         states[n] = 2;
  291.  
  292.         return;
  293.       }
  294.     }
  295.   }
  296.  
  297.  
  298.   /* Build a table that maps Unicode values to glyph indices. */
  299.   static FT_Error
  300.   ps_unicodes_init( FT_Memory             memory,
  301.                     PS_Unicodes           table,
  302.                     FT_UInt               num_glyphs,
  303.                     PS_GetGlyphNameFunc   get_glyph_name,
  304.                     PS_FreeGlyphNameFunc  free_glyph_name,
  305.                     FT_Pointer            glyph_data )
  306.   {
  307.     FT_Error  error;
  308.  
  309.     FT_UInt  extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  310.     FT_UInt  extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
  311.  
  312.  
  313.     /* we first allocate the table */
  314.     table->num_maps = 0;
  315.     table->maps     = 0;
  316.  
  317.     if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
  318.     {
  319.       FT_UInt     n;
  320.       FT_UInt     count;
  321.       PS_UniMap*  map;
  322.       FT_UInt32   uni_char;
  323.  
  324.  
  325.       map = table->maps;
  326.  
  327.       for ( n = 0; n < num_glyphs; n++ )
  328.       {
  329.         const char*  gname = get_glyph_name( glyph_data, n );
  330.  
  331.  
  332.         if ( gname )
  333.         {
  334.           ps_check_extra_glyph_name( gname, n,
  335.                                      extra_glyphs, extra_glyph_list_states );
  336.           uni_char = ps_unicode_value( gname );
  337.  
  338.           if ( BASE_GLYPH( uni_char ) != 0 )
  339.           {
  340.             ps_check_extra_glyph_unicode( uni_char,
  341.                                           extra_glyph_list_states );
  342.             map->unicode     = uni_char;
  343.             map->glyph_index = n;
  344.             map++;
  345.           }
  346.  
  347.           if ( free_glyph_name )
  348.             free_glyph_name( glyph_data, gname );
  349.         }
  350.       }
  351.  
  352.       for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
  353.       {
  354.         if ( extra_glyph_list_states[n] == 1 )
  355.         {
  356.           /* This glyph name has an additional representation. */
  357.           /* Add it to the cmap.                               */
  358.  
  359.           map->unicode     = ft_extra_glyph_unicodes[n];
  360.           map->glyph_index = extra_glyphs[n];
  361.           map++;
  362.         }
  363.       }
  364.  
  365.       /* now compress the table a bit */
  366.       count = (FT_UInt)( map - table->maps );
  367.  
  368.       if ( count == 0 )
  369.       {
  370.         /* No unicode chars here! */
  371.         FT_FREE( table->maps );
  372.         if ( !error )
  373.           error = FT_THROW( No_Unicode_Glyph_Name );
  374.       }
  375.       else
  376.       {
  377.         /* Reallocate if the number of used entries is much smaller. */
  378.         if ( count < num_glyphs / 2 )
  379.         {
  380.           (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
  381.           error = FT_Err_Ok;
  382.         }
  383.  
  384.         /* Sort the table in increasing order of unicode values, */
  385.         /* taking care of glyph variants.                        */
  386.         ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
  387.                   compare_uni_maps );
  388.       }
  389.  
  390.       table->num_maps = count;
  391.     }
  392.  
  393.     return error;
  394.   }
  395.  
  396.  
  397.   static FT_UInt
  398.   ps_unicodes_char_index( PS_Unicodes  table,
  399.                           FT_UInt32    unicode )
  400.   {
  401.     PS_UniMap  *min, *max, *mid, *result = NULL;
  402.  
  403.  
  404.     /* Perform a binary search on the table. */
  405.  
  406.     min = table->maps;
  407.     max = min + table->num_maps - 1;
  408.  
  409.     while ( min <= max )
  410.     {
  411.       FT_UInt32  base_glyph;
  412.  
  413.  
  414.       mid = min + ( ( max - min ) >> 1 );
  415.  
  416.       if ( mid->unicode == unicode )
  417.       {
  418.         result = mid;
  419.         break;
  420.       }
  421.  
  422.       base_glyph = BASE_GLYPH( mid->unicode );
  423.  
  424.       if ( base_glyph == unicode )
  425.         result = mid; /* remember match but continue search for base glyph */
  426.  
  427.       if ( min == max )
  428.         break;
  429.  
  430.       if ( base_glyph < unicode )
  431.         min = mid + 1;
  432.       else
  433.         max = mid - 1;
  434.     }
  435.  
  436.     if ( result )
  437.       return result->glyph_index;
  438.     else
  439.       return 0;
  440.   }
  441.  
  442.  
  443.   static FT_UInt32
  444.   ps_unicodes_char_next( PS_Unicodes  table,
  445.                          FT_UInt32   *unicode )
  446.   {
  447.     FT_UInt    result    = 0;
  448.     FT_UInt32  char_code = *unicode + 1;
  449.  
  450.  
  451.     {
  452.       FT_UInt     min = 0;
  453.       FT_UInt     max = table->num_maps;
  454.       FT_UInt     mid;
  455.       PS_UniMap*  map;
  456.       FT_UInt32   base_glyph;
  457.  
  458.  
  459.       while ( min < max )
  460.       {
  461.         mid = min + ( ( max - min ) >> 1 );
  462.         map = table->maps + mid;
  463.  
  464.         if ( map->unicode == char_code )
  465.         {
  466.           result = map->glyph_index;
  467.           goto Exit;
  468.         }
  469.  
  470.         base_glyph = BASE_GLYPH( map->unicode );
  471.  
  472.         if ( base_glyph == char_code )
  473.           result = map->glyph_index;
  474.  
  475.         if ( base_glyph < char_code )
  476.           min = mid + 1;
  477.         else
  478.           max = mid;
  479.       }
  480.  
  481.       if ( result )
  482.         goto Exit;               /* we have a variant glyph */
  483.  
  484.       /* we didn't find it; check whether we have a map just above it */
  485.       char_code = 0;
  486.  
  487.       if ( min < table->num_maps )
  488.       {
  489.         map       = table->maps + min;
  490.         result    = map->glyph_index;
  491.         char_code = BASE_GLYPH( map->unicode );
  492.       }
  493.     }
  494.  
  495.   Exit:
  496.     *unicode = char_code;
  497.     return result;
  498.   }
  499.  
  500.  
  501. #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
  502.  
  503.  
  504.   static const char*
  505.   ps_get_macintosh_name( FT_UInt  name_index )
  506.   {
  507.     if ( name_index >= FT_NUM_MAC_NAMES )
  508.       name_index = 0;
  509.  
  510.     return ft_standard_glyph_names + ft_mac_names[name_index];
  511.   }
  512.  
  513.  
  514.   static const char*
  515.   ps_get_standard_strings( FT_UInt  sid )
  516.   {
  517.     if ( sid >= FT_NUM_SID_NAMES )
  518.       return 0;
  519.  
  520.     return ft_standard_glyph_names + ft_sid_names[sid];
  521.   }
  522.  
  523.  
  524. #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
  525.  
  526.   FT_DEFINE_SERVICE_PSCMAPSREC(
  527.     pscmaps_interface,
  528.     (PS_Unicode_ValueFunc)     ps_unicode_value,
  529.     (PS_Unicodes_InitFunc)     ps_unicodes_init,
  530.     (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
  531.     (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,
  532.  
  533.     (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
  534.     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
  535.  
  536.     t1_standard_encoding,
  537.     t1_expert_encoding )
  538.  
  539. #else
  540.  
  541.   FT_DEFINE_SERVICE_PSCMAPSREC(
  542.     pscmaps_interface,
  543.     NULL,
  544.     NULL,
  545.     NULL,
  546.     NULL,
  547.  
  548.     (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
  549.     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
  550.  
  551.     t1_standard_encoding,
  552.     t1_expert_encoding )
  553.  
  554. #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
  555.  
  556.  
  557.   FT_DEFINE_SERVICEDESCREC1(
  558.     pscmaps_services,
  559.     FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET )
  560.  
  561.  
  562.   static FT_Pointer
  563.   psnames_get_service( FT_Module    module,
  564.                        const char*  service_id )
  565.   {
  566.     /* PSCMAPS_SERVICES_GET derefers `library' in PIC mode */
  567. #ifdef FT_CONFIG_OPTION_PIC
  568.     FT_Library  library;
  569.  
  570.  
  571.     if ( !module )
  572.       return NULL;
  573.     library = module->library;
  574.     if ( !library )
  575.       return NULL;
  576. #else
  577.     FT_UNUSED( module );
  578. #endif
  579.  
  580.     return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id );
  581.   }
  582.  
  583. #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
  584.  
  585.  
  586. #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
  587. #define PUT_PS_NAMES_SERVICE( a )  NULL
  588. #else
  589. #define PUT_PS_NAMES_SERVICE( a )  a
  590. #endif
  591.  
  592.   FT_DEFINE_MODULE(
  593.     psnames_module_class,
  594.  
  595.     0,  /* this is not a font driver, nor a renderer */
  596.     sizeof ( FT_ModuleRec ),
  597.  
  598.     "psnames",  /* driver name                         */
  599.     0x10000L,   /* driver version                      */
  600.     0x20000L,   /* driver requires FreeType 2 or above */
  601.  
  602.     PUT_PS_NAMES_SERVICE(
  603.       (void*)&PSCMAPS_INTERFACE_GET ),   /* module specific interface */
  604.     (FT_Module_Constructor)NULL,
  605.     (FT_Module_Destructor) NULL,
  606.     (FT_Module_Requester)  PUT_PS_NAMES_SERVICE( psnames_get_service ) )
  607.  
  608.  
  609. /* END */
  610.