Subversion Repositories Kolibri OS

Rev

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

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftccmap.c                                                              */
  4. /*                                                                         */
  5. /*    FreeType CharMap cache (body)                                        */
  6. /*                                                                         */
  7. /*  Copyright 2000-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_FREETYPE_H
  21. #include FT_CACHE_H
  22. #include "ftcmanag.h"
  23. #include FT_INTERNAL_MEMORY_H
  24. #include FT_INTERNAL_OBJECTS_H
  25. #include FT_INTERNAL_DEBUG_H
  26.  
  27. #include "ftccback.h"
  28. #include "ftcerror.h"
  29.  
  30. #undef  FT_COMPONENT
  31. #define FT_COMPONENT  trace_cache
  32.  
  33.  
  34.   /*************************************************************************/
  35.   /*                                                                       */
  36.   /* Each FTC_CMapNode contains a simple array to map a range of character */
  37.   /* codes to equivalent glyph indices.                                    */
  38.   /*                                                                       */
  39.   /* For now, the implementation is very basic: Each node maps a range of  */
  40.   /* 128 consecutive character codes to their corresponding glyph indices. */
  41.   /*                                                                       */
  42.   /* We could do more complex things, but I don't think it is really very  */
  43.   /* useful.                                                               */
  44.   /*                                                                       */
  45.   /*************************************************************************/
  46.  
  47.  
  48.   /* number of glyph indices / character code per node */
  49. #define FTC_CMAP_INDICES_MAX  128
  50.  
  51.   /* compute a query/node hash */
  52. #define FTC_CMAP_HASH( faceid, index, charcode )         \
  53.           ( _FTC_FACE_ID_HASH( faceid ) + 211 * (index) + \
  54.             ( (charcode) / FTC_CMAP_INDICES_MAX )      )
  55.  
  56.   /* the charmap query */
  57.   typedef struct  FTC_CMapQueryRec_
  58.   {
  59.     FTC_FaceID  face_id;
  60.     FT_UInt     cmap_index;
  61.     FT_UInt32   char_code;
  62.  
  63.   } FTC_CMapQueryRec, *FTC_CMapQuery;
  64.  
  65. #define FTC_CMAP_QUERY( x )  ((FTC_CMapQuery)(x))
  66. #define FTC_CMAP_QUERY_HASH( x )                                         \
  67.           FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
  68.  
  69.   /* the cmap cache node */
  70.   typedef struct  FTC_CMapNodeRec_
  71.   {
  72.     FTC_NodeRec  node;
  73.     FTC_FaceID   face_id;
  74.     FT_UInt      cmap_index;
  75.     FT_UInt32    first;                         /* first character in node */
  76.     FT_UInt16    indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices  */
  77.  
  78.   } FTC_CMapNodeRec, *FTC_CMapNode;
  79.  
  80. #define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
  81. #define FTC_CMAP_NODE_HASH( x )                                      \
  82.           FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
  83.  
  84.   /* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
  85.   /* glyph indices haven't been queried through FT_Get_Glyph_Index() yet   */
  86. #define FTC_CMAP_UNKNOWN  (FT_UInt16)~0
  87.  
  88.  
  89.   /*************************************************************************/
  90.   /*************************************************************************/
  91.   /*****                                                               *****/
  92.   /*****                        CHARMAP NODES                          *****/
  93.   /*****                                                               *****/
  94.   /*************************************************************************/
  95.   /*************************************************************************/
  96.  
  97.  
  98.   FT_CALLBACK_DEF( void )
  99.   ftc_cmap_node_free( FTC_Node   ftcnode,
  100.                       FTC_Cache  cache )
  101.   {
  102.     FTC_CMapNode  node   = (FTC_CMapNode)ftcnode;
  103.     FT_Memory     memory = cache->memory;
  104.  
  105.  
  106.     FT_FREE( node );
  107.   }
  108.  
  109.  
  110.   /* initialize a new cmap node */
  111.   FT_CALLBACK_DEF( FT_Error )
  112.   ftc_cmap_node_new( FTC_Node   *ftcanode,
  113.                      FT_Pointer  ftcquery,
  114.                      FTC_Cache   cache )
  115.   {
  116.     FTC_CMapNode  *anode  = (FTC_CMapNode*)ftcanode;
  117.     FTC_CMapQuery  query  = (FTC_CMapQuery)ftcquery;
  118.     FT_Error       error;
  119.     FT_Memory      memory = cache->memory;
  120.     FTC_CMapNode   node   = NULL;
  121.     FT_UInt        nn;
  122.  
  123.  
  124.     if ( !FT_NEW( node ) )
  125.     {
  126.       node->face_id    = query->face_id;
  127.       node->cmap_index = query->cmap_index;
  128.       node->first      = (query->char_code / FTC_CMAP_INDICES_MAX) *
  129.                          FTC_CMAP_INDICES_MAX;
  130.  
  131.       for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )
  132.         node->indices[nn] = FTC_CMAP_UNKNOWN;
  133.     }
  134.  
  135.     *anode = node;
  136.     return error;
  137.   }
  138.  
  139.  
  140.   /* compute the weight of a given cmap node */
  141.   FT_CALLBACK_DEF( FT_Offset )
  142.   ftc_cmap_node_weight( FTC_Node   cnode,
  143.                         FTC_Cache  cache )
  144.   {
  145.     FT_UNUSED( cnode );
  146.     FT_UNUSED( cache );
  147.  
  148.     return sizeof ( *cnode );
  149.   }
  150.  
  151.  
  152.   /* compare a cmap node to a given query */
  153.   FT_CALLBACK_DEF( FT_Bool )
  154.   ftc_cmap_node_compare( FTC_Node    ftcnode,
  155.                          FT_Pointer  ftcquery,
  156.                          FTC_Cache   cache,
  157.                          FT_Bool*    list_changed )
  158.   {
  159.     FTC_CMapNode   node  = (FTC_CMapNode)ftcnode;
  160.     FTC_CMapQuery  query = (FTC_CMapQuery)ftcquery;
  161.     FT_UNUSED( cache );
  162.  
  163.  
  164.     if ( list_changed )
  165.       *list_changed = FALSE;
  166.     if ( node->face_id    == query->face_id    &&
  167.          node->cmap_index == query->cmap_index )
  168.     {
  169.       FT_UInt32  offset = (FT_UInt32)( query->char_code - node->first );
  170.  
  171.  
  172.       return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
  173.     }
  174.  
  175.     return 0;
  176.   }
  177.  
  178.  
  179.   FT_CALLBACK_DEF( FT_Bool )
  180.   ftc_cmap_node_remove_faceid( FTC_Node    ftcnode,
  181.                                FT_Pointer  ftcface_id,
  182.                                FTC_Cache   cache,
  183.                                FT_Bool*    list_changed )
  184.   {
  185.     FTC_CMapNode  node    = (FTC_CMapNode)ftcnode;
  186.     FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
  187.     FT_UNUSED( cache );
  188.  
  189.  
  190.     if ( list_changed )
  191.       *list_changed = FALSE;
  192.     return FT_BOOL( node->face_id == face_id );
  193.   }
  194.  
  195.  
  196.   /*************************************************************************/
  197.   /*************************************************************************/
  198.   /*****                                                               *****/
  199.   /*****                    GLYPH IMAGE CACHE                          *****/
  200.   /*****                                                               *****/
  201.   /*************************************************************************/
  202.   /*************************************************************************/
  203.  
  204.  
  205.   FT_CALLBACK_TABLE_DEF
  206.   const FTC_CacheClassRec  ftc_cmap_cache_class =
  207.   {
  208.     ftc_cmap_node_new,
  209.     ftc_cmap_node_weight,
  210.     ftc_cmap_node_compare,
  211.     ftc_cmap_node_remove_faceid,
  212.     ftc_cmap_node_free,
  213.  
  214.     sizeof ( FTC_CacheRec ),
  215.     ftc_cache_init,
  216.     ftc_cache_done,
  217.   };
  218.  
  219.  
  220.   /* documentation is in ftcache.h */
  221.  
  222.   FT_EXPORT_DEF( FT_Error )
  223.   FTC_CMapCache_New( FTC_Manager     manager,
  224.                      FTC_CMapCache  *acache )
  225.   {
  226.     return FTC_Manager_RegisterCache( manager,
  227.                                       &ftc_cmap_cache_class,
  228.                                       FTC_CACHE_P( acache ) );
  229.   }
  230.  
  231.  
  232.   /* documentation is in ftcache.h */
  233.  
  234.   FT_EXPORT_DEF( FT_UInt )
  235.   FTC_CMapCache_Lookup( FTC_CMapCache  cmap_cache,
  236.                         FTC_FaceID     face_id,
  237.                         FT_Int         cmap_index,
  238.                         FT_UInt32      char_code )
  239.   {
  240.     FTC_Cache         cache = FTC_CACHE( cmap_cache );
  241.     FTC_CMapQueryRec  query;
  242.     FTC_Node          node;
  243.     FT_Error          error;
  244.     FT_UInt           gindex = 0;
  245.     FT_PtrDist        hash;
  246.     FT_Int            no_cmap_change = 0;
  247.  
  248.  
  249.     if ( cmap_index < 0 )
  250.     {
  251.       /* Treat a negative cmap index as a special value, meaning that you */
  252.       /* don't want to change the FT_Face's character map through this    */
  253.       /* call.  This can be useful if the face requester callback already */
  254.       /* sets the face's charmap to the appropriate value.                */
  255.  
  256.       no_cmap_change = 1;
  257.       cmap_index     = 0;
  258.     }
  259.  
  260.     if ( !cache )
  261.     {
  262.       FT_TRACE0(( "FTC_CMapCache_Lookup: bad arguments, returning 0\n" ));
  263.       return 0;
  264.     }
  265.  
  266.     query.face_id    = face_id;
  267.     query.cmap_index = (FT_UInt)cmap_index;
  268.     query.char_code  = char_code;
  269.  
  270.     hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
  271.  
  272. #if 1
  273.     FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
  274.                           node, error );
  275. #else
  276.     error = FTC_Cache_Lookup( cache, hash, &query, &node );
  277. #endif
  278.     if ( error )
  279.       goto Exit;
  280.  
  281.     FT_ASSERT( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first ) <
  282.                 FTC_CMAP_INDICES_MAX );
  283.  
  284.     /* something rotten can happen with rogue clients */
  285.     if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >=
  286.                     FTC_CMAP_INDICES_MAX ) )
  287.       return 0; /* XXX: should return appropriate error */
  288.  
  289.     gindex = FTC_CMAP_NODE( node )->indices[char_code -
  290.                                             FTC_CMAP_NODE( node )->first];
  291.     if ( gindex == FTC_CMAP_UNKNOWN )
  292.     {
  293.       FT_Face  face;
  294.  
  295.  
  296.       gindex = 0;
  297.  
  298.       error = FTC_Manager_LookupFace( cache->manager,
  299.                                       FTC_CMAP_NODE( node )->face_id,
  300.                                       &face );
  301.       if ( error )
  302.         goto Exit;
  303.  
  304. #ifdef FT_MAX_CHARMAP_CACHEABLE
  305.       /* something rotten can happen with rogue clients */
  306.       if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE )
  307.         return 0; /* XXX: should return appropriate error */
  308. #endif
  309.  
  310.       if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
  311.       {
  312.         FT_CharMap  old, cmap  = NULL;
  313.  
  314.  
  315.         old  = face->charmap;
  316.         cmap = face->charmaps[cmap_index];
  317.  
  318.         if ( old != cmap && !no_cmap_change )
  319.           FT_Set_Charmap( face, cmap );
  320.  
  321.         gindex = FT_Get_Char_Index( face, char_code );
  322.  
  323.         if ( old != cmap && !no_cmap_change )
  324.           FT_Set_Charmap( face, old );
  325.       }
  326.  
  327.       FTC_CMAP_NODE( node )->indices[char_code -
  328.                                      FTC_CMAP_NODE( node )->first]
  329.         = (FT_UShort)gindex;
  330.     }
  331.  
  332.   Exit:
  333.     return gindex;
  334.   }
  335.  
  336.  
  337. /* END */
  338.