예제 #1
0
T1_Face_Init( FT_Stream      stream,
              FT_Face        t1face,          /* T1_Face */
              FT_Int         face_index,
              FT_Int         num_params,
              FT_Parameter*  params )
{
    T1_Face             face = (T1_Face)t1face;
    FT_Error            error;
    FT_Service_PsCMaps  psnames;
    PSAux_Service       psaux;
    T1_Font             type1 = &face->type1;
    PS_FontInfo         info = &type1->font_info;

    FT_UNUSED( num_params );
    FT_UNUSED( params );
    FT_UNUSED( stream );


    face->root.num_faces = 1;

    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
    face->psnames = psnames;

    face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
                                           "psaux" );
    psaux = (PSAux_Service)face->psaux;
    if ( !psaux )
    {
        FT_ERROR(( "T1_Face_Init: cannot access `psaux' module\n" ));
        error = FT_THROW( Missing_Module );
        goto Exit;
    }

    face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
                     "pshinter" );

    FT_TRACE2(( "Type 1 driver\n" ));

    /* open the tokenizer; this will also check the font format */
    error = T1_Open_Face( face );
    if ( error )
        goto Exit;

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

    /* check the face index */
    if ( face_index > 0 )
    {
        FT_ERROR(( "T1_Face_Init: invalid face index\n" ));
        error = FT_THROW( Invalid_Argument );
        goto Exit;
    }

    /* now load the font program into the face object */

    /* initialize the face object fields */

    /* set up root face fields */
    {
        FT_Face  root = (FT_Face)&face->root;


        root->num_glyphs = type1->num_glyphs;
        root->face_index = 0;

        root->face_flags |= FT_FACE_FLAG_SCALABLE    |
                            FT_FACE_FLAG_HORIZONTAL  |
                            FT_FACE_FLAG_GLYPH_NAMES |
                            FT_FACE_FLAG_HINTER;

        if ( info->is_fixed_pitch )
            root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

        if ( face->blend )
            root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;

        /* XXX: TODO -- add kerning with .afm support */


        /* The following code to extract the family and the style is very   */
        /* simplistic and might get some things wrong.  For a full-featured */
        /* algorithm you might have a look at the whitepaper given at       */
        /*                                                                  */
        /*   http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */

        /* get style name -- be careful, some broken fonts only */
        /* have a `/FontName' dictionary entry!                 */
        root->family_name = info->family_name;
        root->style_name  = NULL;

        if ( root->family_name )
        {
            char*  full   = info->full_name;
            char*  family = root->family_name;


            if ( full )
            {
                FT_Bool  the_same = TRUE;


                while ( *full )
                {
                    if ( *full == *family )
                    {
                        family++;
                        full++;
                    }
                    else
                    {
                        if ( *full == ' ' || *full == '-' )
                            full++;
                        else if ( *family == ' ' || *family == '-' )
                            family++;
                        else
                        {
                            the_same = FALSE;

                            if ( !*family )
                                root->style_name = full;
                            break;
                        }
                    }
                }

                if ( the_same )
                    root->style_name = (char *)"Regular";
            }
        }
        else
        {
            /* do we have a `/FontName'? */
            if ( type1->font_name )
                root->family_name = type1->font_name;
        }

        if ( !root->style_name )
        {
            if ( info->weight )
                root->style_name = info->weight;
            else
                /* assume `Regular' style because we don't know better */
                root->style_name = (char *)"Regular";
        }

        /* compute style flags */
        root->style_flags = 0;
        if ( info->italic_angle )
            root->style_flags |= FT_STYLE_FLAG_ITALIC;
        if ( info->weight )
        {
            if ( !ft_strcmp( info->weight, "Bold"  ) ||
                    !ft_strcmp( info->weight, "Black" ) )
                root->style_flags |= FT_STYLE_FLAG_BOLD;
        }

        /* no embedded bitmap support */
        root->num_fixed_sizes = 0;
        root->available_sizes = 0;

        root->bbox.xMin =   type1->font_bbox.xMin            >> 16;
        root->bbox.yMin =   type1->font_bbox.yMin            >> 16;
        /* no `U' suffix here to 0xFFFF! */
        root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16;
        root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16;

        /* Set units_per_EM if we didn't set it in t1_parse_font_matrix. */
        if ( !root->units_per_EM )
            root->units_per_EM = 1000;

        root->ascender  = (FT_Short)( root->bbox.yMax );
        root->descender = (FT_Short)( root->bbox.yMin );

        root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 );
        if ( root->height < root->ascender - root->descender )
            root->height = (FT_Short)( root->ascender - root->descender );

        /* now compute the maximum advance width */
        root->max_advance_width =
            (FT_Short)( root->bbox.xMax );
        {
            FT_Pos  max_advance;


            error = T1_Compute_Max_Advance( face, &max_advance );

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

        root->max_advance_height = root->height;

        root->underline_position  = (FT_Short)info->underline_position;
        root->underline_thickness = (FT_Short)info->underline_thickness;
    }

    {
        FT_Face  root = &face->root;


        if ( psnames )
        {
            FT_CharMapRec    charmap;
            T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
            FT_CMap_Class    clazz;


            charmap.face = root;

            /* first of all, try to synthesize a Unicode charmap */
            charmap.platform_id = TT_PLATFORM_MICROSOFT;
            charmap.encoding_id = TT_MS_ID_UNICODE_CS;
            charmap.encoding    = FT_ENCODING_UNICODE;

            error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
            if ( error                                      &&
                    FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
                goto Exit;
            error = FT_Err_Ok;

            /* now, generate an Adobe Standard encoding when appropriate */
            charmap.platform_id = TT_PLATFORM_ADOBE;
            clazz               = NULL;

            switch ( type1->encoding_type )
            {
            case T1_ENCODING_TYPE_STANDARD:
                charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
                charmap.encoding_id = TT_ADOBE_ID_STANDARD;
                clazz               = cmap_classes->standard;
                break;

            case T1_ENCODING_TYPE_EXPERT:
                charmap.encoding    = FT_ENCODING_ADOBE_EXPERT;
                charmap.encoding_id = TT_ADOBE_ID_EXPERT;
                clazz               = cmap_classes->expert;
                break;

            case T1_ENCODING_TYPE_ARRAY:
                charmap.encoding    = FT_ENCODING_ADOBE_CUSTOM;
                charmap.encoding_id = TT_ADOBE_ID_CUSTOM;
                clazz               = cmap_classes->custom;
                break;

            case T1_ENCODING_TYPE_ISOLATIN1:
                charmap.encoding    = FT_ENCODING_ADOBE_LATIN_1;
                charmap.encoding_id = TT_ADOBE_ID_LATIN_1;
                clazz               = cmap_classes->unicode;
                break;

            default:
                ;
            }

            if ( clazz )
                error = FT_CMap_New( clazz, NULL, &charmap, NULL );

#if 0
            /* Select default charmap */
            if (root->num_charmaps)
                root->charmap = root->charmaps[0];
#endif
        }
    }

Exit:
    return error;
}
예제 #2
0
  pfr_face_init( FT_Stream      stream,
                 FT_Face        pfrface,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    PFR_Face  face = (PFR_Face)pfrface;
    FT_Error  error;

    FT_UNUSED( num_params );
    FT_UNUSED( params );


    /* load the header and check it */
    error = pfr_header_load( &face->header, stream );
    if ( error )
      goto Exit;

    if ( !pfr_header_check( &face->header ) )
    {
      FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" ));
      error = PFR_Err_Unknown_File_Format;
      goto Exit;
    }

    /* check face index */
    {
      FT_UInt  num_faces;


      error = pfr_log_font_count( stream,
                                  face->header.log_dir_offset,
                                  &num_faces );
      if ( error )
        goto Exit;

      pfrface->num_faces = num_faces;
    }

    if ( face_index < 0 )
      goto Exit;

    if ( face_index >= pfrface->num_faces )
    {
      FT_ERROR(( "pfr_face_init: invalid face index\n" ));
      error = PFR_Err_Invalid_Argument;
      goto Exit;
    }

    /* load the face */
    error = pfr_log_font_load(
               &face->log_font, stream, face_index,
               face->header.log_dir_offset,
               FT_BOOL( face->header.phy_font_max_size_high != 0 ) );
    if ( error )
      goto Exit;

    /* now load the physical font descriptor */
    error = pfr_phy_font_load( &face->phy_font, stream,
                               face->log_font.phys_offset,
                               face->log_font.phys_size );
    if ( error )
      goto Exit;

    /* now, set-up all root face fields */
    {
      PFR_PhyFont  phy_font = &face->phy_font;


      pfrface->face_index = face_index;
      pfrface->num_glyphs = phy_font->num_chars;
      pfrface->face_flags = FT_FACE_FLAG_SCALABLE;

      if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 )
        pfrface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

      if ( phy_font->flags & PFR_PHY_VERTICAL )
        pfrface->face_flags |= FT_FACE_FLAG_VERTICAL;
      else
        pfrface->face_flags |= FT_FACE_FLAG_HORIZONTAL;

      if ( phy_font->num_strikes > 0 )
        pfrface->face_flags |= FT_FACE_FLAG_FIXED_SIZES;

      if ( phy_font->num_kern_pairs > 0 )
        pfrface->face_flags |= FT_FACE_FLAG_KERNING;

      /* If no family name was found in the "undocumented" auxiliary
       * data, use the font ID instead.  This sucks but is better than
       * nothing.
       */
      pfrface->family_name = phy_font->family_name;
      if ( pfrface->family_name == NULL )
        pfrface->family_name = phy_font->font_id;

      /* note that the style name can be NULL in certain PFR fonts,
       * probably meaning "Regular"
       */
      pfrface->style_name = phy_font->style_name;

      pfrface->num_fixed_sizes = 0;
      pfrface->available_sizes = 0;

      pfrface->bbox         = phy_font->bbox;
      pfrface->units_per_EM = (FT_UShort)phy_font->outline_resolution;
      pfrface->ascender     = (FT_Short) phy_font->bbox.yMax;
      pfrface->descender    = (FT_Short) phy_font->bbox.yMin;
      pfrface->height       = (FT_Short)(
        ( ( pfrface->ascender - pfrface->descender ) * 12 ) / 10 );

      if ( phy_font->num_strikes > 0 )
      {
        FT_UInt          n, count = phy_font->num_strikes;
        FT_Bitmap_Size*  size;
        PFR_Strike       strike;
        FT_Memory        memory = pfrface->stream->memory;
         
         
        if ( FT_NEW_ARRAY( pfrface->available_sizes, count ) )
          goto Exit;
         
        size   = pfrface->available_sizes;
        strike = phy_font->strikes;
        for ( n = 0; n < count; n++, size++, strike++ )
        {
          size->height = (FT_UShort)strike->y_ppm;
          size->width  = (FT_UShort)strike->x_ppm;
        }
        pfrface->num_fixed_sizes = count;
      }

      /* now compute maximum advance width */
      if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 )
        pfrface->max_advance_width = (FT_Short)phy_font->standard_advance;
      else
      {
        FT_Int    max = 0;
        FT_UInt   count = phy_font->num_chars;
        PFR_Char  gchar = phy_font->chars;


        for ( ; count > 0; count--, gchar++ )
        {
          if ( max < gchar->advance )
            max = gchar->advance;
        }

        pfrface->max_advance_width = (FT_Short)max;
      }

      pfrface->max_advance_height = pfrface->height;

      pfrface->underline_position  = (FT_Short)( -pfrface->units_per_EM / 10 );
      pfrface->underline_thickness = (FT_Short)(  pfrface->units_per_EM / 30 );

      /* create charmap */
      {
        FT_CharMapRec  charmap;


        charmap.face        = pfrface;
        charmap.platform_id = 3;
        charmap.encoding_id = 1;
        charmap.encoding    = FT_ENCODING_UNICODE;

        FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL );

