shithub: freetype+ttf2subf

ref: c06eb3b73a07f18e24634bd96d3ef791bc43a3dc
dir: /src/type1/t1objs.c/

View raw version
/*******************************************************************
 *
 *  t1objs.c                                                     1.0
 *
 *    Type1 Objects manager.        
 *
 *  Copyright 1996-1998 by
 *  David Turner, Robert Wilhelm, and Werner Lemberg.
 *
 *  This file is part of the FreeType project, and may only be used
 *  modified and distributed under the terms of the FreeType project
 *  license, LICENSE.TXT.  By continuing to use, modify, or distribute
 *  this file you indicate that you have read the license and
 *  understand and accept it fully.
 *
 ******************************************************************/

#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftstream.h>

#include <t1gload.h>
#include <t1load.h>
#include <t1afm.h>

#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
#include <t1hinter.h>
#endif

#include <freetype/internal/psnames.h>

/* Required by tracing mode */
#undef   FT_COMPONENT
#define  FT_COMPONENT  trace_t1objs

/*******************************************************************
 *                                                                 *
 *                         SIZE  FUNCTIONS                         *
 *                                                                 *
 *                                                                 *
 *******************************************************************/

/*******************************************************************
 *
 * <Function>  T1_Done_Size
 *
 * <Description>
 *    The TrueDoc instance object destructor. Used to discard
 *    a given instance object..
 *
 * <Input>
 *    instance   :: handle to the target instance object
 *
 * <Return>
 *    TrueDoc error code. 0 means success
 *
 ******************************************************************/

  LOCAL_FUNC
  void  T1_Done_Size( T1_Size  size )
  {
    if (size)
    {
#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
      T1_Done_Size_Hinter( size );
#endif
      size->valid = 0;
    }
  }


/*******************************************************************
 *
 *  <Function> T1_Init_Size
 *
 *  <Description>
 *     The instance object constructor
 *
 *  <Input>
 *     instance  : handle to new instance object
 *     face      : pointer to parent face object
 *
 *  <Return>
 *     TrueDoc error code. 0 means success.
 *
 ******************************************************************/

  LOCAL_DEF
  T1_Error  T1_Init_Size( T1_Size  size )
  {
    T1_Error    error;
      
    size->valid = 0;
    
#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
    error = T1_New_Size_Hinter( size );
    return error;
#else
    (void)error;
    return T1_Err_Ok;
#endif
  }


/*******************************************************************
 *
 *  <Function> T1_Reset_Size
 *
 *  <Description>
 *     Resets an instance to a new pointsize/transform.
 *     This function is in charge of resetting the blue zones,
 *     As well as the stem snap tables for a given size..
 *
 *  <Input>
 *     instance   the instance object to destroy
 *
 *  <Output>
 *     Error code.
 *
 ******************************************************************/
 
  LOCAL_FUNC
  T1_Error  T1_Reset_Size( T1_Size  size )
  {
#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
    return T1_Reset_Size_Hinter( size );
#else
    (void)size;
    return 0;
#endif
  }


/*******************************************************************
 *                                                                 *
 *                         FACE  FUNCTIONS                         *
 *                                                                 *
 *                                                                 *
 *******************************************************************/

/*******************************************************************
 *
 *  <Function> T1_Done_Face
 *
 *  <Description>
 *     The face object destructor.
 *
 *  <Input>
 *     face  :: typeless pointer to the face object to destroy
 *
 *  <Return>
 *     Error code.                       
 *
 ******************************************************************/

  LOCAL_FUNC
  void  T1_Done_Face( T1_Face  face )
  {
    FT_Memory  memory;
    T1_Font*   type1 = &face->type1;

    if (face)
    {
      memory = face->root.memory;
      
      /* release font info strings */      
      {
        T1_FontInfo*  info = &type1->font_info;
        
        FREE( info->version );
        FREE( info->notice );
        FREE( info->full_name );
        FREE( info->family_name );
        FREE( info->weight );
      }

      /* release top dictionary */      
      FREE( type1->charstrings_len );
      FREE( type1->charstrings );
      FREE( type1->glyph_names );

      FREE( type1->subrs );
      FREE( type1->subrs_len );
      
      FREE( type1->subrs_block );
      FREE( type1->charstrings_block );
      FREE( type1->glyph_names_block );

      FREE( type1->encoding.char_index );
      FREE( type1->font_name );
      
#ifndef T1_CONFIG_OPTION_NO_AFM
      /* release afm data if present */
      if ( face->afm_data)
        T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
#endif

      /* release unicode map, if any */
      FREE( face->unicode_map.maps );
      face->unicode_map.num_maps = 0;

      face->root.family_name = 0;
      face->root.style_name  = 0;
    }
  }

