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;
    PSNames_Service   psnames;
    PSHinter_Service  pshinter;
    FT_Bool           pure_cff    = 1;
    FT_Bool           sfnt_format = 0;


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

    psnames = (PSNames_Service)FT_Get_Module_Interface(
                face->root.driver->root.library, "psnames" );

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

    /* 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_UInt    flags;


      if ( FT_NEW( cff ) )
        goto Exit;

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

      cff->pshinter = pshinter;

      /* 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;

        /* retrieve font family & style name */
        root->family_name  = CFF_Get_Name( &cff->name_index, face_index );
        if ( dict->cid_registry )
          root->style_name = CFF_StrCopy( memory, "Regular" );  /* XXXX */
        else
          root->style_name = CFF_Get_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;
        
        /* XXX: no charmaps for pure CFF fonts currently! */
      }
    }

  Exit:
    return error;

  Bad_Format:
    error = CFF_Err_Unknown_File_Format;
    goto Exit;
  }
Beispiel #2
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;
  }