#if 0
        /* Select default charmap */
        if ( pfrface->num_charmaps )
          pfrface->charmap = pfrface->charmaps[0];
#endif
      }

      /* check whether we've loaded any kerning pairs */
      if ( phy_font->num_kern_pairs )
        pfrface->face_flags |= FT_FACE_FLAG_KERNING;
    }

  Exit:
    return error;
  }
예제 #3
0
  cff_face_init( FT_Stream      stream,
                 FT_Face        cffface,        /* CFF_Face */
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    CFF_Face            face        = (CFF_Face)cffface;
    FT_Error            error;
    SFNT_Service        sfnt;
    FT_Service_PsCMaps  psnames;
    PSHinter_Service    pshinter;
    FT_Bool             pure_cff    = 1;
    FT_Bool             sfnt_format = 0;
    FT_Library          library     = cffface->driver->root.library;


    sfnt = (SFNT_Service)FT_Get_Module_Interface(
             library, "sfnt" );
    if ( !sfnt )
    {
      FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" ));
      error = FT_THROW( Missing_Module );
      goto Exit;
    }

    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );

    pshinter = (PSHinter_Service)FT_Get_Module_Interface(
                 library, "pshinter" );

    FT_TRACE2(( "CFF driver\n" ));

    /* create input stream from resource */
    if ( FT_STREAM_SEEK( 0 ) )
      goto Exit;

    /* check whether we have a valid OpenType file */
    error = sfnt->init_face( stream, face, face_index, num_params, params );
    if ( !error )
    {
      if ( face->format_tag != TTAG_OTTO )  /* `OTTO'; OpenType/CFF font */
      {
        FT_TRACE2(( "  not an OpenType/CFF font\n" ));
        error = FT_THROW( Unknown_File_Format );
        goto Exit;
      }

      /* if we are performing a simple font format check, exit immediately */
      if ( face_index < 0 )
        return FT_Err_Ok;

      sfnt_format = 1;

      /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
      /* font; in the latter case it doesn't have a `head' table         */
      error = face->goto_table( face, TTAG_head, stream, 0 );
      if ( !error )
      {
        pure_cff = 0;

        /* load font directory */
        error = sfnt->load_face( stream, face, face_index,
                                 num_params, params );
        if ( error )
          goto Exit;
      }
      else
      {
        /* load the `cmap' table explicitly */
        error = sfnt->load_cmap( face, stream );
        if ( error )
          goto Exit;
      }

      /* now load the CFF part of the file */
      error = face->goto_table( face, TTAG_CFF, stream, 0 );
      if ( error )
        goto Exit;
    }
    else
    {
      /* rewind to start of file; we are going to load a pure-CFF font */
      if ( FT_STREAM_SEEK( 0 ) )
        goto Exit;
      error = FT_Err_Ok;
    }

    /* now load and parse the CFF table in the file */
    {
      CFF_Font         cff = NULL;
      CFF_FontRecDict  dict;
      FT_Memory        memory = cffface->memory;
      FT_Int32         flags;
      FT_UInt          i;


      if ( FT_NEW( cff ) )
        goto Exit;

      face->extra.data = cff;
      error = cff_font_load( library, stream, face_index, cff, pure_cff );
      if ( error )
        goto Exit;

      cff->pshinter = pshinter;
      cff->psnames  = psnames;

      cffface->face_index = face_index;

      /* Complement the root flags with some interesting information. */
      /* Note that this is only necessary for pure CFF and CEF fonts; */
      /* SFNT based fonts use the `name' table instead.               */

      cffface->num_glyphs = cff->num_glyphs;

      dict = &cff->top_font.font_dict;

      /* we need the `PSNames' module for CFF and CEF formats */
      /* which aren't CID-keyed                               */
      if ( dict->cid_registry == 0xFFFFU && !psnames )
      {
        FT_ERROR(( "cff_face_init:"
                   " cannot open CFF & CEF fonts\n"
                   "              "
                   " without the `PSNames' module\n" ));
        error = FT_THROW( Missing_Module );
        goto Exit;
      }

#ifdef FT_DEBUG_LEVEL_TRACE
      {
        FT_UInt     idx;
        FT_String*  s;


        FT_TRACE4(( "SIDs\n" ));

        /* dump string index, including default strings for convenience */
        for ( idx = 0; idx < cff->num_strings + 390; idx++ )
        {
          s = cff_index_get_sid_string( cff, idx );
          if ( s )
            FT_TRACE4(("  %5d %s\n", idx, s ));
        }
      }
#endif /* FT_DEBUG_LEVEL_TRACE */

      if ( !dict->has_font_matrix )
        dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;

      /* Normalize the font matrix so that `matrix->xx' is 1; the */
      /* scaling is done with `units_per_em' then (at this point, */
      /* it already contains the scaling factor, but without      */
      /* normalization of the matrix).                            */
      /*                                                          */
      /* Note that the offsets must be expressed in integer font  */
      /* units.                                                   */

      {
        FT_Matrix*  matrix = &dict->font_matrix;
        FT_Vector*  offset = &dict->font_offset;
        FT_ULong*   upm    = &dict->units_per_em;
        FT_Fixed    temp   = FT_ABS( matrix->yy );


        if ( temp != 0x10000L )
        {
          *upm = FT_DivFix( *upm, temp );

          matrix->xx = FT_DivFix( matrix->xx, temp );
          matrix->yx = FT_DivFix( matrix->yx, temp );
          matrix->xy = FT_DivFix( matrix->xy, temp );
          matrix->yy = FT_DivFix( matrix->yy, temp );
          offset->x  = FT_DivFix( offset->x,  temp );
          offset->y  = FT_DivFix( offset->y,  temp );
        }

        offset->x >>= 16;
        offset->y >>= 16;
      }

      for ( i = cff->num_subfonts; i > 0; i-- )
      {
        CFF_FontRecDict  sub = &cff->subfonts[i - 1]->font_dict;
        CFF_FontRecDict  top = &cff->top_font.font_dict;

        FT_Matrix*  matrix;
        FT_Vector*  offset;
        FT_ULong*   upm;
        FT_Fixed    temp;


        if ( sub->has_font_matrix )
        {
          FT_Long  scaling;


          /* if we have a top-level matrix, */
          /* concatenate the subfont matrix */

          if ( top->has_font_matrix )
          {
            if ( top->units_per_em > 1 && sub->units_per_em > 1 )
              scaling = FT_MIN( top->units_per_em, sub->units_per_em );
            else
              scaling = 1;

            FT_Matrix_Multiply_Scaled( &top->font_matrix,
                                       &sub->font_matrix,
                                       scaling );
            FT_Vector_Transform_Scaled( &sub->font_offset,
                                        &top->font_matrix,
                                        scaling );

            sub->units_per_em = FT_MulDiv( sub->units_per_em,
                                           top->units_per_em,
                                           scaling );
          }
        }
        else
        {
          sub->font_matrix = top->font_matrix;
          sub->font_offset = top->font_offset;

          sub->units_per_em = top->units_per_em;
        }

        matrix = &sub->font_matrix;
        offset = &sub->font_offset;
        upm    = &sub->units_per_em;
        temp   = FT_ABS( matrix->yy );

        if ( temp != 0x10000L )
        {
          *upm = FT_DivFix( *upm, temp );

          matrix->xx = FT_DivFix( matrix->xx, temp );
          matrix->yx = FT_DivFix( matrix->yx, temp );
          matrix->xy = FT_DivFix( matrix->xy, temp );
          matrix->yy = FT_DivFix( matrix->yy, temp );
          offset->x  = FT_DivFix( offset->x,  temp );
          offset->y  = FT_DivFix( offset->y,  temp );
        }

        offset->x >>= 16;
        offset->y >>= 16;
      }

      if ( pure_cff )
      {
        char*  style_name = NULL;


        /* set up num_faces */
        cffface->num_faces = cff->num_faces;

        /* compute number of glyphs */
        if ( dict->cid_registry != 0xFFFFU )
          cffface->num_glyphs = cff->charset.max_cid + 1;
        else
          cffface->num_glyphs = cff->charstrings_index.count;

        /* set global bbox, as well as EM size */
        cffface->bbox.xMin =   dict->font_bbox.xMin            >> 16;
        cffface->bbox.yMin =   dict->font_bbox.yMin            >> 16;
        /* no `U' suffix here to 0xFFFF! */
        cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16;
        cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16;

        cffface->units_per_EM = (FT_UShort)( dict->units_per_em );

        cffface->ascender  = (FT_Short)( cffface->bbox.yMax );
        cffface->descender = (FT_Short)( cffface->bbox.yMin );

        cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );
        if ( cffface->height < cffface->ascender - cffface->descender )
          cffface->height = (FT_Short)( cffface->ascender - cffface->descender );

        cffface->underline_position  =
          (FT_Short)( dict->underline_position >> 16 );
        cffface->underline_thickness =
          (FT_Short)( dict->underline_thickness >> 16 );

        /* retrieve font family & style name */
        cffface->family_name = cff_index_get_name( cff, face_index );
        if ( cffface->family_name )
        {
          char*  full   = cff_index_get_sid_string( cff,
                                                    dict->full_name );
          char*  fullp  = full;
          char*  family = cffface->family_name;
          char*  family_name = NULL;


          remove_subset_prefix( cffface->family_name );

          if ( dict->family_name )
          {
            family_name = cff_index_get_sid_string( cff,
                                                    dict->family_name );
            if ( family_name )
              family = family_name;
          }

          /* We try to extract the style name from the full name.   */
          /* We need to ignore spaces and dashes during the search. */
          if ( full && family )
          {
            while ( *fullp )
            {
              /* skip common characters at the start of both strings */
              if ( *fullp == *family )
              {
                family++;
                fullp++;
                continue;
              }

              /* ignore spaces and dashes in full name during comparison */
              if ( *fullp == ' ' || *fullp == '-' )
              {
                fullp++;
                continue;
              }

              /* ignore spaces and dashes in family name during comparison */
              if ( *family == ' ' || *family == '-' )
              {
                family++;
                continue;
              }

              if ( !*family && *fullp )
              {
                /* The full name begins with the same characters as the  */
                /* family name, with spaces and dashes removed.  In this */
                /* case, the remaining string in `fullp' will be used as */
                /* the style name.                                       */
                style_name = cff_strcpy( memory, fullp );

                /* remove the style part from the family name (if present) */
                remove_style( cffface->family_name, style_name );
              }
              break;
            }
          }
        }
        else
        {
          char  *cid_font_name =
                   cff_index_get_sid_string( cff,
                                             dict->cid_font_name );


          /* do we have a `/FontName' for a CID-keyed font? */
          if ( cid_font_name )
            cffface->family_name = cff_strcpy( memory, cid_font_name );
        }

        if ( style_name )
          cffface->style_name = style_name;
        else
          /* assume "Regular" style if we don't know better */
          cffface->style_name = cff_strcpy( memory, (char *)"Regular" );

        /*******************************************************************/
        /*                                                                 */
        /* Compute face flags.                                             */
        /*                                                                 */
        flags = FT_FACE_FLAG_SCALABLE   | /* scalable outlines */
                FT_FACE_FLAG_HORIZONTAL | /* horizontal data   */
                FT_FACE_FLAG_HINTER;      /* has native hinter */

        if ( sfnt_format )
          flags |= FT_FACE_FLAG_SFNT;

        /* fixed width font? */
        if ( dict->is_fixed_pitch )
          flags |= FT_FACE_FLAG_FIXED_WIDTH;

  /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
#if 0
        /* kerning available? */
        if ( face->kern_pairs )
          flags |= FT_FACE_FLAG_KERNING;
#endif

        cffface->face_flags |= flags;

        /*******************************************************************/
        /*                                                                 */
        /* Compute style flags.                                            */
        /*                                                                 */
        flags = 0;

        if ( dict->italic_angle )
          flags |= FT_STYLE_FLAG_ITALIC;

        {
          char  *weight = cff_index_get_sid_string( cff,
                                                    dict->weight );


          if ( weight )
            if ( !ft_strcmp( weight, "Bold"  ) ||
                 !ft_strcmp( weight, "Black" ) )
              flags |= FT_STYLE_FLAG_BOLD;
        }

        /* double check */
        if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name )
          if ( !ft_strncmp( cffface->style_name, "Bold", 4 )  ||
               !ft_strncmp( cffface->style_name, "Black", 5 ) )
            flags |= FT_STYLE_FLAG_BOLD;

        cffface->style_flags = flags;
      }