/*******************************************************************
 *
 *  <Function>  T1_Init_Face
 *
 *  <Description>
 *     The face object constructor.
 *
 *  <Input>
 *     face  ::  face record to build
 *     Input ::  input stream where to load font data
 *
 *  <Return>
 *     Error code.
 *
 ******************************************************************/

  LOCAL_FUNC
  T1_Error  T1_Init_Face( FT_Stream      stream,
                          T1_Face        face,
                          FT_Int         face_index,
                          FT_Int         num_params,
                          FT_Parameter*  params )
  {
    T1_Tokenizer        tokenizer;
    T1_Error            error;
    PSNames_Interface*  psnames;

    UNUSED(num_params);
    UNUSED(params);
    UNUSED(face_index);
    UNUSED(face);

    face->root.num_faces = 1;

    psnames = (PSNames_Interface*)face->psnames;
    if (!psnames)
    {
      /* look-up the PSNames driver */
      FT_Driver  psnames_driver;
      
      psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" );
      if (psnames_driver)
        face->psnames = (PSNames_Interface*)
                            (psnames_driver->interface.format_interface);
    }

    /* open the tokenizer, this will also check the font format */
    error = New_Tokenizer( stream, &tokenizer );
    if (error) goto Fail;

    /* if we just wanted to check the format, leave successfully now */
    if (face_index < 0)
      goto Leave;

    /* check the face index */
    if ( face_index != 0 )
    {
      FT_ERROR(( "T1.Init_Face : invalid face index\n" ));
      error = T1_Err_Invalid_Argument;
      goto Leave;
    }

    /* Now, load the font program into the face object */
    {
      T1_Parser  parser;

      Init_T1_Parser( &parser, face, tokenizer );
      error = Parse_T1_FontProgram( &parser );
      if (error) goto Leave;

      /* Init the face object fields */
      /* Now set up root face fields */
      {
        FT_Face  root  = (FT_Face)&face->root;
        T1_Font* type1 = &face->type1;
        
        root->num_glyphs   = type1->num_glyphs;
        root->num_charmaps = 1;
  
        root->face_index = face_index;
        root->face_flags = FT_FACE_FLAG_SCALABLE;
        
        root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
                              
        if ( type1->font_info.is_fixed_pitch )
          root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

        /* XXX : TO DO - add kerning with .afm support */

        /* get style name - be careful, some broken fonts only */
        /* have a /FontName dictionary entry .. !!             */
        root->family_name = type1->font_info.family_name;
        if (root->family_name)
        {
          char*  full   = type1->font_info.full_name;
          char*  family = root->family_name;
          
          while ( *family && *full == *family )
          {
            family++;
            full++;
          }
          
          root->style_name = ( *full == ' ' ? full+1 : "Regular" );
        }
        else
        {
          /* do we have a /FontName ?? */
          if (type1->font_name)
          {
            root->family_name = type1->font_name;
            root->style_name  = "Regular";
          }
        }
  
        /* no embedded bitmap support */
        root->num_fixed_sizes = 0;
        root->available_sizes = 0;
  
        root->bbox         = type1->font_bbox;
        root->units_per_EM = 1000;
        root->ascender     =  (T1_Short)type1->font_bbox.yMax;
        root->descender    = -(T1_Short)type1->font_bbox.yMin;
        root->height       = ((root->ascender + root->descender)*12)/10;
  
        /* now compute the maximum advance width */

        root->max_advance_width = type1->private_dict.standard_width;

        /* compute max advance width for proportional fonts */
        if (!type1->font_info.is_fixed_pitch)
        {
          T1_Int  max_advance;

          error = T1_Compute_Max_Advance( face, &max_advance );

          /* in case of error, keep the standard width */
          if (!error)
            root->max_advance_width = max_advance;
          else
            error = 0;   /* clear error */
        }

        root->max_advance_height = root->height;
        
        root->underline_position  = type1->font_info.underline_position;
        root->underline_thickness = type1->font_info.underline_thickness;
  
        root->max_points   = 0;
        root->max_contours = 0;
      }
    }

    /* charmap support - synthetize unicode charmap when possible */
    {
      FT_Face      root    = &face->root;
      FT_CharMap   charmap = face->charmaprecs;

      /* synthesize a Unicode charmap if there is support in the "psnames" */
      /* module..                                                          */
      if (face->psnames)
      {
        PSNames_Interface*  psnames = (PSNames_Interface*)face->psnames;
        if (psnames->unicode_value)
        {
          error = psnames->build_unicodes( root->memory,
                                           face->type1.num_glyphs,
                                           (const char**)face->type1.glyph_names,
                                           &face->unicode_map );
          if (!error)
          {
            root->charmap        = charmap;
            charmap->face        = (FT_Face)face;
            charmap->encoding    = ft_encoding_unicode;
            charmap->platform_id = 3;
            charmap->encoding_id = 1;
            charmap++;
          }
          
          /* simply clear the error in case of failure (which really) */
          /* means that out of memory or no unicode glyph names       */
          error = 0;
        }
      }

      /* now, support either the standard, expert, or custom encodings */
      charmap->face        = (FT_Face)face;
      charmap->platform_id = 7;  /* a new platform id for Adobe fonts ?? */
      
      switch (face->type1.encoding_type)
      {
        case t1_encoding_standard:
          charmap->encoding    = ft_encoding_adobe_standard;
          charmap->encoding_id = 0;
          break;
        
        case t1_encoding_expert:
          charmap->encoding    = ft_encoding_adobe_expert;
          charmap->encoding_id = 1;
          break;
        
        default:
          charmap->encoding    = ft_encoding_adobe_custom;
          charmap->encoding_id = 2;
          break;
      }
      
      root->charmaps = face->charmaps;
      root->num_charmaps = charmap - face->charmaprecs + 1;
      face->charmaps[0] = &face->charmaprecs[0];
      face->charmaps[1] = &face->charmaprecs[1];
    }

  Leave:
    Done_Tokenizer( tokenizer );

  Fail:
    return error;
  }


