src/java.desktop/share/native/libfreetype/src/autofit/afloader.c
changeset 54876 da3834261f0c
parent 49234 3375a8039fde
equal deleted inserted replaced
54875:bcfedddcf4ce 54876:da3834261f0c
     1 /***************************************************************************/
     1 /****************************************************************************
     2 /*                                                                         */
     2  *
     3 /*  afloader.c                                                             */
     3  * afloader.c
     4 /*                                                                         */
     4  *
     5 /*    Auto-fitter glyph loading routines (body).                           */
     5  *   Auto-fitter glyph loading routines (body).
     6 /*                                                                         */
     6  *
     7 /*  Copyright 2003-2018 by                                                 */
     7  * Copyright (C) 2003-2019 by
     8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
     8  * David Turner, Robert Wilhelm, and Werner Lemberg.
     9 /*                                                                         */
     9  *
    10 /*  This file is part of the FreeType project, and may only be used,       */
    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      */
    11  * modified, and distributed under the terms of the FreeType project
    12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
    12  * license, LICENSE.TXT.  By continuing to use, modify, or distribute
    13 /*  this file you indicate that you have read the license and              */
    13  * this file you indicate that you have read the license and
    14 /*  understand and accept it fully.                                        */
    14  * understand and accept it fully.
    15 /*                                                                         */
    15  *
    16 /***************************************************************************/
    16  */
    17 
    17 
    18 
    18 
    19 #include "afglobal.h"
    19 #include "afglobal.h"
    20 #include "afloader.h"
    20 #include "afloader.h"
    21 #include "afhints.h"
    21 #include "afhints.h"
    22 #include "aferrors.h"
    22 #include "aferrors.h"
    23 #include "afmodule.h"
    23 #include "afmodule.h"
    24 #include "afpic.h"
       
    25 
    24 
    26 #include FT_INTERNAL_CALC_H
    25 #include FT_INTERNAL_CALC_H
    27 
    26 
    28 
    27 
    29   /* Initialize glyph loader. */
    28   /* Initialize glyph loader. */
   117       error = FT_ERR( Corrupted_Font_Header );
   116       error = FT_ERR( Corrupted_Font_Header );
   118       goto Exit;
   117       goto Exit;
   119     }
   118     }
   120 
   119 
   121     /*
   120     /*
   122      *  We depend on the writing system (script analyzers) to supply
   121      * We depend on the writing system (script analyzers) to supply
   123      *  standard widths for the script of the glyph we are looking at.  If
   122      * standard widths for the script of the glyph we are looking at.  If
   124      *  it can't deliver, stem darkening is disabled.
   123      * it can't deliver, stem darkening is disabled.
   125      */
   124      */
   126     writing_system_class =
   125     writing_system_class =
   127       AF_WRITING_SYSTEM_CLASSES_GET[style_metrics->style_class->writing_system];
   126       af_writing_system_classes[style_metrics->style_class->writing_system];
   128 
   127 
   129     if ( writing_system_class->style_metrics_getstdw )
   128     if ( writing_system_class->style_metrics_getstdw )
   130       writing_system_class->style_metrics_getstdw( style_metrics,
   129       writing_system_class->style_metrics_getstdw( style_metrics,
   131                                                    &stdHW,
   130                                                    &stdHW,
   132                                                    &stdVW );
   131                                                    &stdVW );
   172       globals->standard_horizontal_width = stdHW;
   171       globals->standard_horizontal_width = stdHW;
   173       globals->stem_darkening_for_ppem   = size_metrics->x_ppem;
   172       globals->stem_darkening_for_ppem   = size_metrics->x_ppem;
   174       globals->darken_y                  = af_fixedToInt( darken_y );
   173       globals->darken_y                  = af_fixedToInt( darken_y );
   175 
   174 
   176       /*
   175       /*
   177        *  Scale outlines down on the Y-axis to keep them inside their blue
   176        * Scale outlines down on the Y-axis to keep them inside their blue
   178        *  zones.  The stronger the emboldening, the stronger the downscaling
   177        * zones.  The stronger the emboldening, the stronger the downscaling
   179        *  (plus heuristical padding to prevent outlines still falling out
   178        * (plus heuristical padding to prevent outlines still falling out
   180        *  their zones due to rounding).
   179        * their zones due to rounding).
   181        *
   180        *
   182        *  Reason: `FT_Outline_Embolden' works by shifting the rightmost
   181        * Reason: `FT_Outline_Embolden' works by shifting the rightmost
   183        *  points of stems farther to the right, and topmost points farther
   182        * points of stems farther to the right, and topmost points farther
   184        *  up.  This positions points on the Y-axis outside their
   183        * up.  This positions points on the Y-axis outside their
   185        *  pre-computed blue zones and leads to distortion when applying the
   184        * pre-computed blue zones and leads to distortion when applying the
   186        *  hints in the code further below.  Code outside this emboldening
   185        * hints in the code further below.  Code outside this emboldening
   187        *  block doesn't know we are presenting it with modified outlines the
   186        * block doesn't know we are presenting it with modified outlines the
   188        *  analyzer didn't see!
   187        * analyzer didn't see!
   189        *
   188        *
   190        *  An unfortunate side effect of downscaling is that the emboldening
   189        * An unfortunate side effect of downscaling is that the emboldening
   191        *  effect is slightly decreased.  The loss becomes more pronounced
   190        * effect is slightly decreased.  The loss becomes more pronounced
   192        *  versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
   191        * versus the CFF driver at smaller sizes, e.g., at 9ppem and below.
   193        */
   192        */
   194       globals->scale_down_factor =
   193       globals->scale_down_factor =
   195         FT_DivFix( em_size - ( darken_by_font_units_y + af_intToFixed( 8 ) ),
   194         FT_DivFix( em_size - ( darken_by_font_units_y + af_intToFixed( 8 ) ),
   196                    em_size );
   195                    em_size );
   197     }
   196     }
   229     AF_ScalerRec           scaler;
   228     AF_ScalerRec           scaler;
   230     AF_StyleMetrics        style_metrics;
   229     AF_StyleMetrics        style_metrics;
   231     FT_UInt                style_options = AF_STYLE_NONE_DFLT;
   230     FT_UInt                style_options = AF_STYLE_NONE_DFLT;
   232     AF_StyleClass          style_class;
   231     AF_StyleClass          style_class;
   233     AF_WritingSystemClass  writing_system_class;
   232     AF_WritingSystemClass  writing_system_class;
   234 
       
   235 #ifdef FT_CONFIG_OPTION_PIC
       
   236     AF_FaceGlobals  globals = loader->globals;
       
   237 #endif
       
   238 
   233 
   239 
   234 
   240     if ( !size )
   235     if ( !size )
   241       return FT_THROW( Invalid_Size_Handle );
   236       return FT_THROW( Invalid_Size_Handle );
   242 
   237 
   280       }
   275       }
   281 #endif /* AF_CONFIG_OPTION_TT_SIZE_METRICS */
   276 #endif /* AF_CONFIG_OPTION_TT_SIZE_METRICS */
   282     }
   277     }
   283 
   278 
   284     /*
   279     /*
   285      *  TODO: This code currently doesn't support fractional advance widths,
   280      * TODO: This code currently doesn't support fractional advance widths,
   286      *  i.e., placing hinted glyphs at anything other than integer
   281      * i.e., placing hinted glyphs at anything other than integer
   287      *  x-positions.  This is only relevant for the warper code, which
   282      * x-positions.  This is only relevant for the warper code, which
   288      *  scales and shifts glyphs to optimize blackness of stems (hinting on
   283      * scales and shifts glyphs to optimize blackness of stems (hinting on
   289      *  the x-axis by nature places things on pixel integers, hinting on the
   284      * the x-axis by nature places things on pixel integers, hinting on the
   290      *  y-axis only, i.e., LIGHT mode, doesn't touch the x-axis).  The delta
   285      * y-axis only, i.e., LIGHT mode, doesn't touch the x-axis).  The delta
   291      *  values of the scaler would need to be adjusted.
   286      * values of the scaler would need to be adjusted.
   292      */
   287      */
   293     scaler.face    = face;
   288     scaler.face    = face;
   294     scaler.x_scale = size_internal->autohint_metrics.x_scale;
   289     scaler.x_scale = size_internal->autohint_metrics.x_scale;
   295     scaler.x_delta = 0;
   290     scaler.x_delta = 0;
   296     scaler.y_scale = size_internal->autohint_metrics.y_scale;
   291     scaler.y_scale = size_internal->autohint_metrics.y_scale;
   310     if ( load_flags & ( 1UL << 20 ) )
   305     if ( load_flags & ( 1UL << 20 ) )
   311       style_options = AF_STYLE_LTN2_DFLT;
   306       style_options = AF_STYLE_LTN2_DFLT;
   312 #endif
   307 #endif
   313 
   308 
   314     /*
   309     /*
   315      *  Glyphs (really code points) are assigned to scripts.  Script
   310      * Glyphs (really code points) are assigned to scripts.  Script
   316      *  analysis is done lazily: For each glyph that passes through here,
   311      * analysis is done lazily: For each glyph that passes through here,
   317      *  the corresponding script analyzer is called, but returns immediately
   312      * the corresponding script analyzer is called, but returns immediately
   318      *  if it has been run already.
   313      * if it has been run already.
   319      */
   314      */
   320     error = af_face_globals_get_metrics( loader->globals, glyph_index,
   315     error = af_face_globals_get_metrics( loader->globals, glyph_index,
   321                                          style_options, &style_metrics );
   316                                          style_options, &style_metrics );
   322     if ( error )
   317     if ( error )
   323       goto Exit;
   318       goto Exit;
   324 
   319 
   325     style_class          = style_metrics->style_class;
   320     style_class          = style_metrics->style_class;
   326     writing_system_class =
   321     writing_system_class =
   327       AF_WRITING_SYSTEM_CLASSES_GET[style_class->writing_system];
   322       af_writing_system_classes[style_class->writing_system];
   328 
   323 
   329     loader->metrics = style_metrics;
   324     loader->metrics = style_metrics;
   330 
   325 
   331     if ( writing_system_class->style_metrics_scale )
   326     if ( writing_system_class->style_metrics_scale )
   332       writing_system_class->style_metrics_scale( style_metrics, &scaler );
   327       writing_system_class->style_metrics_scale( style_metrics, &scaler );
   340       if ( error )
   335       if ( error )
   341         goto Exit;
   336         goto Exit;
   342     }
   337     }
   343 
   338 
   344     /*
   339     /*
   345      *  Do the main work of `af_loader_load_glyph'.  Note that we never have
   340      * Do the main work of `af_loader_load_glyph'.  Note that we never have
   346      *  to deal with composite glyphs as those get loaded into
   341      * to deal with composite glyphs as those get loaded into
   347      *  FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function.
   342      * FT_GLYPH_FORMAT_OUTLINE by the recursed `FT_Load_Glyph' function.
   348      *  In the rare cases where FT_LOAD_NO_RECURSE is set, it implies
   343      * In the rare cases where FT_LOAD_NO_RECURSE is set, it implies
   349      *  FT_LOAD_NO_SCALE and as such the auto-hinter is never called.
   344      * FT_LOAD_NO_SCALE and as such the auto-hinter is never called.
   350      */
   345      */
   351     load_flags |=  FT_LOAD_NO_SCALE         |
   346     load_flags |=  FT_LOAD_NO_SCALE         |
   352                    FT_LOAD_IGNORE_TRANSFORM |
   347                    FT_LOAD_IGNORE_TRANSFORM |
   353                    FT_LOAD_LINEAR_DESIGN;
   348                    FT_LOAD_LINEAR_DESIGN;
   354     load_flags &= ~FT_LOAD_RENDER;
   349     load_flags &= ~FT_LOAD_RENDER;
   356     error = FT_Load_Glyph( face, glyph_index, load_flags );
   351     error = FT_Load_Glyph( face, glyph_index, load_flags );
   357     if ( error )
   352     if ( error )
   358       goto Exit;
   353       goto Exit;
   359 
   354 
   360     /*
   355     /*
   361      *  Apply stem darkening (emboldening) here before hints are applied to
   356      * Apply stem darkening (emboldening) here before hints are applied to
   362      *  the outline.  Glyphs are scaled down proportionally to the
   357      * the outline.  Glyphs are scaled down proportionally to the
   363      *  emboldening so that curve points don't fall outside their
   358      * emboldening so that curve points don't fall outside their
   364      *  precomputed blue zones.
   359      * precomputed blue zones.
   365      *
   360      *
   366      *  Any emboldening done by the font driver (e.g., the CFF driver)
   361      * Any emboldening done by the font driver (e.g., the CFF driver)
   367      *  doesn't reach here because the autohinter loads the unprocessed
   362      * doesn't reach here because the autohinter loads the unprocessed
   368      *  glyphs in font units for analysis (functions `af_*_metrics_init_*')
   363      * glyphs in font units for analysis (functions `af_*_metrics_init_*')
   369      *  and then above to prepare it for the rasterizers by itself,
   364      * and then above to prepare it for the rasterizers by itself,
   370      *  independently of the font driver.  So emboldening must be done here,
   365      * independently of the font driver.  So emboldening must be done here,
   371      *  within the autohinter.
   366      * within the autohinter.
   372      *
   367      *
   373      *  All glyphs to be autohinted pass through here one by one.  The
   368      * All glyphs to be autohinted pass through here one by one.  The
   374      *  standard widths can therefore change from one glyph to the next,
   369      * standard widths can therefore change from one glyph to the next,
   375      *  depending on what script a glyph is assigned to (each script has its
   370      * depending on what script a glyph is assigned to (each script has its
   376      *  own set of standard widths and other metrics).  The darkening amount
   371      * own set of standard widths and other metrics).  The darkening amount
   377      *  must therefore be recomputed for each size and
   372      * must therefore be recomputed for each size and
   378      *  `standard_{vertical,horizontal}_width' change.
   373      * `standard_{vertical,horizontal}_width' change.
   379      *
   374      *
   380      *  Ignore errors and carry on without emboldening.
   375      * Ignore errors and carry on without emboldening.
   381      *
   376      *
   382      */
   377      */
   383 
   378 
   384     /* stem darkening only works well in `light' mode */
   379     /* stem darkening only works well in `light' mode */
   385     if ( scaler.render_mode == FT_RENDER_MODE_LIGHT    &&
   380     if ( scaler.render_mode == FT_RENDER_MODE_LIGHT    &&
   424         goto Hint_Metrics;
   419         goto Hint_Metrics;
   425 
   420 
   426       /* now load the slot image into the auto-outline */
   421       /* now load the slot image into the auto-outline */
   427       /* and run the automatic hinting process         */
   422       /* and run the automatic hinting process         */
   428       if ( writing_system_class->style_hints_apply )
   423       if ( writing_system_class->style_hints_apply )
   429         writing_system_class->style_hints_apply( glyph_index,
   424       {
   430                                                  hints,
   425         error = writing_system_class->style_hints_apply(
   431                                                  &gloader->base.outline,
   426                   glyph_index,
   432                                                  style_metrics );
   427                   hints,
       
   428                   &gloader->base.outline,
       
   429                   style_metrics );
       
   430         if ( error )
       
   431           goto Exit;
       
   432       }
   433 
   433 
   434       /* we now need to adjust the metrics according to the change in */
   434       /* we now need to adjust the metrics according to the change in */
   435       /* width/positioning that occurred during the hinting process   */
   435       /* width/positioning that occurred during the hinting process   */
   436       if ( scaler.render_mode != FT_RENDER_MODE_LIGHT )
   436       if ( scaler.render_mode != FT_RENDER_MODE_LIGHT )
   437       {
   437       {
   438         FT_Pos  old_rsb, old_lsb, new_lsb;
       
   439         FT_Pos  pp1x_uh, pp2x_uh;
       
   440 
       
   441         AF_AxisHints  axis  = &hints->axis[AF_DIMENSION_HORZ];
   438         AF_AxisHints  axis  = &hints->axis[AF_DIMENSION_HORZ];
   442         AF_Edge       edge1 = axis->edges;         /* leftmost edge  */
       
   443         AF_Edge       edge2 = edge1 +
       
   444                               axis->num_edges - 1; /* rightmost edge */
       
   445 
   439 
   446 
   440 
   447         if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
   441         if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
   448         {
   442         {
   449           old_rsb = loader->pp2.x - edge2->opos;
   443           AF_Edge  edge1 = axis->edges;         /* leftmost edge  */
       
   444           AF_Edge  edge2 = edge1 +
       
   445                            axis->num_edges - 1; /* rightmost edge */
       
   446 
       
   447           FT_Pos  old_rsb = loader->pp2.x - edge2->opos;
   450           /* loader->pp1.x is always zero at this point of time */
   448           /* loader->pp1.x is always zero at this point of time */
   451           old_lsb = edge1->opos /* - loader->pp1.x */;
   449           FT_Pos  old_lsb = edge1->opos;     /* - loader->pp1.x */
   452           new_lsb = edge1->pos;
   450           FT_Pos  new_lsb = edge1->pos;
   453 
   451 
   454           /* remember unhinted values to later account */
   452           /* remember unhinted values to later account */
   455           /* for rounding errors                       */
   453           /* for rounding errors                       */
   456           pp1x_uh = new_lsb    - old_lsb;
   454           FT_Pos  pp1x_uh = new_lsb    - old_lsb;
   457           pp2x_uh = edge2->pos + old_rsb;
   455           FT_Pos  pp2x_uh = edge2->pos + old_rsb;
       
   456 
   458 
   457 
   459           /* prefer too much space over too little space */
   458           /* prefer too much space over too little space */
   460           /* for very small sizes                        */
   459           /* for very small sizes                        */
   461 
   460 
   462           if ( old_lsb < 24 )
   461           if ( old_lsb < 24 )