#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
      /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */
      /* has unset this flag because of the 3.0 `post' table.          */
      if ( dict->cid_registry == 0xFFFFU )
        cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
#endif

      if ( dict->cid_registry != 0xFFFFU && pure_cff )
        cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;


      /*******************************************************************/
      /*                                                                 */
      /* Compute char maps.                                              */
      /*                                                                 */

      /* Try to synthesize a Unicode charmap if there is none available */
      /* already.  If an OpenType font contains a Unicode "cmap", we    */
      /* will use it, whatever be in the CFF part of the file.          */
      {
        FT_CharMapRec  cmaprec;
        FT_CharMap     cmap;
        FT_UInt        nn;
        CFF_Encoding   encoding = &cff->encoding;


        for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ )
        {
          cmap = cffface->charmaps[nn];

          /* Windows Unicode? */
          if ( cmap->platform_id == TT_PLATFORM_MICROSOFT &&
               cmap->encoding_id == TT_MS_ID_UNICODE_CS   )
            goto Skip_Unicode;

          /* Apple Unicode platform id? */
          if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE )
            goto Skip_Unicode; /* Apple Unicode */
        }

        /* since CID-keyed fonts don't contain glyph names, we can't */
        /* construct a cmap                                          */
        if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
          goto Exit;

#ifdef FT_MAX_CHARMAP_CACHEABLE
        if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE )
        {
          FT_ERROR(( "cff_face_init: no Unicode cmap is found, "
                     "and too many subtables (%d) to add synthesized cmap\n",
                     nn ));
          goto Exit;
        }
#endif

        /* we didn't find a Unicode charmap -- synthesize one */
        cmaprec.face        = cffface;
        cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
        cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
        cmaprec.encoding    = FT_ENCODING_UNICODE;

        nn = (FT_UInt)cffface->num_charmaps;

        error = FT_CMap_New( &CFF_CMAP_UNICODE_CLASS_REC_GET, NULL,
                             &cmaprec, NULL );
        if ( error                                      &&
             FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
          goto Exit;
        error = FT_Err_Ok;

        /* if no Unicode charmap was previously selected, select this one */
        if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps )
          cffface->charmap = cffface->charmaps[nn];

      Skip_Unicode:
#ifdef FT_MAX_CHARMAP_CACHEABLE
        if ( nn > FT_MAX_CHARMAP_CACHEABLE )
        {
          FT_ERROR(( "cff_face_init: Unicode cmap is found, "
                     "but too many preceding subtables (%d) to access\n",
                     nn - 1 ));
          goto Exit;
        }
#endif
        if ( encoding->count > 0 )
        {
          FT_CMap_Class  clazz;


          cmaprec.face        = cffface;
          cmaprec.platform_id = TT_PLATFORM_ADOBE;  /* Adobe platform id */

          if ( encoding->offset == 0 )
          {
            cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
            cmaprec.encoding    = FT_ENCODING_ADOBE_STANDARD;
            clazz               = &CFF_CMAP_ENCODING_CLASS_REC_GET;
          }
          else if ( encoding->offset == 1 )
          {
            cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
            cmaprec.encoding    = FT_ENCODING_ADOBE_EXPERT;
            clazz               = &CFF_CMAP_ENCODING_CLASS_REC_GET;
          }
          else
          {
            cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
            cmaprec.encoding    = FT_ENCODING_ADOBE_CUSTOM;
            clazz               = &CFF_CMAP_ENCODING_CLASS_REC_GET;
          }

          error = FT_CMap_New( clazz, NULL, &cmaprec, NULL );
        }
      }
    }

  Exit:
    return error;
  }
예제 #4
0
파일: pfrobjs.c 프로젝트: 8l/inferno
  pfr_face_init( FT_Stream      stream,
                 PFR_Face       face,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    FT_Error  error;

    FT_UNUSED( num_params );
    FT_UNUSED( params );


    /* load the header and check it */
    error = pfr_header_load( &face->header, stream );
    if ( error )
      goto Exit;

    if ( !pfr_header_check( &face->header ) )
    {
      FT_TRACE4(( "pfr_face_init: not a valid PFR font\n" ));
      error = PFR_Err_Unknown_File_Format;
      goto Exit;
    }

    /* check face index */
    {
      FT_UInt  num_faces;


      error = pfr_log_font_count( stream,
                                  face->header.log_dir_offset,
                                  &num_faces );
      if ( error )
        goto Exit;

      face->root.num_faces = num_faces;
    }

    if ( face_index < 0 )
      goto Exit;

    if ( face_index >= face->root.num_faces )
    {
      FT_ERROR(( "pfr_face_init: invalid face index\n" ));
      error = PFR_Err_Invalid_Argument;
      goto Exit;
    }

    /* load the face */
    error = pfr_log_font_load(
               &face->log_font, stream, face_index,
               face->header.log_dir_offset,
               FT_BOOL( face->header.phy_font_max_size_high != 0 ) );
    if ( error )
      goto Exit;

    /* now load the physical font descriptor */
     error = pfr_phy_font_load( &face->phy_font, stream,
                                 face->log_font.phys_offset,
                                 face->log_font.phys_size );
     if ( error )
       goto Exit;

     /* now, set-up all root face fields */
     {
       FT_Face      root     = FT_FACE( face );
       PFR_PhyFont  phy_font = &face->phy_font;


       root->face_index = face_index;
       root->num_glyphs = phy_font->num_chars;
       root->face_flags = FT_FACE_FLAG_SCALABLE;

       if ( (phy_font->flags & PFR_PHY_PROPORTIONAL) == 0 )
         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

       if ( phy_font->flags & PFR_PHY_VERTICAL )
         root->face_flags |= FT_FACE_FLAG_VERTICAL;
       else
         root->face_flags |= FT_FACE_FLAG_HORIZONTAL;

       if ( phy_font->num_strikes > 0 )
         root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;

       if ( phy_font->num_kern_pairs > 0 )
         root->face_flags |= FT_FACE_FLAG_KERNING;

       root->family_name = phy_font->font_id;
       root->style_name  = NULL;  /* no style name in font file */

       root->num_fixed_sizes = 0;
       root->available_sizes = 0;

       root->bbox         = phy_font->bbox;
       root->units_per_EM = (FT_UShort)phy_font->outline_resolution;
       root->ascender     = (FT_Short) phy_font->bbox.yMax;
       root->descender    = (FT_Short) phy_font->bbox.yMin;
       root->height       = (FT_Short)
                              ( ( ( root->ascender - root->descender ) * 12 )
                                / 10 );

       /* now compute maximum advance width */
       if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 )
         root->max_advance_width = (FT_Short)phy_font->standard_advance;
       else
       {
         FT_Int    max = 0;
         FT_UInt   count = phy_font->num_chars;
         PFR_Char  gchar = phy_font->chars;


         for ( ; count > 0; count--, gchar++ )
         {
           if ( max < gchar->advance )
             max = gchar->advance;
         }

         root->max_advance_width = (FT_Short)max;
       }

       root->max_advance_height = root->height;

       root->underline_position  = (FT_Short)( - root->units_per_EM / 10 );
       root->underline_thickness = (FT_Short)(   root->units_per_EM / 30 );

       /* create charmap */
       {
         FT_CharMapRec  charmap;


         charmap.face        = root;
         charmap.platform_id = 3;
         charmap.encoding_id = 1;
         charmap.encoding    = FT_ENCODING_UNICODE;

         FT_CMap_New( &pfr_cmap_class_rec, NULL, &charmap, NULL );

#if 0
         /* Select default charmap */
         if (root->num_charmaps)
           root->charmap = root->charmaps[0];
#endif
       }

       /* check whether we've loaded any kerning pairs */
       if ( phy_font->num_kern_pairs )
         root->face_flags |= FT_FACE_FLAG_KERNING;
     }

  Exit:
    return error;
  }
예제 #5
0
파일: t42objs.c 프로젝트: 0uyangsheng/xbmc
  T42_Face_Init( FT_Stream      stream,
                 T42_Face       face,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    FT_Error            error;
    FT_Service_PsCMaps  psnames;
    PSAux_Service       psaux;
    FT_Face             root  = (FT_Face)&face->root;
    T1_Font             type1 = &face->type1;
    PS_FontInfo         info  = &type1->font_info;

    FT_UNUSED( num_params );
    FT_UNUSED( params );
    FT_UNUSED( face_index );
    FT_UNUSED( stream );


    face->ttf_face       = NULL;
    face->root.num_faces = 1;

    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
    face->psnames = psnames;

    face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
                                           "psaux" );
    psaux = (PSAux_Service)face->psaux;

    /* open the tokenizer, this will also check the font format */
    error = T42_Open_Face( face );
    if ( error )
      goto Exit;

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

    /* check the face index */
    if ( face_index > 0 )
    {
      FT_ERROR(( "T42_Face_Init: invalid face index\n" ));
      error = T42_Err_Invalid_Argument;
      goto Exit;
    }

    /* Now load the font program into the face object */

    /* Init the face object fields */
    /* Now set up root face fields */

    root->num_glyphs   = type1->num_glyphs;
    root->num_charmaps = 0;
    root->face_index   = 0;

    root->face_flags = FT_FACE_FLAG_SCALABLE    |
                       FT_FACE_FLAG_HORIZONTAL  |
                       FT_FACE_FLAG_GLYPH_NAMES;

    if ( info->is_fixed_pitch )
      root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

    /* We only set this flag if we have the patented bytecode interpreter. */
    /* There are no known `tricky' Type42 fonts that could be loaded with  */
    /* the unpatented interpreter.                                         */
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
    root->face_flags |= FT_FACE_FLAG_HINTER;
