Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  afglobal.c                                                             */
  4. /*                                                                         */
  5. /*    Auto-fitter routines to compute global hinting values (body).        */
  6. /*                                                                         */
  7. /*  Copyright 2003-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 "afglobal.h"
  20. #include "afdummy.h"
  21. #include "aflatin.h"
  22. #include "afcjk.h"
  23. #include "afindic.h"
  24. #include "afpic.h"
  25.  
  26. #include "aferrors.h"
  27.  
  28. #ifdef FT_OPTION_AUTOFIT2
  29. #include "aflatin2.h"
  30. #endif
  31.  
  32. #ifndef FT_CONFIG_OPTION_PIC
  33.  
  34.   /* when updating this table, don't forget to update          */
  35.   /* AF_SCRIPT_CLASSES_COUNT and autofit_module_class_pic_init */
  36.  
  37.   /* populate this list when you add new scripts */
  38.   static AF_ScriptClass const  af_script_classes[] =
  39.   {
  40.     &af_dummy_script_class,
  41. #ifdef FT_OPTION_AUTOFIT2
  42.     &af_latin2_script_class,
  43. #endif
  44.     &af_latin_script_class,
  45.     &af_cjk_script_class,
  46.     &af_indic_script_class,
  47.     NULL  /* do not remove */
  48.   };
  49.  
  50. #endif /* !FT_CONFIG_OPTION_PIC */
  51.  
  52.  
  53.   /* Compute the script index of each glyph within a given face. */
  54.  
  55.   static FT_Error
  56.   af_face_globals_compute_script_coverage( AF_FaceGlobals  globals )
  57.   {
  58.     FT_Error    error;
  59.     FT_Face     face        = globals->face;
  60.     FT_CharMap  old_charmap = face->charmap;
  61.     FT_Byte*    gscripts    = globals->glyph_scripts;
  62.     FT_UInt     ss;
  63.     FT_UInt     i;
  64.  
  65.  
  66.     /* the value AF_SCRIPT_NONE means `uncovered glyph' */
  67.     FT_MEM_SET( globals->glyph_scripts,
  68.                 AF_SCRIPT_NONE,
  69.                 globals->glyph_count );
  70.  
  71.     error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
  72.     if ( error )
  73.     {
  74.      /*
  75.       *  Ignore this error; we simply use the fallback script.
  76.       *  XXX: Shouldn't we rather disable hinting?
  77.       */
  78.       error = FT_Err_Ok;
  79.       goto Exit;
  80.     }
  81.  
  82.     /* scan each script in a Unicode charmap */
  83.     for ( ss = 0; AF_SCRIPT_CLASSES_GET[ss]; ss++ )
  84.     {
  85.       AF_ScriptClass      clazz = AF_SCRIPT_CLASSES_GET[ss];
  86.       AF_Script_UniRange  range;
  87.  
  88.  
  89.       if ( clazz->script_uni_ranges == NULL )
  90.         continue;
  91.  
  92.       /*
  93.        *  Scan all Unicode points in the range and set the corresponding
  94.        *  glyph script index.
  95.        */
  96.       for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
  97.       {
  98.         FT_ULong  charcode = range->first;
  99.         FT_UInt   gindex;
  100.  
  101.  
  102.         gindex = FT_Get_Char_Index( face, charcode );
  103.  
  104.         if ( gindex != 0                             &&
  105.              gindex < (FT_ULong)globals->glyph_count &&
  106.              gscripts[gindex] == AF_SCRIPT_NONE )
  107.           gscripts[gindex] = (FT_Byte)ss;
  108.  
  109.         for (;;)
  110.         {
  111.           charcode = FT_Get_Next_Char( face, charcode, &gindex );
  112.  
  113.           if ( gindex == 0 || charcode > range->last )
  114.             break;
  115.  
  116.           if ( gindex < (FT_ULong)globals->glyph_count &&
  117.                gscripts[gindex] == AF_SCRIPT_NONE )
  118.             gscripts[gindex] = (FT_Byte)ss;
  119.         }
  120.       }
  121.     }
  122.  
  123.     /* mark ASCII digits */
  124.     for ( i = 0x30; i <= 0x39; i++ )
  125.     {
  126.       FT_UInt  gindex = FT_Get_Char_Index( face, i );
  127.  
  128.  
  129.       if ( gindex != 0 && gindex < (FT_ULong)globals->glyph_count )
  130.         gscripts[gindex] |= AF_DIGIT;
  131.     }
  132.  
  133.   Exit:
  134.     /*
  135.      *  By default, all uncovered glyphs are set to the fallback script.
  136.      *  XXX: Shouldn't we disable hinting or do something similar?
  137.      */
  138.     if ( globals->module->fallback_script != AF_SCRIPT_NONE )
  139.     {
  140.       FT_Long  nn;
  141.  
  142.  
  143.       for ( nn = 0; nn < globals->glyph_count; nn++ )
  144.       {
  145.         if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_NONE )
  146.         {
  147.           gscripts[nn] &= ~AF_SCRIPT_NONE;
  148.           gscripts[nn] |= globals->module->fallback_script;
  149.         }
  150.       }
  151.     }
  152.  
  153.     FT_Set_Charmap( face, old_charmap );
  154.     return error;
  155.   }
  156.  
  157.  
  158.   FT_LOCAL_DEF( FT_Error )
  159.   af_face_globals_new( FT_Face          face,
  160.                        AF_FaceGlobals  *aglobals,
  161.                        AF_Module        module )
  162.   {
  163.     FT_Error        error;
  164.     FT_Memory       memory;
  165.     AF_FaceGlobals  globals = NULL;
  166.  
  167.  
  168.     memory = face->memory;
  169.  
  170.     if ( FT_ALLOC( globals, sizeof ( *globals ) +
  171.                             face->num_glyphs * sizeof ( FT_Byte ) ) )
  172.       goto Exit;
  173.  
  174.     globals->face          = face;
  175.     globals->glyph_count   = face->num_glyphs;
  176.     globals->glyph_scripts = (FT_Byte*)( globals + 1 );
  177.     globals->module        = module;
  178.  
  179.     error = af_face_globals_compute_script_coverage( globals );
  180.     if ( error )
  181.     {
  182.       af_face_globals_free( globals );
  183.       globals = NULL;
  184.     }
  185.  
  186.     globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
  187.  
  188.   Exit:
  189.     *aglobals = globals;
  190.     return error;
  191.   }
  192.  
  193.  
  194.   FT_LOCAL_DEF( void )
  195.   af_face_globals_free( AF_FaceGlobals  globals )
  196.   {
  197.     if ( globals )
  198.     {
  199.       FT_Memory  memory = globals->face->memory;
  200.       FT_UInt    nn;
  201.  
  202.  
  203.       for ( nn = 0; nn < AF_SCRIPT_MAX; nn++ )
  204.       {
  205.         if ( globals->metrics[nn] )
  206.         {
  207.           AF_ScriptClass  clazz = AF_SCRIPT_CLASSES_GET[nn];
  208.  
  209.  
  210.           FT_ASSERT( globals->metrics[nn]->clazz == clazz );
  211.  
  212.           if ( clazz->script_metrics_done )
  213.             clazz->script_metrics_done( globals->metrics[nn] );
  214.  
  215.           FT_FREE( globals->metrics[nn] );
  216.         }
  217.       }
  218.  
  219.       globals->glyph_count   = 0;
  220.       globals->glyph_scripts = NULL;  /* no need to free this one! */
  221.       globals->face          = NULL;
  222.  
  223.       FT_FREE( globals );
  224.     }
  225.   }
  226.  
  227.  
  228.   FT_LOCAL_DEF( FT_Error )
  229.   af_face_globals_get_metrics( AF_FaceGlobals     globals,
  230.                                FT_UInt            gindex,
  231.                                FT_UInt            options,
  232.                                AF_ScriptMetrics  *ametrics )
  233.   {
  234.     AF_ScriptMetrics  metrics = NULL;
  235.     FT_UInt           gidx;
  236.     AF_ScriptClass    clazz;
  237.     FT_UInt           script     = options & 15;
  238.     const FT_Offset   script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
  239.                                      sizeof ( AF_SCRIPT_CLASSES_GET[0] );
  240.     FT_Error          error      = FT_Err_Ok;
  241.  
  242.  
  243.     if ( gindex >= (FT_ULong)globals->glyph_count )
  244.     {
  245.       error = FT_THROW( Invalid_Argument );
  246.       goto Exit;
  247.     }
  248.  
  249.     gidx = script;
  250.     if ( gidx == 0 || gidx + 1 >= script_max )
  251.       gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_NONE;
  252.  
  253.     clazz = AF_SCRIPT_CLASSES_GET[gidx];
  254.     if ( script == 0 )
  255.       script = clazz->script;
  256.  
  257.     metrics = globals->metrics[clazz->script];
  258.     if ( metrics == NULL )
  259.     {
  260.       /* create the global metrics object if necessary */
  261.       FT_Memory  memory = globals->face->memory;
  262.  
  263.  
  264.       if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
  265.         goto Exit;
  266.  
  267.       metrics->clazz   = clazz;
  268.       metrics->globals = globals;
  269.  
  270.       if ( clazz->script_metrics_init )
  271.       {
  272.         error = clazz->script_metrics_init( metrics, globals->face );
  273.         if ( error )
  274.         {
  275.           if ( clazz->script_metrics_done )
  276.             clazz->script_metrics_done( metrics );
  277.  
  278.           FT_FREE( metrics );
  279.           goto Exit;
  280.         }
  281.       }
  282.  
  283.       globals->metrics[clazz->script] = metrics;
  284.     }
  285.  
  286.   Exit:
  287.     *ametrics = metrics;
  288.  
  289.     return error;
  290.   }
  291.  
  292.  
  293.   FT_LOCAL_DEF( FT_Bool )
  294.   af_face_globals_is_digit( AF_FaceGlobals  globals,
  295.                             FT_UInt         gindex )
  296.   {
  297.     if ( gindex < (FT_ULong)globals->glyph_count )
  298.       return (FT_Bool)( globals->glyph_scripts[gindex] & AF_DIGIT );
  299.  
  300.     return (FT_Bool)0;
  301.   }
  302.  
  303.  
  304. /* END */
  305.