misc/libfreetype/src/pshinter/pshglob.c
changeset 5172 88f2e05288ba
equal deleted inserted replaced
5171:f9283dc4860d 5172:88f2e05288ba
       
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  pshglob.c                                                              */
       
     4 /*                                                                         */
       
     5 /*    PostScript hinter global hinting management (body).                  */
       
     6 /*    Inspired by the new auto-hinter module.                              */
       
     7 /*                                                                         */
       
     8 /*  Copyright 2001, 2002, 2003, 2004, 2006, 2010 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 #include <ft2build.h>
       
    21 #include FT_FREETYPE_H
       
    22 #include FT_INTERNAL_OBJECTS_H
       
    23 #include "pshglob.h"
       
    24 
       
    25 #ifdef DEBUG_HINTER
       
    26   PSH_Globals  ps_debug_globals = 0;
       
    27 #endif
       
    28 
       
    29 
       
    30   /*************************************************************************/
       
    31   /*************************************************************************/
       
    32   /*****                                                               *****/
       
    33   /*****                       STANDARD WIDTHS                         *****/
       
    34   /*****                                                               *****/
       
    35   /*************************************************************************/
       
    36   /*************************************************************************/
       
    37 
       
    38 
       
    39   /* scale the widths/heights table */
       
    40   static void
       
    41   psh_globals_scale_widths( PSH_Globals  globals,
       
    42                             FT_UInt      direction )
       
    43   {
       
    44     PSH_Dimension  dim   = &globals->dimension[direction];
       
    45     PSH_Widths     stdw  = &dim->stdw;
       
    46     FT_UInt        count = stdw->count;
       
    47     PSH_Width      width = stdw->widths;
       
    48     PSH_Width      stand = width;               /* standard width/height */
       
    49     FT_Fixed       scale = dim->scale_mult;
       
    50 
       
    51 
       
    52     if ( count > 0 )
       
    53     {
       
    54       width->cur = FT_MulFix( width->org, scale );
       
    55       width->fit = FT_PIX_ROUND( width->cur );
       
    56 
       
    57       width++;
       
    58       count--;
       
    59 
       
    60       for ( ; count > 0; count--, width++ )
       
    61       {
       
    62         FT_Pos  w, dist;
       
    63 
       
    64 
       
    65         w    = FT_MulFix( width->org, scale );
       
    66         dist = w - stand->cur;
       
    67 
       
    68         if ( dist < 0 )
       
    69           dist = -dist;
       
    70 
       
    71         if ( dist < 128 )
       
    72           w = stand->cur;
       
    73 
       
    74         width->cur = w;
       
    75         width->fit = FT_PIX_ROUND( w );
       
    76       }
       
    77     }
       
    78   }
       
    79 
       
    80 
       
    81 #if 0
       
    82 
       
    83   /* org_width is is font units, result in device pixels, 26.6 format */
       
    84   FT_LOCAL_DEF( FT_Pos )
       
    85   psh_dimension_snap_width( PSH_Dimension  dimension,
       
    86                             FT_Int         org_width )
       
    87   {
       
    88     FT_UInt  n;
       
    89     FT_Pos   width     = FT_MulFix( org_width, dimension->scale_mult );
       
    90     FT_Pos   best      = 64 + 32 + 2;
       
    91     FT_Pos   reference = width;
       
    92 
       
    93 
       
    94     for ( n = 0; n < dimension->stdw.count; n++ )
       
    95     {
       
    96       FT_Pos  w;
       
    97       FT_Pos  dist;
       
    98 
       
    99 
       
   100       w = dimension->stdw.widths[n].cur;
       
   101       dist = width - w;
       
   102       if ( dist < 0 )
       
   103         dist = -dist;
       
   104       if ( dist < best )
       
   105       {
       
   106         best      = dist;
       
   107         reference = w;
       
   108       }
       
   109     }
       
   110 
       
   111     if ( width >= reference )
       
   112     {
       
   113       width -= 0x21;
       
   114       if ( width < reference )
       
   115         width = reference;
       
   116     }
       
   117     else
       
   118     {
       
   119       width += 0x21;
       
   120       if ( width > reference )
       
   121         width = reference;
       
   122     }
       
   123 
       
   124     return width;
       
   125   }
       
   126 
       
   127 #endif /* 0 */
       
   128 
       
   129 
       
   130   /*************************************************************************/
       
   131   /*************************************************************************/
       
   132   /*****                                                               *****/
       
   133   /*****                       BLUE ZONES                              *****/
       
   134   /*****                                                               *****/
       
   135   /*************************************************************************/
       
   136   /*************************************************************************/
       
   137 
       
   138   static void
       
   139   psh_blues_set_zones_0( PSH_Blues       target,
       
   140                          FT_Bool         is_others,
       
   141                          FT_UInt         read_count,
       
   142                          FT_Short*       read,
       
   143                          PSH_Blue_Table  top_table,
       
   144                          PSH_Blue_Table  bot_table )
       
   145   {
       
   146     FT_UInt  count_top = top_table->count;
       
   147     FT_UInt  count_bot = bot_table->count;
       
   148     FT_Bool  first     = 1;
       
   149 
       
   150     FT_UNUSED( target );
       
   151 
       
   152 
       
   153     for ( ; read_count > 1; read_count -= 2 )
       
   154     {
       
   155       FT_Int         reference, delta;
       
   156       FT_UInt        count;
       
   157       PSH_Blue_Zone  zones, zone;
       
   158       FT_Bool        top;
       
   159 
       
   160 
       
   161       /* read blue zone entry, and select target top/bottom zone */
       
   162       top = 0;
       
   163       if ( first || is_others )
       
   164       {
       
   165         reference = read[1];
       
   166         delta     = read[0] - reference;
       
   167 
       
   168         zones = bot_table->zones;
       
   169         count = count_bot;
       
   170         first = 0;
       
   171       }
       
   172       else
       
   173       {
       
   174         reference = read[0];
       
   175         delta     = read[1] - reference;
       
   176 
       
   177         zones = top_table->zones;
       
   178         count = count_top;
       
   179         top   = 1;
       
   180       }
       
   181 
       
   182       /* insert into sorted table */
       
   183       zone = zones;
       
   184       for ( ; count > 0; count--, zone++ )
       
   185       {
       
   186         if ( reference < zone->org_ref )
       
   187           break;
       
   188 
       
   189         if ( reference == zone->org_ref )
       
   190         {
       
   191           FT_Int  delta0 = zone->org_delta;
       
   192 
       
   193 
       
   194           /* we have two zones on the same reference position -- */
       
   195           /* only keep the largest one                           */
       
   196           if ( delta < 0 )
       
   197           {
       
   198             if ( delta < delta0 )
       
   199               zone->org_delta = delta;
       
   200           }
       
   201           else
       
   202           {
       
   203             if ( delta > delta0 )
       
   204               zone->org_delta = delta;
       
   205           }
       
   206           goto Skip;
       
   207         }
       
   208       }
       
   209 
       
   210       for ( ; count > 0; count-- )
       
   211         zone[count] = zone[count-1];
       
   212 
       
   213       zone->org_ref   = reference;
       
   214       zone->org_delta = delta;
       
   215 
       
   216       if ( top )
       
   217         count_top++;
       
   218       else
       
   219         count_bot++;
       
   220 
       
   221     Skip:
       
   222       read += 2;
       
   223     }
       
   224 
       
   225     top_table->count = count_top;
       
   226     bot_table->count = count_bot;
       
   227   }
       
   228 
       
   229 
       
   230   /* Re-read blue zones from the original fonts and store them into out */
       
   231   /* private structure.  This function re-orders, sanitizes and         */
       
   232   /* fuzz-expands the zones as well.                                    */
       
   233   static void
       
   234   psh_blues_set_zones( PSH_Blues  target,
       
   235                        FT_UInt    count,
       
   236                        FT_Short*  blues,
       
   237                        FT_UInt    count_others,
       
   238                        FT_Short*  other_blues,
       
   239                        FT_Int     fuzz,
       
   240                        FT_Int     family )
       
   241   {
       
   242     PSH_Blue_Table  top_table, bot_table;
       
   243     FT_Int          count_top, count_bot;
       
   244 
       
   245 
       
   246     if ( family )
       
   247     {
       
   248       top_table = &target->family_top;
       
   249       bot_table = &target->family_bottom;
       
   250     }
       
   251     else
       
   252     {
       
   253       top_table = &target->normal_top;
       
   254       bot_table = &target->normal_bottom;
       
   255     }
       
   256 
       
   257     /* read the input blue zones, and build two sorted tables  */
       
   258     /* (one for the top zones, the other for the bottom zones) */
       
   259     top_table->count = 0;
       
   260     bot_table->count = 0;
       
   261 
       
   262     /* first, the blues */
       
   263     psh_blues_set_zones_0( target, 0,
       
   264                            count, blues, top_table, bot_table );
       
   265     psh_blues_set_zones_0( target, 1,
       
   266                            count_others, other_blues, top_table, bot_table );
       
   267 
       
   268     count_top = top_table->count;
       
   269     count_bot = bot_table->count;
       
   270 
       
   271     /* sanitize top table */
       
   272     if ( count_top > 0 )
       
   273     {
       
   274       PSH_Blue_Zone  zone = top_table->zones;
       
   275 
       
   276 
       
   277       for ( count = count_top; count > 0; count--, zone++ )
       
   278       {
       
   279         FT_Int  delta;
       
   280 
       
   281 
       
   282         if ( count > 1 )
       
   283         {
       
   284           delta = zone[1].org_ref - zone[0].org_ref;
       
   285           if ( zone->org_delta > delta )
       
   286             zone->org_delta = delta;
       
   287         }
       
   288 
       
   289         zone->org_bottom = zone->org_ref;
       
   290         zone->org_top    = zone->org_delta + zone->org_ref;
       
   291       }
       
   292     }
       
   293 
       
   294     /* sanitize bottom table */
       
   295     if ( count_bot > 0 )
       
   296     {
       
   297       PSH_Blue_Zone  zone = bot_table->zones;
       
   298 
       
   299 
       
   300       for ( count = count_bot; count > 0; count--, zone++ )
       
   301       {
       
   302         FT_Int  delta;
       
   303 
       
   304 
       
   305         if ( count > 1 )
       
   306         {
       
   307           delta = zone[0].org_ref - zone[1].org_ref;
       
   308           if ( zone->org_delta < delta )
       
   309             zone->org_delta = delta;
       
   310         }
       
   311 
       
   312         zone->org_top    = zone->org_ref;
       
   313         zone->org_bottom = zone->org_delta + zone->org_ref;
       
   314       }
       
   315     }
       
   316 
       
   317     /* expand top and bottom tables with blue fuzz */
       
   318     {
       
   319       FT_Int         dim, top, bot, delta;
       
   320       PSH_Blue_Zone  zone;
       
   321 
       
   322 
       
   323       zone  = top_table->zones;
       
   324       count = count_top;
       
   325 
       
   326       for ( dim = 1; dim >= 0; dim-- )
       
   327       {
       
   328         if ( count > 0 )
       
   329         {
       
   330           /* expand the bottom of the lowest zone normally */
       
   331           zone->org_bottom -= fuzz;
       
   332 
       
   333           /* expand the top and bottom of intermediate zones;    */
       
   334           /* checking that the interval is smaller than the fuzz */
       
   335           top = zone->org_top;
       
   336 
       
   337           for ( count--; count > 0; count-- )
       
   338           {
       
   339             bot   = zone[1].org_bottom;
       
   340             delta = bot - top;
       
   341 
       
   342             if ( delta < 2 * fuzz )
       
   343               zone[0].org_top = zone[1].org_bottom = top + delta / 2;
       
   344             else
       
   345             {
       
   346               zone[0].org_top    = top + fuzz;
       
   347               zone[1].org_bottom = bot - fuzz;
       
   348             }
       
   349 
       
   350             zone++;
       
   351             top = zone->org_top;
       
   352           }
       
   353 
       
   354           /* expand the top of the highest zone normally */
       
   355           zone->org_top = top + fuzz;
       
   356         }
       
   357         zone  = bot_table->zones;
       
   358         count = count_bot;
       
   359       }
       
   360     }
       
   361   }
       
   362 
       
   363 
       
   364   /* reset the blues table when the device transform changes */
       
   365   static void
       
   366   psh_blues_scale_zones( PSH_Blues  blues,
       
   367                          FT_Fixed   scale,
       
   368                          FT_Pos     delta )
       
   369   {
       
   370     FT_UInt         count;
       
   371     FT_UInt         num;
       
   372     PSH_Blue_Table  table = 0;
       
   373 
       
   374     /*                                                        */
       
   375     /* Determine whether we need to suppress overshoots or    */
       
   376     /* not.  We simply need to compare the vertical scale     */
       
   377     /* parameter to the raw bluescale value.  Here is why:    */
       
   378     /*                                                        */
       
   379     /*   We need to suppress overshoots for all pointsizes.   */
       
   380     /*   At 300dpi that satisfies:                            */
       
   381     /*                                                        */
       
   382     /*      pointsize < 240*bluescale + 0.49                  */
       
   383     /*                                                        */
       
   384     /*   This corresponds to:                                 */
       
   385     /*                                                        */
       
   386     /*      pixelsize < 1000*bluescale + 49/24                */
       
   387     /*                                                        */
       
   388     /*      scale*EM_Size < 1000*bluescale + 49/24            */
       
   389     /*                                                        */
       
   390     /*   However, for normal Type 1 fonts, EM_Size is 1000!   */
       
   391     /*   We thus only check:                                  */
       
   392     /*                                                        */
       
   393     /*      scale < bluescale + 49/24000                      */
       
   394     /*                                                        */
       
   395     /*   which we shorten to                                  */
       
   396     /*                                                        */
       
   397     /*      "scale < bluescale"                               */
       
   398     /*                                                        */
       
   399     /* Note that `blue_scale' is stored 1000 times its real   */
       
   400     /* value, and that `scale' converts from font units to    */
       
   401     /* fractional pixels.                                     */
       
   402     /*                                                        */
       
   403 
       
   404     /* 1000 / 64 = 125 / 8 */
       
   405     if ( scale >= 0x20C49BAL )
       
   406       blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 );
       
   407     else
       
   408       blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 );
       
   409 
       
   410     /*                                                        */
       
   411     /*  The blue threshold is the font units distance under   */
       
   412     /*  which overshoots are suppressed due to the BlueShift  */
       
   413     /*  even if the scale is greater than BlueScale.          */
       
   414     /*                                                        */
       
   415     /*  It is the smallest distance such that                 */
       
   416     /*                                                        */
       
   417     /*    dist <= BlueShift && dist*scale <= 0.5 pixels       */
       
   418     /*                                                        */
       
   419     {
       
   420       FT_Int  threshold = blues->blue_shift;
       
   421 
       
   422 
       
   423       while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 )
       
   424         threshold--;
       
   425 
       
   426       blues->blue_threshold = threshold;
       
   427     }
       
   428 
       
   429     for ( num = 0; num < 4; num++ )
       
   430     {
       
   431       PSH_Blue_Zone  zone;
       
   432 
       
   433 
       
   434       switch ( num )
       
   435       {
       
   436       case 0:
       
   437         table = &blues->normal_top;
       
   438         break;
       
   439       case 1:
       
   440         table = &blues->normal_bottom;
       
   441         break;
       
   442       case 2:
       
   443         table = &blues->family_top;
       
   444         break;
       
   445       default:
       
   446         table = &blues->family_bottom;
       
   447         break;
       
   448       }
       
   449 
       
   450       zone  = table->zones;
       
   451       count = table->count;
       
   452       for ( ; count > 0; count--, zone++ )
       
   453       {
       
   454         zone->cur_top    = FT_MulFix( zone->org_top,    scale ) + delta;
       
   455         zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta;
       
   456         zone->cur_ref    = FT_MulFix( zone->org_ref,    scale ) + delta;
       
   457         zone->cur_delta  = FT_MulFix( zone->org_delta,  scale );
       
   458 
       
   459         /* round scaled reference position */
       
   460         zone->cur_ref = FT_PIX_ROUND( zone->cur_ref );
       
   461 
       
   462 #if 0
       
   463         if ( zone->cur_ref > zone->cur_top )
       
   464           zone->cur_ref -= 64;
       
   465         else if ( zone->cur_ref < zone->cur_bottom )
       
   466           zone->cur_ref += 64;
       
   467 #endif
       
   468       }
       
   469     }
       
   470 
       
   471     /* process the families now */
       
   472 
       
   473     for ( num = 0; num < 2; num++ )
       
   474     {
       
   475       PSH_Blue_Zone   zone1, zone2;
       
   476       FT_UInt         count1, count2;
       
   477       PSH_Blue_Table  normal, family;
       
   478 
       
   479 
       
   480       switch ( num )
       
   481       {
       
   482       case 0:
       
   483         normal = &blues->normal_top;
       
   484         family = &blues->family_top;
       
   485         break;
       
   486 
       
   487       default:
       
   488         normal = &blues->normal_bottom;
       
   489         family = &blues->family_bottom;
       
   490       }
       
   491 
       
   492       zone1  = normal->zones;
       
   493       count1 = normal->count;
       
   494 
       
   495       for ( ; count1 > 0; count1--, zone1++ )
       
   496       {
       
   497         /* try to find a family zone whose reference position is less */
       
   498         /* than 1 pixel far from the current zone                     */
       
   499         zone2  = family->zones;
       
   500         count2 = family->count;
       
   501 
       
   502         for ( ; count2 > 0; count2--, zone2++ )
       
   503         {
       
   504           FT_Pos  Delta;
       
   505 
       
   506 
       
   507           Delta = zone1->org_ref - zone2->org_ref;
       
   508           if ( Delta < 0 )
       
   509             Delta = -Delta;
       
   510 
       
   511           if ( FT_MulFix( Delta, scale ) < 64 )
       
   512           {
       
   513             zone1->cur_top    = zone2->cur_top;
       
   514             zone1->cur_bottom = zone2->cur_bottom;
       
   515             zone1->cur_ref    = zone2->cur_ref;
       
   516             zone1->cur_delta  = zone2->cur_delta;
       
   517             break;
       
   518           }
       
   519         }
       
   520       }
       
   521     }
       
   522   }
       
   523 
       
   524 
       
   525   FT_LOCAL_DEF( void )
       
   526   psh_blues_snap_stem( PSH_Blues      blues,
       
   527                        FT_Int         stem_top,
       
   528                        FT_Int         stem_bot,
       
   529                        PSH_Alignment  alignment )
       
   530   {
       
   531     PSH_Blue_Table  table;
       
   532     FT_UInt         count;
       
   533     FT_Pos          delta;
       
   534     PSH_Blue_Zone   zone;
       
   535     FT_Int          no_shoots;
       
   536 
       
   537 
       
   538     alignment->align = PSH_BLUE_ALIGN_NONE;
       
   539 
       
   540     no_shoots = blues->no_overshoots;
       
   541 
       
   542     /* look up stem top in top zones table */
       
   543     table = &blues->normal_top;
       
   544     count = table->count;
       
   545     zone  = table->zones;
       
   546 
       
   547     for ( ; count > 0; count--, zone++ )
       
   548     {
       
   549       delta = stem_top - zone->org_bottom;
       
   550       if ( delta < -blues->blue_fuzz )
       
   551         break;
       
   552 
       
   553       if ( stem_top <= zone->org_top + blues->blue_fuzz )
       
   554       {
       
   555         if ( no_shoots || delta <= blues->blue_threshold )
       
   556         {
       
   557           alignment->align    |= PSH_BLUE_ALIGN_TOP;
       
   558           alignment->align_top = zone->cur_ref;
       
   559         }
       
   560         break;
       
   561       }
       
   562     }
       
   563 
       
   564     /* look up stem bottom in bottom zones table */
       
   565     table = &blues->normal_bottom;
       
   566     count = table->count;
       
   567     zone  = table->zones + count-1;
       
   568 
       
   569     for ( ; count > 0; count--, zone-- )
       
   570     {
       
   571       delta = zone->org_top - stem_bot;
       
   572       if ( delta < -blues->blue_fuzz )
       
   573         break;
       
   574 
       
   575       if ( stem_bot >= zone->org_bottom - blues->blue_fuzz )
       
   576       {
       
   577         if ( no_shoots || delta < blues->blue_threshold )
       
   578         {
       
   579           alignment->align    |= PSH_BLUE_ALIGN_BOT;
       
   580           alignment->align_bot = zone->cur_ref;
       
   581         }
       
   582         break;
       
   583       }
       
   584     }
       
   585   }
       
   586 
       
   587 
       
   588   /*************************************************************************/
       
   589   /*************************************************************************/
       
   590   /*****                                                               *****/
       
   591   /*****                        GLOBAL HINTS                           *****/
       
   592   /*****                                                               *****/
       
   593   /*************************************************************************/
       
   594   /*************************************************************************/
       
   595 
       
   596   static void
       
   597   psh_globals_destroy( PSH_Globals  globals )
       
   598   {
       
   599     if ( globals )
       
   600     {
       
   601       FT_Memory  memory;
       
   602 
       
   603 
       
   604       memory = globals->memory;
       
   605       globals->dimension[0].stdw.count = 0;
       
   606       globals->dimension[1].stdw.count = 0;
       
   607 
       
   608       globals->blues.normal_top.count    = 0;
       
   609       globals->blues.normal_bottom.count = 0;
       
   610       globals->blues.family_top.count    = 0;
       
   611       globals->blues.family_bottom.count = 0;
       
   612 
       
   613       FT_FREE( globals );
       
   614 
       
   615 #ifdef DEBUG_HINTER
       
   616       ps_debug_globals = 0;
       
   617 #endif
       
   618     }
       
   619   }
       
   620 
       
   621 
       
   622   static FT_Error
       
   623   psh_globals_new( FT_Memory     memory,
       
   624                    T1_Private*   priv,
       
   625                    PSH_Globals  *aglobals )
       
   626   {
       
   627     PSH_Globals  globals = NULL;
       
   628     FT_Error     error;
       
   629 
       
   630 
       
   631     if ( !FT_NEW( globals ) )
       
   632     {
       
   633       FT_UInt    count;
       
   634       FT_Short*  read;
       
   635 
       
   636 
       
   637       globals->memory = memory;
       
   638 
       
   639       /* copy standard widths */
       
   640       {
       
   641         PSH_Dimension  dim   = &globals->dimension[1];
       
   642         PSH_Width      write = dim->stdw.widths;
       
   643 
       
   644 
       
   645         write->org = priv->standard_width[0];
       
   646         write++;
       
   647 
       
   648         read = priv->snap_widths;
       
   649         for ( count = priv->num_snap_widths; count > 0; count-- )
       
   650         {
       
   651           write->org = *read;
       
   652           write++;
       
   653           read++;
       
   654         }
       
   655 
       
   656         dim->stdw.count = priv->num_snap_widths + 1;
       
   657       }
       
   658 
       
   659       /* copy standard heights */
       
   660       {
       
   661         PSH_Dimension  dim = &globals->dimension[0];
       
   662         PSH_Width      write = dim->stdw.widths;
       
   663 
       
   664 
       
   665         write->org = priv->standard_height[0];
       
   666         write++;
       
   667         read = priv->snap_heights;
       
   668         for ( count = priv->num_snap_heights; count > 0; count-- )
       
   669         {
       
   670           write->org = *read;
       
   671           write++;
       
   672           read++;
       
   673         }
       
   674 
       
   675         dim->stdw.count = priv->num_snap_heights + 1;
       
   676       }
       
   677 
       
   678       /* copy blue zones */
       
   679       psh_blues_set_zones( &globals->blues, priv->num_blue_values,
       
   680                            priv->blue_values, priv->num_other_blues,
       
   681                            priv->other_blues, priv->blue_fuzz, 0 );
       
   682 
       
   683       psh_blues_set_zones( &globals->blues, priv->num_family_blues,
       
   684                            priv->family_blues, priv->num_family_other_blues,
       
   685                            priv->family_other_blues, priv->blue_fuzz, 1 );
       
   686 
       
   687       globals->blues.blue_scale = priv->blue_scale;
       
   688       globals->blues.blue_shift = priv->blue_shift;
       
   689       globals->blues.blue_fuzz  = priv->blue_fuzz;
       
   690 
       
   691       globals->dimension[0].scale_mult  = 0;
       
   692       globals->dimension[0].scale_delta = 0;
       
   693       globals->dimension[1].scale_mult  = 0;
       
   694       globals->dimension[1].scale_delta = 0;
       
   695 
       
   696 #ifdef DEBUG_HINTER
       
   697       ps_debug_globals = globals;
       
   698 #endif
       
   699     }
       
   700 
       
   701     *aglobals = globals;
       
   702     return error;
       
   703   }
       
   704 
       
   705 
       
   706   FT_LOCAL_DEF( FT_Error )
       
   707   psh_globals_set_scale( PSH_Globals  globals,
       
   708                          FT_Fixed     x_scale,
       
   709                          FT_Fixed     y_scale,
       
   710                          FT_Fixed     x_delta,
       
   711                          FT_Fixed     y_delta )
       
   712   {
       
   713     PSH_Dimension  dim = &globals->dimension[0];
       
   714 
       
   715 
       
   716     dim = &globals->dimension[0];
       
   717     if ( x_scale != dim->scale_mult  ||
       
   718          x_delta != dim->scale_delta )
       
   719     {
       
   720       dim->scale_mult  = x_scale;
       
   721       dim->scale_delta = x_delta;
       
   722 
       
   723       psh_globals_scale_widths( globals, 0 );
       
   724     }
       
   725 
       
   726     dim = &globals->dimension[1];
       
   727     if ( y_scale != dim->scale_mult  ||
       
   728          y_delta != dim->scale_delta )
       
   729     {
       
   730       dim->scale_mult  = y_scale;
       
   731       dim->scale_delta = y_delta;
       
   732 
       
   733       psh_globals_scale_widths( globals, 1 );
       
   734       psh_blues_scale_zones( &globals->blues, y_scale, y_delta );
       
   735     }
       
   736 
       
   737     return 0;
       
   738   }
       
   739 
       
   740 
       
   741   FT_LOCAL_DEF( void )
       
   742   psh_globals_funcs_init( PSH_Globals_FuncsRec*  funcs )
       
   743   {
       
   744     funcs->create    = psh_globals_new;
       
   745     funcs->set_scale = psh_globals_set_scale;
       
   746     funcs->destroy   = psh_globals_destroy;
       
   747   }
       
   748 
       
   749 
       
   750 /* END */