#endif

    /* XXX: TODO -- add kerning with .afm support */

    /* get style name -- be careful, some broken fonts only */
    /* have a `/FontName' dictionary entry!                 */
    root->family_name = info->family_name;
    /* assume "Regular" style if we don't know better */
    root->style_name = (char *)"Regular";
    if ( root->family_name )
    {
      char*  full   = info->full_name;
      char*  family = root->family_name;


      if ( full )
      {
        while ( *full )
        {
          if ( *full == *family )
          {
            family++;
            full++;
          }
          else
          {
            if ( *full == ' ' || *full == '-' )
              full++;
            else if ( *family == ' ' || *family == '-' )
              family++;
            else
            {
              if ( !*family )
                root->style_name = full;
              break;
            }
          }
        }
      }
    }
    else
    {
      /* do we have a `/FontName'? */
      if ( type1->font_name )
        root->family_name = type1->font_name;
    }

    /* no embedded bitmap support */
    root->num_fixed_sizes = 0;
    root->available_sizes = 0;

    /* Load the TTF font embedded in the T42 font */
    {
      FT_Open_Args  args;


      args.flags       = FT_OPEN_MEMORY;
      args.memory_base = face->ttf_data;
      args.memory_size = face->ttf_size;

      if ( num_params )
      {
        args.flags     |= FT_OPEN_PARAMS;
        args.num_params = num_params;
        args.params     = params;
      }

      error = FT_Open_Face( FT_FACE_LIBRARY( face ),
                            &args, 0, &face->ttf_face );
    }

    if ( error )
      goto Exit;

    FT_Done_Size( face->ttf_face->size );

    /* Ignore info in FontInfo dictionary and use the info from the  */
    /* loaded TTF font.  The PostScript interpreter also ignores it. */
    root->bbox         = face->ttf_face->bbox;
    root->units_per_EM = face->ttf_face->units_per_EM;

    root->ascender  = face->ttf_face->ascender;
    root->descender = face->ttf_face->descender;
    root->height    = face->ttf_face->height;

    root->max_advance_width  = face->ttf_face->max_advance_width;
    root->max_advance_height = face->ttf_face->max_advance_height;

    root->underline_position  = (FT_Short)info->underline_position;
    root->underline_thickness = (FT_Short)info->underline_thickness;

    /* compute style flags */
    root->style_flags = 0;
    if ( info->italic_angle )
      root->style_flags |= FT_STYLE_FLAG_ITALIC;

    if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )
      root->style_flags |= FT_STYLE_FLAG_BOLD;

    if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )
      root->face_flags |= FT_FACE_FLAG_VERTICAL;

    {
      if ( psnames && psaux )
      {
        FT_CharMapRec    charmap;
        T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
        FT_CMap_Class    clazz;


        charmap.face = root;

        /* first of all, try to synthesize a Unicode charmap */
        charmap.platform_id = 3;
        charmap.encoding_id = 1;
        charmap.encoding    = FT_ENCODING_UNICODE;

        FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );

        /* now, generate an Adobe Standard encoding when appropriate */
        charmap.platform_id = 7;
        clazz               = NULL;

        switch ( type1->encoding_type )
        {
        case T1_ENCODING_TYPE_STANDARD:
          charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
          charmap.encoding_id = 0;
          clazz               = cmap_classes->standard;
          break;

        case T1_ENCODING_TYPE_EXPERT:
          charmap.encoding    = FT_ENCODING_ADOBE_EXPERT;
          charmap.encoding_id = 1;
          clazz               = cmap_classes->expert;
          break;

        case T1_ENCODING_TYPE_ARRAY:
          charmap.encoding    = FT_ENCODING_ADOBE_CUSTOM;
          charmap.encoding_id = 2;
          clazz               = cmap_classes->custom;
          break;

        case T1_ENCODING_TYPE_ISOLATIN1:
          charmap.encoding    = FT_ENCODING_ADOBE_LATIN_1;
          charmap.encoding_id = 3;
          clazz               = cmap_classes->unicode;
          break;

        default:
          ;
        }

        if ( clazz )
          FT_CMap_New( clazz, NULL, &charmap, NULL );

#if 0
        /* Select default charmap */
        if ( root->num_charmaps )
          root->charmap = root->charmaps[0];
#endif
      }
    }
  Exit:
    return error;
  }
예제 #6
0
  PCF_Face_Init( FT_Stream      stream,
                 PCF_Face       face,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    FT_Error  error = PCF_Err_Ok;

    FT_UNUSED( num_params );
    FT_UNUSED( params );
    FT_UNUSED( face_index );


    error = pcf_load_font( stream, face );
    if ( error )
    {
      FT_Error  error2;


      /* this didn't work, try gzip support! */
      error2 = FT_Stream_OpenGzip( &face->gzip_stream, stream );
      if ( error2 == PCF_Err_Unimplemented_Feature )
        goto Fail;

      error = error2;
      if ( error )
        goto Fail;

      face->gzip_source = stream;
      face->root.stream = &face->gzip_stream;

      stream = face->root.stream;

      error = pcf_load_font( stream, face );
      if ( error )
        goto Fail;
    }

    /* set-up charmap */
    {
      FT_String  *charset_registry, *charset_encoding;
      FT_Bool     unicode_charmap  = 0;


      charset_registry = face->charset_registry;
      charset_encoding = face->charset_encoding;

      if ( ( charset_registry != NULL ) &&
           ( charset_encoding != NULL ) )
      {
        char*  s = face->charset_registry;


        /* Uh, oh, compare first letters manually to avoid dependency
           on locales. */
        if ( ( s[0] == 'i' || s[0] == 'I' ) &&
             ( s[1] == 's' || s[1] == 'S' ) &&
             ( s[2] == 'o' || s[2] == 'O' ) )
        {
          s += 3;
          if ( !ft_strcmp( s, "10646" )                      ||
               ( !ft_strcmp( s, "8859" ) &&
                 !ft_strcmp( face->charset_encoding, "1" ) ) )
          unicode_charmap = 1;
        }
      }

      {
        FT_CharMapRec  charmap;


        charmap.face        = FT_FACE( face );
        charmap.encoding    = FT_ENCODING_NONE;
        charmap.platform_id = 0;
        charmap.encoding_id = 0;

        if ( unicode_charmap )
        {
          charmap.encoding    = FT_ENCODING_UNICODE;
          charmap.platform_id = 3;
          charmap.encoding_id = 1;
        }

        error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );

#if 0
        /* Select default charmap */
        if (face->root.num_charmaps)
          face->root.charmap = face->root.charmaps[0];
#endif
      }
    }

  Exit:
    return error;

  Fail:
    FT_TRACE2(( "[not a valid PCF file]\n" ));
    error = PCF_Err_Unknown_File_Format;  /* error */
    goto Exit;
  }
예제 #7
0
  cff_face_init( FT_Stream      stream,
                 FT_Face        cffface,        /* CFF_Face */
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    CFF_Face            face = (CFF_Face)cffface;
    FT_Error            error;
    SFNT_Service        sfnt;
    FT_Service_PsCMaps  psnames;
    PSHinter_Service    pshinter;
    FT_Bool             pure_cff    = 1;
    FT_Bool             sfnt_format = 0;


#if 0
    FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt,     SFNT );
    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames,  POSTSCRIPT_NAMES );
    FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER );

    if ( !sfnt )
      goto Bad_Format;
#else
    sfnt = (SFNT_Service)FT_Get_Module_Interface(
             cffface->driver->root.library, "sfnt" );
    if ( !sfnt )
      goto Bad_Format;

    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );

    pshinter = (PSHinter_Service)FT_Get_Module_Interface(
                 cffface->driver->root.library, "pshinter" );
#endif

    /* create input stream from resource */
    if ( FT_STREAM_SEEK( 0 ) )
      goto Exit;

    /* check whether we have a valid OpenType file */
    error = sfnt->init_face( stream, face, face_index, num_params, params );
    if ( !error )
    {
      if ( face->format_tag != 0x4F54544FL )  /* `OTTO'; OpenType/CFF font */
      {
        FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
        goto Bad_Format;
      }

      /* if we are performing a simple font format check, exit immediately */
      if ( face_index < 0 )
        return CFF_Err_Ok;

      /* UNDOCUMENTED!  A CFF in an SFNT can have only a single font. */
      if ( face_index > 0 )
      {
        FT_ERROR(( "cff_face_init: invalid face index\n" ));
        error = CFF_Err_Invalid_Argument;
        goto Exit;
      }

      sfnt_format = 1;

      /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
      /* font; in the latter case it doesn't have a `head' table         */
      error = face->goto_table( face, TTAG_head, stream, 0 );
      if ( !error )
      {
        pure_cff = 0;

        /* load font directory */
        error = sfnt->load_face( stream, face,
                                 face_index, num_params, params );
        if ( error )
          goto Exit;
      }
      else
      {
        /* load the `cmap' table explicitly */
        error = sfnt->load_cmap( face, stream );
        if ( error )
          goto Exit;

        /* XXX: we don't load the GPOS table, as OpenType Layout     */
        /* support will be added later to a layout library on top of */
        /* FreeType 2                                                */
      }

      /* now load the CFF part of the file */
      error = face->goto_table( face, TTAG_CFF, stream, 0 );
      if ( error )
        goto Exit;
    }
    else
    {
      /* rewind to start of file; we are going to load a pure-CFF font */
      if ( FT_STREAM_SEEK( 0 ) )
        goto Exit;
      error = CFF_Err_Ok;
    }

    /* now load and parse the CFF table in the file */
    {
      CFF_Font         cff;
      CFF_FontRecDict  dict;
      FT_Memory        memory = cffface->memory;
      FT_Int32         flags;
      FT_UInt          i;


      if ( FT_NEW( cff ) )
        goto Exit;

      face->extra.data = cff;
      error = cff_font_load( stream, face_index, cff );
      if ( error )
        goto Exit;

      cff->pshinter = pshinter;
      cff->psnames  = (void*)psnames;

      /* Complement the root flags with some interesting information. */
      /* Note that this is only necessary for pure CFF and CEF fonts; */
      /* SFNT based fonts use the `name' table instead.               */

      cffface->num_glyphs = cff->num_glyphs;

      dict = &cff->top_font.font_dict;

      /* we need the `PSNames' module for CFF and CEF formats */
      /* which aren't CID-keyed                               */
      if ( dict->cid_registry == 0xFFFFU && !psnames )
      {
        FT_ERROR(( "cff_face_init:" ));
        FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
        FT_ERROR(( "              " ));
        FT_ERROR(( " without the `PSNames' module\n" ));
        goto Bad_Format;
      }

      if ( pure_cff )
      {
        char*  style_name = NULL;


        /* set up num_faces */
        cffface->num_faces = cff->num_faces;

        /* compute number of glyphs */
        if ( dict->cid_registry != 0xFFFFU )
          cffface->num_glyphs = cff->charset.max_cid;
        else
          cffface->num_glyphs = cff->charstrings_index.count;

        /* set global bbox, as well as EM size */
        cffface->bbox.xMin =   dict->font_bbox.xMin             >> 16;
        cffface->bbox.yMin =   dict->font_bbox.yMin             >> 16;
        cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFFU ) >> 16;
        cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFFU ) >> 16;

        if ( !dict->units_per_em )
          dict->units_per_em = 1000;

        cffface->units_per_EM = dict->units_per_em;

        cffface->ascender  = (FT_Short)( cffface->bbox.yMax );
        cffface->descender = (FT_Short)( cffface->bbox.yMin );

        cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );
        if ( cffface->height < cffface->ascender - cffface->descender )
          cffface->height = (FT_Short)( cffface->ascender - cffface->descender );

        cffface->underline_position  =
          (FT_Short)( dict->underline_position >> 16 );
        cffface->underline_thickness =
          (FT_Short)( dict->underline_thickness >> 16 );

        /* retrieve font family & style name */
        cffface->family_name = cff_index_get_name( &cff->name_index,
                                                   face_index );

        if ( cffface->family_name )
        {
          char*  full   = cff_index_get_sid_string( &cff->string_index,
                                                    dict->full_name,
                                                    psnames );
          char*  fullp  = full;
          char*  family = cffface->family_name;
          char*  family_name = 0;


          if ( dict->family_name )
          {
            family_name = cff_index_get_sid_string( &cff->string_index,
                                                    dict->family_name,
                                                    psnames);
            if ( family_name )
              family = family_name;
          }

          /* We try to extract the style name from the full name.   */
          /* We need to ignore spaces and dashes during the search. */
          if ( full && family )
          {
            while ( *fullp )
            {
              /* skip common characters at the start of both strings */
              if ( *fullp == *family )
              {
                family++;
                fullp++;
                continue;
              }

              /* ignore spaces and dashes in full name during comparison */
              if ( *fullp == ' ' || *fullp == '-' )
              {
                fullp++;
                continue;
              }

              /* ignore spaces and dashes in family name during comparison */
              if ( *family == ' ' || *family == '-' )
              {
                family++;
                continue;
              }

              if ( !*family && *fullp )
              {
                /* The full name begins with the same characters as the  */
                /* family name, with spaces and dashes removed.  In this */
                /* case, the remaining string in `fullp' will be used as */
                /* the style name.                                       */
                style_name = cff_strcpy( memory, fullp );
              }
              break;
            }

            if ( family_name )
              FT_FREE( family_name );
            FT_FREE( full );
          }
        }
        else
        {
          char  *cid_font_name =
                   cff_index_get_sid_string( &cff->string_index,
                                             dict->cid_font_name,
                                             psnames );


          /* do we have a `/FontName' for a CID-keyed font? */
          if ( cid_font_name )
            cffface->family_name = cid_font_name;
        }

        if ( style_name )
          cffface->style_name = style_name;
        else
          /* assume "Regular" style if we don't know better */
          cffface->style_name = cff_strcpy( memory, (char *)"Regular" );

        /*******************************************************************/
        /*                                                                 */
        /* Compute face flags.                                             */
        /*                                                                 */
        flags = FT_FACE_FLAG_SCALABLE   |       /* scalable outlines */
                FT_FACE_FLAG_HORIZONTAL |       /* horizontal data   */
                FT_FACE_FLAG_HINTER;            /* has native hinter */

        if ( sfnt_format )
          flags |= FT_FACE_FLAG_SFNT;

        /* fixed width font? */
        if ( dict->is_fixed_pitch )
          flags |= FT_FACE_FLAG_FIXED_WIDTH;

  /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