/*******************************************************************
 *
 *  Function    :  Glyph_Destroy
 *
 *  Description :  The glyph object destructor.
 *
 *  Input  :  _glyph  typeless pointer to the glyph record to destroy
 *
 *  Output :  Error code.                       
 *
 ******************************************************************/

  LOCAL_FUNC
  void  T1_Done_GlyphSlot( T1_GlyphSlot  glyph )
  {
    FT_Memory  memory  = glyph->root.face->memory;
    FT_Library library = glyph->root.face->driver->library;

#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
    T1_Done_Glyph_Hinter( glyph );
#endif
	/* the bitmaps are created on demand */
	FREE( glyph->root.bitmap.buffer );
    FT_Outline_Done( library, &glyph->root.outline );
    return;
  }


/*******************************************************************
 *
 *  Function    :  Glyph_Create
 *
 *  Description :  The glyph object constructor.
 *
 *  Input  :  glyph   glyph record to build.
 *            face    the glyph's parent face.              
 *
 *  Output :  Error code.
 *
 ******************************************************************/

  LOCAL_FUNC
  T1_Error  T1_Init_GlyphSlot( T1_GlyphSlot  glyph )
  {
    FT_Library  library = glyph->root.face->driver->library;
    T1_Error    error;

    glyph->max_points         = 0;
    glyph->max_contours       = 0;
    glyph->root.bitmap.buffer = 0;

    error = FT_Outline_New( library, 0, 0, &glyph->root.outline );
    if (error) return error;

#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
    error = T1_New_Glyph_Hinter( glyph );
    if (error)
      FT_Outline_Done( library, &glyph->root.outline );
#endif

    return error;
  }


/*******************************************************************
 *
 *  <Function>  T1_Init_Driver
 *
 *  <Description>
 *     Initialise a given Type 1 driver object
 *
 *  <Input>
 *     driver ::  handle to target driver object
 *
 *  <Return>
 *     Error code.
 *
 ******************************************************************/

  LOCAL_FUNC
  T1_Error  T1_Init_Driver( T1_Driver  driver )
  {
    UNUSED(driver);
    return T1_Err_Ok;
  }



/*******************************************************************
 *
 *  <Function> T1_Done_Driver
 *
 *  <Description>
 *     finalise a given Type 1 driver
 *
 *  <Input>
 *     driver  :: handle to target Type 1 driver
 *
 ******************************************************************/

  LOCAL_DEF
  void  T1_Done_Driver( T1_Driver  driver )
  {
    UNUSED(driver);
  }


/* END */