#if 0
        /* kerning available? */
        if ( face->kern_pairs )
          flags |= FT_FACE_FLAG_KERNING;
#endif

        cffface->face_flags = flags;

        /*******************************************************************/
        /*                                                                 */
        /* Compute style flags.                                            */
        /*                                                                 */
        flags = 0;

        if ( dict->italic_angle )
          flags |= FT_STYLE_FLAG_ITALIC;

        {
          char  *weight = cff_index_get_sid_string( &cff->string_index,
                                                    dict->weight,
                                                    psnames );


          if ( weight )
            if ( !ft_strcmp( weight, "Bold"  ) ||
                 !ft_strcmp( weight, "Black" ) )
              flags |= FT_STYLE_FLAG_BOLD;
          FT_FREE( weight );
        }

        /* double check */
        if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name )
          if ( !ft_strncmp( cffface->style_name, "Bold", 4 )  ||
               !ft_strncmp( cffface->style_name, "Black", 5 ) )
            flags |= FT_STYLE_FLAG_BOLD;

        cffface->style_flags = flags;
      }
      else
      {
        if ( !dict->units_per_em )
          dict->units_per_em = face->root.units_per_EM;
      }

      /* Normalize the font matrix so that `matrix->xx' is 1; the */
      /* scaling is done with `units_per_em' then (at this point, */
      /* it already contains the scaling factor, but without      */
      /* normalization of the matrix).                            */
      /*                                                          */
      /* Note that the offsets must be expressed in integer font  */
      /* units.                                                   */

      {
        FT_Matrix*  matrix = &dict->font_matrix;
        FT_Vector*  offset = &dict->font_offset;
        FT_ULong*   upm    = &dict->units_per_em;
        FT_Fixed    temp   = FT_ABS( matrix->yy );


        if ( temp != 0x10000L )
        {
          *upm = FT_DivFix( *upm, temp );

          matrix->xx = FT_DivFix( matrix->xx, temp );
          matrix->yx = FT_DivFix( matrix->yx, temp );
          matrix->xy = FT_DivFix( matrix->xy, temp );
          matrix->yy = FT_DivFix( matrix->yy, temp );
          offset->x  = FT_DivFix( offset->x,  temp );
          offset->y  = FT_DivFix( offset->y,  temp );
        }

        offset->x >>= 16;
        offset->y >>= 16;
      }

      for ( i = cff->num_subfonts; i > 0; i-- )
      {
        CFF_FontRecDict  sub = &cff->subfonts[i - 1]->font_dict;
        CFF_FontRecDict  top = &cff->top_font.font_dict;

        FT_Matrix*  matrix;
        FT_Vector*  offset;
        FT_ULong*   upm;
        FT_Fixed    temp;


        if ( sub->units_per_em )
        {
          FT_Int  scaling;


          if ( top->units_per_em > 1 && sub->units_per_em > 1 )
            scaling = FT_MIN( top->units_per_em, sub->units_per_em );
          else
            scaling = 1;

          FT_Matrix_Multiply_Scaled( &top->font_matrix,
                                     &sub->font_matrix,
                                     scaling );
          FT_Vector_Transform_Scaled( &sub->font_offset,
                                      &top->font_matrix,
                                      scaling );

          sub->units_per_em = FT_MulDiv( sub->units_per_em,
                                         top->units_per_em,
                                         scaling );
        }
        else
        {
          sub->font_matrix = top->font_matrix;
          sub->font_offset = top->font_offset;

          sub->units_per_em = top->units_per_em;
        }

        matrix = &sub->font_matrix;
        offset = &sub->font_offset;
        upm    = &sub->units_per_em;
        temp   = FT_ABS( matrix->yy );

        if ( temp != 0x10000L )
        {
          *upm = FT_DivFix( *upm, temp );

          /* if *upm is larger than 100*1000 we divide by 1000 --     */
          /* this can happen if e.g. there is no top-font FontMatrix  */
          /* and the subfont FontMatrix already contains the complete */
          /* scaling for the subfont (see section 5.11 of the PLRM)   */

          /* 100 is a heuristic value */

          if ( *upm > 100L * 1000L )
            *upm = ( *upm + 500 ) / 1000;

          matrix->xx = FT_DivFix( matrix->xx, temp );
          matrix->yx = FT_DivFix( matrix->yx, temp );
          matrix->xy = FT_DivFix( matrix->xy, temp );
          matrix->yy = FT_DivFix( matrix->yy, temp );
          offset->x  = FT_DivFix( offset->x,  temp );
          offset->y  = FT_DivFix( offset->y,  temp );
        }

        offset->x >>= 16;
        offset->y >>= 16;
      }

#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
      /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */
      /* has unset this flag because of the 3.0 `post' table.          */
      if ( dict->cid_registry == 0xFFFFU )
        cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
#endif

      if ( dict->cid_registry != 0xFFFFU )
        cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;


      /*******************************************************************/
      /*                                                                 */
      /* Compute char maps.                                              */
      /*                                                                 */

      /* Try to synthetize a Unicode charmap if there is none available */
      /* already.  If an OpenType font contains a Unicode "cmap", we    */
      /* will use it, whatever be in the CFF part of the file.          */
      {
        FT_CharMapRec  cmaprec;
        FT_CharMap     cmap;
        FT_UInt        nn;
        CFF_Encoding   encoding = &cff->encoding;


        for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ )
        {
          cmap = cffface->charmaps[nn];

          /* Windows Unicode (3,1)? */
          if ( cmap->platform_id == 3 && cmap->encoding_id == 1 )
            goto Skip_Unicode;

          /* Deprecated Unicode platform id? */
          if ( cmap->platform_id == 0 )
            goto Skip_Unicode; /* Standard Unicode (deprecated) */
        }

        /* since CID-keyed fonts don't contain glyph names, we can't */
        /* construct a cmap                                          */
        if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
          goto Exit;

        /* we didn't find a Unicode charmap -- synthesize one */
        cmaprec.face        = cffface;
        cmaprec.platform_id = 3;
        cmaprec.encoding_id = 1;
        cmaprec.encoding    = FT_ENCODING_UNICODE;

        nn = (FT_UInt)cffface->num_charmaps;

        FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL );

        /* if no Unicode charmap was previously selected, select this one */
        if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps )
          cffface->charmap = cffface->charmaps[nn];

      Skip_Unicode:
        if ( encoding->count > 0 )
        {
          FT_CMap_Class  clazz;


          cmaprec.face        = cffface;
          cmaprec.platform_id = 7;  /* Adobe platform id */

          if ( encoding->offset == 0 )
          {
            cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
            cmaprec.encoding    = FT_ENCODING_ADOBE_STANDARD;
            clazz               = &cff_cmap_encoding_class_rec;
          }
          else if ( encoding->offset == 1 )
          {
            cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
            cmaprec.encoding    = FT_ENCODING_ADOBE_EXPERT;
            clazz               = &cff_cmap_encoding_class_rec;
          }
          else
          {
            cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
            cmaprec.encoding    = FT_ENCODING_ADOBE_CUSTOM;
            clazz               = &cff_cmap_encoding_class_rec;
          }

          FT_CMap_New( clazz, NULL, &cmaprec, NULL );
        }
      }
    }
예제 #8
0
  T1_Face_Init( FT_Stream      stream,
                T1_Face        face,
                FT_Int         face_index,
                FT_Int         num_params,
                FT_Parameter*  params )
  {
    FT_Error            error;
    FT_Service_PsCMaps  psnames;
    PSAux_Service       psaux;
    T1_Font             type1 = &face->type1;
    PS_FontInfo         info = &type1->font_info;

    FT_UNUSED( num_params );
    FT_UNUSED( params );
    FT_UNUSED( face_index );
    FT_UNUSED( stream );


    face->root.num_faces = 1;

    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
    face->psnames = psnames;

    face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
                                           "psaux" );
    psaux = (PSAux_Service)face->psaux;

    face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
                                              "pshinter" );

    /* open the tokenizer; this will also check the font format */
    error = T1_Open_Face( face );
    if ( error )
      goto Exit;

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

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

    /* now load the font program into the face object */

    /* initialize the face object fields */

    /* set up root face fields */
    {
      FT_Face  root = (FT_Face)&face->root;


      root->num_glyphs = type1->num_glyphs;
      root->face_index = face_index;

      root->face_flags  = FT_FACE_FLAG_SCALABLE;
      root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
      root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;

      if ( info->is_fixed_pitch )
        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

      if ( face->blend )
        root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;

      /* XXX: TODO -- add kerning with .afm support */

      /* get style name -- be careful, some broken fonts only */
      /* have a `/FontName' dictionary entry!                 */
      root->family_name = info->family_name;
      /* assume "Regular" style if we don't know better */
      root->style_name = (char *)"Regular";
      if ( root->family_name )
      {
        char*  full   = info->full_name;
        char*  family = root->family_name;


        if ( full )
        {
          while ( *full )
          {
            if ( *full == *family )
            {
              family++;
              full++;
            }
            else
            {
              if ( *full == ' ' || *full == '-' )
                full++;
              else if ( *family == ' ' || *family == '-' )
                family++;
              else
              {
                if ( !*family )
                  root->style_name = full;
                break;
              }
            }
          }
        }
      }
      else
      {
        /* do we have a `/FontName'? */
        if ( type1->font_name )
          root->family_name = type1->font_name;
      }

      /* compute style flags */
      root->style_flags = 0;
      if ( info->italic_angle )
        root->style_flags |= FT_STYLE_FLAG_ITALIC;
      if ( info->weight )
      {
        if ( !ft_strcmp( info->weight, "Bold"  ) ||
             !ft_strcmp( info->weight, "Black" ) )
          root->style_flags |= FT_STYLE_FLAG_BOLD;
      }

      /* no embedded bitmap support */
      root->num_fixed_sizes = 0;
      root->available_sizes = 0;

      root->bbox.xMin =   type1->font_bbox.xMin             >> 16;
      root->bbox.yMin =   type1->font_bbox.yMin             >> 16;
      root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFFU ) >> 16;
      root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFFU ) >> 16;

      /* Set units_per_EM if we didn't set it in parse_font_matrix. */
      if ( !root->units_per_EM )
        root->units_per_EM = 1000;

      root->ascender  = (FT_Short)( root->bbox.yMax );
      root->descender = (FT_Short)( root->bbox.yMin );
      root->height    = (FT_Short)(
        ( ( root->ascender - root->descender ) * 12 ) / 10 );

      /* now compute the maximum advance width */
      root->max_advance_width =
        (FT_Short)( root->bbox.xMax );
      {
        FT_Pos  max_advance;


        error = T1_Compute_Max_Advance( face, &max_advance );

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

      root->max_advance_height = root->height;

      root->underline_position  = (FT_Short)info->underline_position;
      root->underline_thickness = (FT_Short)info->underline_thickness;

      root->internal->max_points   = 0;
      root->internal->max_contours = 0;
    }

    {
      FT_Face  root = &face->root;


      if ( psnames && psaux )
      {
        FT_CharMapRec    charmap;
        T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
        FT_CMap_Class    clazz;


        charmap.face = root;

        /* first of all, try to synthetize a Unicode charmap */
        charmap.platform_id = 3;
        charmap.encoding_id = 1;
        charmap.encoding    = FT_ENCODING_UNICODE;

        FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );

        /* now, generate an Adobe Standard encoding when appropriate */
        charmap.platform_id = 7;
        clazz               = NULL;

        switch ( type1->encoding_type )
        {
        case T1_ENCODING_TYPE_STANDARD:
          charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
          charmap.encoding_id = TT_ADOBE_ID_STANDARD;
          clazz               = cmap_classes->standard;
          break;

        case T1_ENCODING_TYPE_EXPERT:
          charmap.encoding    = FT_ENCODING_ADOBE_EXPERT;
          charmap.encoding_id = TT_ADOBE_ID_EXPERT;
          clazz               = cmap_classes->expert;
          break;

        case T1_ENCODING_TYPE_ARRAY:
          charmap.encoding    = FT_ENCODING_ADOBE_CUSTOM;
          charmap.encoding_id = TT_ADOBE_ID_CUSTOM;
          clazz               = cmap_classes->custom;
          break;

        case T1_ENCODING_TYPE_ISOLATIN1:
          charmap.encoding    = FT_ENCODING_ADOBE_LATIN_1;
          charmap.encoding_id = TT_ADOBE_ID_LATIN_1;
          clazz               = cmap_classes->unicode;
          break;

        default:
          ;
        }

        if ( clazz )
          FT_CMap_New( clazz, NULL, &charmap, NULL );

#if 0
        /* Select default charmap */
        if (root->num_charmaps)
          root->charmap = root->charmaps[0];
#endif
      }
    }

  Exit:
    return error;
  }
예제 #9
0
파일: winfnt.c 프로젝트: 1tgr/mobius
static FT_Error
FNT_Face_Init( FT_Stream      stream,
               FNT_Face       face,
               FT_Int         face_index,
               FT_Int         num_params,
               FT_Parameter*  params )
{
    FT_Error   error;
    FT_Memory  memory = FT_FACE_MEMORY( face );

    FT_UNUSED( num_params );
    FT_UNUSED( params );


    /* try to load font from a DLL */
    error = fnt_face_get_dll_font( face, face_index );
    if ( error )
    {
        /* this didn't work; try to load a single FNT font */
        FNT_Font  font;


        if ( FT_NEW( face->font ) )
            goto Exit;

        face->root.num_faces = 1;

        font           = face->font;
        font->offset   = 0;
        font->fnt_size = stream->size;

        error = fnt_font_load( font, stream );
        if ( error )
            goto Fail;
    }

    /* we now need to fill the root FT_Face fields */
    /* with relevant information                   */
    {
        FT_Face   root = FT_FACE( face );
        FNT_Font  font = face->font;


        root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
                           FT_FACE_FLAG_HORIZONTAL;

        if ( font->header.avg_width == font->header.max_width )
            root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

        if ( font->header.italic )
            root->style_flags |= FT_STYLE_FLAG_ITALIC;

        if ( font->header.weight >= 800 )
            root->style_flags |= FT_STYLE_FLAG_BOLD;

        /* set up the `fixed_sizes' array */
        if ( FT_NEW_ARRAY( root->available_sizes, 1 ) )
            goto Fail;

        root->num_fixed_sizes = 1;

        {
            FT_Bitmap_Size*  bsize = root->available_sizes;


            bsize->width  = font->header.avg_width;
            bsize->height =
                font->header.pixel_height + font->header.external_leading;
            bsize->size   = font->header.nominal_point_size << 6;
            bsize->x_ppem =
                (FT_Pos)( ( font->header.horizontal_resolution * bsize->size + 36 )
                          / 72 );
            bsize->y_ppem =
                (FT_Pos)( ( font->header.vertical_resolution* bsize->size + 36 )
                          / 72 );
        }

        {
            FT_CharMapRec  charmap;


            charmap.encoding    = FT_ENCODING_UNICODE;
            charmap.platform_id = 3;
            charmap.encoding_id = 1;
            charmap.face        = root;

            error = FT_CMap_New( fnt_cmap_class,
                                 NULL,
                                 &charmap,
                                 NULL );
            if ( error )
                goto Fail;

            /* Select default charmap */
            if ( root->num_charmaps )
                root->charmap = root->charmaps[0];
        }

        /* setup remaining flags */

        /* reserve one slot for the .notdef glyph at index 0 */
        root->num_glyphs = font->header.last_char -
                           font->header.first_char + 1 + 1;

        root->family_name = (FT_String*)font->fnt_frame +
                            font->header.face_name_offset;
        root->style_name  = (char *)"Regular";

        if ( root->style_flags & FT_STYLE_FLAG_BOLD )
        {
            if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
                root->style_name = (char *)"Bold Italic";
            else
                root->style_name = (char *)"Bold";
        }
        else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
            root->style_name = (char *)"Italic";
    }

Fail:
    if ( error )
        FNT_Face_Done( face );

Exit:
    return error;
}
예제 #10
0
  PCF_Face_Init( FT_Stream      stream,
                 PCF_Face       face,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    FT_Error  error = PCF_Err_Ok;

    FT_UNUSED( num_params );
    FT_UNUSED( params );
    FT_UNUSED( face_index );


    error = pcf_load_font( stream, face );
    if ( error )
      goto Fail;

    /* set-up charmap */
    {
      FT_String  *charset_registry, *charset_encoding;
      FT_Bool     unicode_charmap  = 0;


      charset_registry = face->charset_registry;
      charset_encoding = face->charset_encoding;

      if ( ( charset_registry != NULL ) &&
           ( charset_encoding != NULL ) )
      {
        if ( !ft_strcmp( face->charset_registry, "ISO10646" )     ||
             ( !ft_strcmp( face->charset_registry, "ISO8859" ) &&
               !ft_strcmp( face->charset_encoding, "1" )       )  )
          unicode_charmap = 1;
      }

#ifdef FT_CONFIG_OPTION_USE_CMAPS

      {
        FT_CharMapRec  charmap;


        charmap.face        = FT_FACE( face );
        charmap.encoding    = ft_encoding_none;
        charmap.platform_id = 0;
        charmap.encoding_id = 0;

        if ( unicode_charmap )
        {
          charmap.encoding    = ft_encoding_unicode;
          charmap.platform_id = 3;
          charmap.encoding_id = 1;
        }

        error = FT_CMap_New( &pcf_cmap_class, NULL, &charmap, NULL );

        /* Select default charmap */
        if (face->root.num_charmaps)
          face->root.charmap = face->root.charmaps[0];
      }

#else  /* !FT_CONFIG_OPTION_USE_CMAPS */

      /* XXX: charmaps.  For now, report unicode for Unicode and Latin 1 */
      face->root.charmaps     = &face->charmap_handle;
      face->root.num_charmaps = 1;

      face->charmap.encoding    = ft_encoding_none;
      face->charmap.platform_id = 0;
      face->charmap.encoding_id = 0;

      if ( unicode_charmap )
      {
        face->charmap.encoding    = ft_encoding_unicode;
        face->charmap.platform_id = 3;
        face->charmap.encoding_id = 1;
      }

      face->charmap.face   = &face->root;
      face->charmap_handle = &face->charmap;
      face->root.charmap   = face->charmap_handle;

#endif /* !FT_CONFIG_OPTION_USE_CMAPS */

    }

  Exit:
    return error;

  Fail:
    FT_TRACE2(( "[not a valid PCF file]\n" ));
    error = PCF_Err_Unknown_File_Format;  /* error */
    goto Exit;
  }
예제 #11
0
  cff_face_init( FT_Stream      stream,
                 CFF_Face       face,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    FT_Error            error;
    SFNT_Service        sfnt;
    FT_Service_PsCMaps  psnames;
    PSHinter_Service    pshinter;
    FT_Bool             pure_cff    = 1;
    FT_Bool             sfnt_format = 0;

#if 0
    FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt,     SFNT );
    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames,  POSTSCRIPT_NAMES );
    FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER );

    if ( !sfnt )
      goto Bad_Format;
#else
    sfnt = (SFNT_Service)FT_Get_Module_Interface(
             face->root.driver->root.library, "sfnt" );
    if ( !sfnt )
      goto Bad_Format;

    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );

    pshinter = (PSHinter_Service)FT_Get_Module_Interface(
                 face->root.driver->root.library, "pshinter" );
#endif

    /* create input stream from resource */
    if ( FT_STREAM_SEEK( 0 ) )
      goto Exit;

    /* check that we have a valid OpenType file */
    error = sfnt->init_face( stream, face, face_index, num_params, params );
    if ( !error )
    {
      if ( face->format_tag != 0x4F54544FL )  /* `OTTO'; OpenType/CFF font */
      {
        FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
        goto Bad_Format;
      }

      /* if we are performing a simple font format check, exit immediately */
      if ( face_index < 0 )
        return CFF_Err_Ok;

      sfnt_format = 1;

      /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
      /* font; in the later case it doesn't have a `head' table          */
      error = face->goto_table( face, TTAG_head, stream, 0 );
      if ( !error )
      {
        pure_cff = 0;

        /* load font directory */
        error = sfnt->load_face( stream, face,
                                 face_index, num_params, params );
        if ( error )
          goto Exit;
      }
      else
      {
        /* load the `cmap' table by hand */
        error = sfnt->load_charmaps( face, stream );
        if ( error )
          goto Exit;

        /* XXX: we don't load the GPOS table, as OpenType Layout     */
        /* support will be added later to a layout library on top of */
        /* FreeType 2                                                */
      }

      /* now, load the CFF part of the file */
      error = face->goto_table( face, TTAG_CFF, stream, 0 );
      if ( error )
        goto Exit;
    }
    else
    {
      /* rewind to start of file; we are going to load a pure-CFF font */
      if ( FT_STREAM_SEEK( 0 ) )
        goto Exit;
      error = CFF_Err_Ok;
    }

    /* now load and parse the CFF table in the file */
    {
      CFF_Font   cff;
      FT_Memory  memory = face->root.memory;
      FT_Face    root;
      FT_Int32   flags;


      if ( FT_NEW( cff ) )
        goto Exit;

      face->extra.data = cff;
      error = cff_font_load( stream, face_index, cff );
      if ( error )
        goto Exit;

      cff->pshinter = pshinter;
      cff->psnames  = (void*)psnames;

      /* Complement the root flags with some interesting information. */
      /* Note that this is only necessary for pure CFF and CEF fonts. */

      root             = &face->root;
      root->num_glyphs = cff->num_glyphs;

      if ( pure_cff )
      {
        CFF_FontRecDict  dict = &cff->top_font.font_dict;


        /* we need the `PSNames' module for pure-CFF and CEF formats */
        if ( !psnames )
        {
          FT_ERROR(( "cff_face_init:" ));
          FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
          FT_ERROR(( "              " ));
          FT_ERROR(( " without the `PSNames' module\n" ));
          goto Bad_Format;
        }

        /* Set up num_faces. */
        root->num_faces = cff->num_faces;

        /* compute number of glyphs */
        if ( dict->cid_registry )
          root->num_glyphs = dict->cid_count;
        else
          root->num_glyphs = cff->charstrings_index.count;

        /* set global bbox, as well as EM size */
        root->bbox.xMin =   dict->font_bbox.xMin             >> 16;
        root->bbox.yMin =   dict->font_bbox.yMin             >> 16;
        root->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFFU ) >> 16;
        root->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFFU ) >> 16;


        root->ascender  = (FT_Short)( root->bbox.yMax );
        root->descender = (FT_Short)( root->bbox.yMin );
        root->height    = (FT_Short)(
          ( ( root->ascender - root->descender ) * 12 ) / 10 );

        if ( dict->units_per_em )
          root->units_per_EM = dict->units_per_em;
        else
          root->units_per_EM = 1000;

        root->underline_position  =
          (FT_Short)( dict->underline_position >> 16 );
        root->underline_thickness =
          (FT_Short)( dict->underline_thickness >> 16 );

        /* retrieve font family & style name */
        root->family_name  = cff_index_get_name( &cff->name_index, face_index );
        if ( dict->cid_registry )
          root->style_name = cff_strcpy( memory, "Regular" );  /* XXXX */
        else
          root->style_name = cff_index_get_sid_string( &cff->string_index,
                                                       dict->weight,
                                                       psnames );

        /*******************************************************************/
        /*                                                                 */
        /* Compute face flags.                                             */
        /*                                                                 */
        flags = FT_FACE_FLAG_SCALABLE  |    /* scalable outlines */
                FT_FACE_FLAG_HORIZONTAL;    /* horizontal data   */

        if ( sfnt_format )
          flags |= FT_FACE_FLAG_SFNT;

        /* fixed width font? */
        if ( dict->is_fixed_pitch )
          flags |= FT_FACE_FLAG_FIXED_WIDTH;

  /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
#if 0
        /* kerning available? */
        if ( face->kern_pairs )
          flags |= FT_FACE_FLAG_KERNING;
#endif

#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
        flags |= FT_FACE_FLAG_GLYPH_NAMES;
#endif

        root->face_flags = flags;

        /*******************************************************************/
        /*                                                                 */
        /* Compute style flags.                                            */
        /*                                                                 */
        flags = 0;

        if ( dict->italic_angle )
          flags |= FT_STYLE_FLAG_ITALIC;

        /* XXX: may not be correct */
        if ( cff->top_font.private_dict.force_bold )
          flags |= FT_STYLE_FLAG_BOLD;

        root->style_flags = flags;
      }

      /*******************************************************************/
      /*                                                                 */
      /* Compute char maps.                                              */
      /*                                                                 */

      /* Try to synthetize a Unicode charmap if there is none available */
      /* already.  If an OpenType font contains a Unicode "cmap", we    */
      /* will use it, whatever be in the CFF part of the file.          */
      {
        FT_CharMapRec  cmaprec;
        FT_CharMap     cmap;
        FT_UInt        nn;
        CFF_Encoding   encoding = &cff->encoding;


        for ( nn = 0; nn < (FT_UInt)root->num_charmaps; nn++ )
        {
          cmap = root->charmaps[nn];

          /* Windows Unicode (3,1)? */
          if ( cmap->platform_id == 3 && cmap->encoding_id == 1 )
            goto Skip_Unicode;

          /* Deprecated Unicode platform id? */
          if ( cmap->platform_id == 0 )
            goto Skip_Unicode; /* Standard Unicode (deprecated) */
        }

        /* we didn't find a Unicode charmap, synthetize one */
        cmaprec.face        = root;
        cmaprec.platform_id = 3;
        cmaprec.encoding_id = 1;
        cmaprec.encoding    = FT_ENCODING_UNICODE;

        nn = (FT_UInt)root->num_charmaps;

        FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL );

        /* if no Unicode charmap was previously selected, select this one */
        if ( root->charmap == NULL && nn != (FT_UInt)root->num_charmaps )
          root->charmap = root->charmaps[nn];

      Skip_Unicode:
        if ( encoding->count > 0 )
        {
          FT_CMap_Class  clazz;


          cmaprec.face        = root;
          cmaprec.platform_id = 7;  /* Adobe platform id */

          if ( encoding->offset == 0 )
          {
            cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
            cmaprec.encoding    = FT_ENCODING_ADOBE_STANDARD;
            clazz               = &cff_cmap_encoding_class_rec;
          }
          else if ( encoding->offset == 1 )
          {
            cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
            cmaprec.encoding    = FT_ENCODING_ADOBE_EXPERT;
            clazz               = &cff_cmap_encoding_class_rec;
          }
          else
          {
            cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
            cmaprec.encoding    = FT_ENCODING_ADOBE_CUSTOM;
            clazz               = &cff_cmap_encoding_class_rec;
          }

          FT_CMap_New( clazz, NULL, &cmaprec, NULL );
        }
      }
    }

  Exit:
    return error;

  Bad_Format:
    error = CFF_Err_Unknown_File_Format;
    goto Exit;
  }
예제 #12
0
파일: t42objs.c 프로젝트: dikerex/theqvd
  T42_Face_Init( FT_Stream      stream,
                 T42_Face       face,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params)
  {
    FT_Error          error;
    PSNames_Service   psnames;
    PSAux_Service     psaux;
    FT_Face           root    = (FT_Face)&face->root;

    FT_UNUSED( num_params );
    FT_UNUSED( params );
    FT_UNUSED( face_index );
    FT_UNUSED( stream );


    face->ttf_face       = NULL;
    face->root.num_faces = 1;

    face->psnames = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
                                             "psnames" );
    psnames = (PSNames_Service)face->psnames;

    face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
                                           "psaux" );
    psaux = (PSAux_Service)face->psaux;

    /* open the tokenizer, this will also check the font format */
    error = T42_Open_Face( face );
    if ( error )
      goto Exit;

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

    /* check the face index */
    if ( face_index != 0 )
    {
      FT_ERROR(( "T42_Face_Init: invalid face index\n" ));
      error = T42_Err_Invalid_Argument;
      goto Exit;
    }

    /* Now, load the font program into the face object */

    /* Init the face object fields */
    /* Now set up root face fields */

    root->num_glyphs   = face->type1.num_glyphs;
    root->num_charmaps = 0;
    root->face_index   = face_index;

    root->face_flags  = FT_FACE_FLAG_SCALABLE;
    root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
    root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;

    if ( face->type1.font_info.is_fixed_pitch )
      root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

    /* XXX: TODO -- add kerning with .afm support */

    /* get style name -- be careful, some broken fonts only */
    /* have a `/FontName' dictionary entry!                 */
    root->family_name = face->type1.font_info.family_name;
    if ( root->family_name )
    {
      char*  full   = face->type1.font_info.full_name;
      char*  family = root->family_name;


      if ( full )
      {
        while ( *family && *full == *family )
        {
          family++;
          full++;
        }

        root->style_name = ( *full == ' ' ? full + 1
                                          : (char *)"Regular" );
      }
      else
        root->style_name = (char *)"Regular";
    }
    else
    {
      /* do we have a `/FontName'? */
      if ( face->type1.font_name )
      {
        root->family_name = face->type1.font_name;
        root->style_name  = (char *)"Regular";
      }
    }

    /* no embedded bitmap support */
    root->num_fixed_sizes = 0;
    root->available_sizes = 0;

    /* Load the TTF font embedded in the T42 font */
    error = FT_New_Memory_Face( FT_FACE_LIBRARY( face ),
                                face->ttf_data,
                                face->ttf_size,
                                0,
                                &face->ttf_face );
    if ( error )
      goto Exit;

    FT_Done_Size( face->ttf_face->size );

    /* Ignore info in FontInfo dictionary and use the info from the  */
    /* loaded TTF font.  The PostScript interpreter also ignores it. */
    root->bbox         = face->ttf_face->bbox;
    root->units_per_EM = face->ttf_face->units_per_EM;

    root->ascender  = face->ttf_face->ascender;
    root->descender = face->ttf_face->descender;
    root->height    = face->ttf_face->height;

    root->max_advance_width  = face->ttf_face->max_advance_width;
    root->max_advance_height = face->ttf_face->max_advance_height;

    root->underline_position  = face->type1.font_info.underline_position;
    root->underline_thickness = face->type1.font_info.underline_thickness;

    root->internal->max_points   = 0;
    root->internal->max_contours = 0;

    /* compute style flags */
    root->style_flags = 0;
    if ( face->type1.font_info.italic_angle )
      root->style_flags |= FT_STYLE_FLAG_ITALIC;

    if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )
      root->style_flags |= FT_STYLE_FLAG_BOLD;

    if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )
      root->face_flags |= FT_FACE_FLAG_VERTICAL;

#ifdef FT_CONFIG_OPTION_USE_CMAPS

    {
      if ( psnames && psaux )
      {
        FT_CharMapRec    charmap;
        T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
        FT_CMap_Class    clazz;


        charmap.face = root;

        /* first of all, try to synthetize a Unicode charmap */
        charmap.platform_id = 3;
        charmap.encoding_id = 1;
        charmap.encoding    = ft_encoding_unicode;

        FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );

        /* now, generate an Adobe Standard encoding when appropriate */
        charmap.platform_id = 7;
        clazz               = NULL;

        switch ( face->type1.encoding_type )
        {
        case T1_ENCODING_TYPE_STANDARD:
          charmap.encoding    = ft_encoding_adobe_standard;
          charmap.encoding_id = 0;
          clazz               = cmap_classes->standard;
          break;

        case T1_ENCODING_TYPE_EXPERT:
          charmap.encoding    = ft_encoding_adobe_expert;
          charmap.encoding_id = 1;
          clazz               = cmap_classes->expert;
          break;

        case T1_ENCODING_TYPE_ARRAY:
          charmap.encoding    = ft_encoding_adobe_custom;
          charmap.encoding_id = 2;
          clazz               = cmap_classes->custom;
          break;

        case T1_ENCODING_TYPE_ISOLATIN1:
          charmap.encoding    = ft_encoding_latin_1;
          charmap.encoding_id = 3;
          clazz               = cmap_classes->unicode;
          break;

        default:
          ;
        }

        if ( clazz )
          FT_CMap_New( clazz, NULL, &charmap, NULL );

        /* Select default charmap */
        if (root->num_charmaps)
          root->charmap = root->charmaps[0];
      }
    }

#else /* !FT_CONFIG_OPTION_USE_CMAPS */

    /* charmap support -- synthetize unicode charmap if possible */
    {
      FT_CharMap  charmap = face->charmaprecs;

      
      /* synthesize a Unicode charmap if there is support in the `PSNames' */
      /* module                                                            */
      if ( psnames && 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++;
        }
        
        /* XXX: Is the following code correct?  It is used in t1objs.c */
        
        /* simply clear the error in case of failure (which really) */
        /* means that out of memory or no unicode glyph names       */
        error = T42_Err_Ok;
      }
      
      /* now, support either the standard, expert, or custom encoding */
      charmap->face        = (FT_Face)face;
      charmap->platform_id = 7;  /* a new platform id for Adobe fonts? */
      
      switch ( face->type1.encoding_type )
      {
      case T1_ENCODING_TYPE_STANDARD:
        charmap->encoding    = ft_encoding_adobe_standard;
        charmap->encoding_id = 0;
        break;
        
      case T1_ENCODING_TYPE_EXPERT:
        charmap->encoding    = ft_encoding_adobe_expert;
        charmap->encoding_id = 1;
        break;
        
      case T1_ENCODING_TYPE_ARRAY:
        charmap->encoding    = ft_encoding_adobe_custom;
        charmap->encoding_id = 2;
        break;
        
      case T1_ENCODING_TYPE_ISOLATIN1:
        charmap->encoding    = ft_encoding_latin_1;
        charmap->encoding_id = 3;
        break;
        
      default:
        FT_ERROR(( "T42_Face_Init: invalid encoding\n" ));
        error = T42_Err_Invalid_File_Format;
        goto Exit;
      }
      
      root->charmaps     = face->charmaps;
      root->num_charmaps = charmap - face->charmaprecs + 1;
      face->charmaps[0]  = &face->charmaprecs[0];
      face->charmaps[1]  = &face->charmaprecs[1];
    }

#endif /* !FT_CONFIG_OPTION_USE_CMAPS */

  Exit:
    return error;
  }
예제 #13
0
  T42_Face_Init( FT_Stream      stream,
                 T42_Face       face,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    FT_Error          error;
    PSNames_Service   psnames;
    PSAux_Service     psaux;
    FT_Face           root    = (FT_Face)&face->root;

    FT_UNUSED( num_params );
    FT_UNUSED( params );
    FT_UNUSED( face_index );
    FT_UNUSED( stream );


    face->ttf_face       = NULL;
    face->root.num_faces = 1;

    face->psnames = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
                                             "psnames" );
    psnames = (PSNames_Service)face->psnames;

    face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
                                           "psaux" );
    psaux = (PSAux_Service)face->psaux;

    /* open the tokenizer, this will also check the font format */
    error = T42_Open_Face( face );
    if ( error )
      goto Exit;

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

    /* check the face index */
    if ( face_index != 0 )
    {
      FT_ERROR(( "T42_Face_Init: invalid face index\n" ));
      error = T42_Err_Invalid_Argument;
      goto Exit;
    }

    /* Now, load the font program into the face object */

    /* Init the face object fields */
    /* Now set up root face fields */

    root->num_glyphs   = face->type1.num_glyphs;
    root->num_charmaps = 0;
    root->face_index   = face_index;

    root->face_flags  = FT_FACE_FLAG_SCALABLE;
    root->face_flags |= FT_FACE_FLAG_HORIZONTAL;
    root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;

    if ( face->type1.font_info.is_fixed_pitch )
      root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

    /* XXX: TODO -- add kerning with .afm support */

    /* get style name -- be careful, some broken fonts only */
    /* have a `/FontName' dictionary entry!                 */
    root->family_name = face->type1.font_info.family_name;
    if ( root->family_name )
    {
      char*  full   = face->type1.font_info.full_name;
      char*  family = root->family_name;


      if ( full )
      {
        while ( *family && *full == *family )
        {
          family++;
          full++;
        }

        root->style_name = ( *full == ' ' ? full + 1
                                          : (char *)"Regular" );
      }
      else
        root->style_name = (char *)"Regular";
    }
    else
    {
      /* do we have a `/FontName'? */
      if ( face->type1.font_name )
      {
        root->family_name = face->type1.font_name;
        root->style_name  = (char *)"Regular";
      }
    }

    /* no embedded bitmap support */
    root->num_fixed_sizes = 0;
    root->available_sizes = 0;

    /* Load the TTF font embedded in the T42 font */
    error = FT_New_Memory_Face( FT_FACE_LIBRARY( face ),
                                face->ttf_data,
                                face->ttf_size,
                                0,
                                &face->ttf_face );
    if ( error )
      goto Exit;

    FT_Done_Size( face->ttf_face->size );

    /* Ignore info in FontInfo dictionary and use the info from the  */
    /* loaded TTF font.  The PostScript interpreter also ignores it. */
    root->bbox         = face->ttf_face->bbox;
    root->units_per_EM = face->ttf_face->units_per_EM;

    root->ascender  = face->ttf_face->ascender;
    root->descender = face->ttf_face->descender;
    root->height    = face->ttf_face->height;

    root->max_advance_width  = face->ttf_face->max_advance_width;
    root->max_advance_height = face->ttf_face->max_advance_height;

    root->underline_position  = face->type1.font_info.underline_position;
    root->underline_thickness = face->type1.font_info.underline_thickness;

    root->internal->max_points   = 0;
    root->internal->max_contours = 0;

    /* compute style flags */
    root->style_flags = 0;
    if ( face->type1.font_info.italic_angle )
      root->style_flags |= FT_STYLE_FLAG_ITALIC;

    if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )
      root->style_flags |= FT_STYLE_FLAG_BOLD;

    if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )
      root->face_flags |= FT_FACE_FLAG_VERTICAL;

    {
      if ( psnames && psaux )
      {
        FT_CharMapRec    charmap;
        T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
        FT_CMap_Class    clazz;


        charmap.face = root;

        /* first of all, try to synthetize a Unicode charmap */
        charmap.platform_id = 3;
        charmap.encoding_id = 1;
        charmap.encoding    = FT_ENCODING_UNICODE;

        FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );

        /* now, generate an Adobe Standard encoding when appropriate */
        charmap.platform_id = 7;
        clazz               = NULL;

        switch ( face->type1.encoding_type )
        {
        case T1_ENCODING_TYPE_STANDARD:
          charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
          charmap.encoding_id = 0;
          clazz               = cmap_classes->standard;
          break;

        case T1_ENCODING_TYPE_EXPERT:
          charmap.encoding    = FT_ENCODING_ADOBE_EXPERT;
          charmap.encoding_id = 1;
          clazz               = cmap_classes->expert;
          break;

        case T1_ENCODING_TYPE_ARRAY:
          charmap.encoding    = FT_ENCODING_ADOBE_CUSTOM;
          charmap.encoding_id = 2;
          clazz               = cmap_classes->custom;
          break;

        case T1_ENCODING_TYPE_ISOLATIN1:
          charmap.encoding    = FT_ENCODING_ADOBE_LATIN_1;
          charmap.encoding_id = 3;
          clazz               = cmap_classes->unicode;
          break;

        default:
          ;
        }

        if ( clazz )
          FT_CMap_New( clazz, NULL, &charmap, NULL );

#if 0
        /* Select default charmap */
        if (root->num_charmaps)
          root->charmap = root->charmaps[0];
#endif
      }
    }
  Exit:
    return error;
  }
예제 #14
0
  static FT_Error
  FNT_Face_Init( FT_Stream      stream,
                 FNT_Face       face,
                 FT_Int         face_index,
                 FT_Int         num_params,
                 FT_Parameter*  params )
  {
    FT_Error   error;
    FT_Memory  memory = FT_FACE_MEMORY( face );

    FT_UNUSED( num_params );
    FT_UNUSED( params );
    FT_UNUSED( face_index );


    /* try to load several fonts from a DLL */
    error = fnt_face_get_dll_fonts( face );
    if ( error )
    {
      /* this didn't work, now try to load a single FNT font */
      FNT_Font  font;


      if ( FT_NEW( face->fonts ) )
        goto Exit;

      face->num_fonts = 1;
      font            = face->fonts;

      font->offset   = 0;
      font->fnt_size = stream->size;

      error = fnt_font_load( font, stream );
      if ( error )
        goto Fail;
    }

    /* all right, one or more fonts were loaded; we now need to */
    /* fill the root FT_Face fields with relevant information   */
    {
      FT_Face   root  = FT_FACE( face );
      FNT_Font  fonts = face->fonts;
      FNT_Font  limit = fonts + face->num_fonts;
      FNT_Font  cur;


      root->num_faces  = 1;
      root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
                         FT_FACE_FLAG_HORIZONTAL;

      if ( fonts->header.avg_width == fonts->header.max_width )
        root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;

      if ( fonts->header.italic )
        root->style_flags |= FT_STYLE_FLAG_ITALIC;

      if ( fonts->header.weight >= 800 )
        root->style_flags |= FT_STYLE_FLAG_BOLD;

      /* Setup the `fixed_sizes' array */
      if ( FT_NEW_ARRAY( root->available_sizes, face->num_fonts ) )
        goto Fail;

      root->num_fixed_sizes = face->num_fonts;

      {
        FT_Bitmap_Size*  size = root->available_sizes;


        for ( cur = fonts; cur < limit; cur++, size++ )
        {
          size->width  = cur->header.pixel_width;
          size->height = cur->header.pixel_height;
        }
      }

#ifdef FT_CONFIG_OPTION_USE_CMAPS

      {
        FT_CharMapRec  charmap;

        charmap.encoding    = ft_encoding_unicode;
        charmap.platform_id = 3;
        charmap.encoding_id = 1;
        charmap.face        = root;

        error = FT_CMap_New( fnt_cmap_class,
                             NULL,
                             &charmap,
                             NULL );
        if ( error )
          goto Fail;

        /* Select default charmap */
        if ( root->num_charmaps )
          root->charmap = root->charmaps[0];
      }

#else /* !FT_CONFIG_OPTION_USE_CMAPS */

      /* Setup the `charmaps' array */
      root->charmaps     = &face->charmap_handle;
      root->num_charmaps = 1;

      face->charmap.encoding    = ft_encoding_unicode;
      face->charmap.platform_id = 3;
      face->charmap.encoding_id = 1;
      face->charmap.face        = root;

      face->charmap_handle = &face->charmap;

      root->charmap = face->charmap_handle;

#endif /* !FT_CONFIG_OPTION_USE_CMAPS */

      /* setup remaining flags */
      root->num_glyphs = fonts->header.last_char -
                         fonts->header.first_char + 1;

      root->family_name = (FT_String*)fonts->fnt_frame +
                          fonts->header.face_name_offset;
      root->style_name  = (char *)"Regular";

      if ( root->style_flags & FT_STYLE_FLAG_BOLD )
      {
        if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
          root->style_name = (char *)"Bold Italic";
        else
          root->style_name = (char *)"Bold";
      }
      else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
        root->style_name = (char *)"Italic";
    }

  Fail:
    if ( error )
      FNT_Face_Done( face );

  Exit:
    return error;
  }