Ejemplo n.º 1
0
  af_face_globals_is_digit( AF_FaceGlobals  globals,
                            FT_UInt         gindex )
  {
    if ( gindex < (FT_ULong)globals->glyph_count )
      return FT_BOOL( globals->glyph_styles[gindex] & AF_DIGIT );

    return FT_BOOL( 0 );
  }
Ejemplo n.º 2
0
  ftc_snode_compare( FTC_Node    ftcsnode,
                     FT_Pointer  ftcgquery,
                     FTC_Cache   cache )
  {
    FTC_SNode   snode  = (FTC_SNode)ftcsnode;
    FTC_GQuery  gquery = (FTC_GQuery)ftcgquery;
    FTC_GNode   gnode  = FTC_GNODE( snode );
    FT_UInt     gindex = gquery->gindex;
    FT_Bool     result;


    result = FT_BOOL( gnode->family == gquery->family                    &&
                      (FT_UInt)( gindex - gnode->gindex ) < snode->count );
    if ( result )
    {
      /* check if we need to load the glyph bitmap now */
      FTC_SBit  sbit = snode->sbits + ( gindex - gnode->gindex );


      if ( sbit->buffer == NULL && sbit->width != 255 )
      {
        FT_ULong  size;


        if ( !ftc_snode_load( snode, cache->manager,
                              gindex, &size ) )
        {
          cache->manager->cur_weight += size;
        }
      }
    }

    return result;
  }
Ejemplo n.º 3
0
  static FT_Bool
  gxv_kern_coverage_classic_microsoft_validate( FT_UShort      coverage,
                                                FT_UShort*     format,
                                                GXV_Validator  gxvalid )
  {
    /* classic Microsoft-dialect */
#ifdef GXV_LOAD_TRACE_VARS
    FT_Bool  horizontal;
    FT_Bool  minimum;
    FT_Bool  cross_stream;
    FT_Bool  override;
#endif

    FT_UNUSED( gxvalid );


    /* reserved bits = 0 */
    if ( coverage & 0xFDF0 )
      return FALSE;

#ifdef GXV_LOAD_TRACE_VARS
    horizontal   = FT_BOOL(   coverage        & 1 );
    minimum      = FT_BOOL( ( coverage >> 1 ) & 1 );
    cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 );
    override     = FT_BOOL( ( coverage >> 3 ) & 1 );
Ejemplo n.º 4
0
  ftc_cmap_node_compare( FTC_CMapNode   cnode,
                         FTC_CMapQuery  cquery )
  {
    FT_UInt32  offset = (FT_UInt32)( cquery->char_code - cnode->first );


    return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
  }
Ejemplo n.º 5
0
  ftc_glyph_node_compare( FTC_GlyphNode   gnode,
                          FTC_GlyphQuery  gquery )
  {
    FT_UInt  start = (FT_UInt)gnode->item_start;
    FT_UInt  count = (FT_UInt)gnode->item_count;

    return FT_BOOL( (FT_UInt)( gquery->gindex - start ) < count );
  }
Ejemplo n.º 6
0
  static FT_Bool
  ft_cubic_is_small_enough( FT_Vector*  base,
                            FT_Angle   *angle_in,
                            FT_Angle   *angle_mid,
                            FT_Angle   *angle_out )
  {
    FT_Vector  d1, d2, d3;
    FT_Angle   theta1, theta2;
    FT_Int     close1, close2, close3;


    d1.x = base[2].x - base[3].x;
    d1.y = base[2].y - base[3].y;
    d2.x = base[1].x - base[2].x;
    d2.y = base[1].y - base[2].y;
    d3.x = base[0].x - base[1].x;
    d3.y = base[0].y - base[1].y;

    close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
    close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
    close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y );

    if ( close1 || close3 )
    {
      if ( close2 )
      {
        /* basically a point */
        *angle_in = *angle_out = *angle_mid = 0;
      }
      else if ( close1 )
      {
        *angle_in  = *angle_mid = FT_Atan2( d2.x, d2.y );
        *angle_out = FT_Atan2( d3.x, d3.y );
      }
      else  /* close2 */
      {
        *angle_in  = FT_Atan2( d1.x, d1.y );
        *angle_mid = *angle_out = FT_Atan2( d2.x, d2.y );
      }
    }
    else if ( close2 )
    {
      *angle_in  = *angle_mid = FT_Atan2( d1.x, d1.y );
      *angle_out = FT_Atan2( d3.x, d3.y );
    }
    else
    {
      *angle_in  = FT_Atan2( d1.x, d1.y );
      *angle_mid = FT_Atan2( d2.x, d2.y );
      *angle_out = FT_Atan2( d3.x, d3.y );
    }

    theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in,  *angle_mid ) );
    theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) );

    return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD &&
                    theta2 < FT_SMALL_CUBIC_THRESHOLD );
  }
Ejemplo n.º 7
0
  ftc_face_node_compare( FTC_MruNode  ftcnode,
                         FT_Pointer   ftcface_id )
  {
    FTC_FaceNode  node    = (FTC_FaceNode)ftcnode;
    FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;


    return FT_BOOL( node->face_id == face_id );
  }
Ejemplo n.º 8
0
  ftc_size_node_compare( FTC_SizeNode   node,
                         FTC_SizeQuery  query )
  {
    FT_Size  size = node->size;


    return FT_BOOL( size->face                    == query->face   &&
                    (FT_UInt)size->metrics.x_ppem == query->width  &&
                    (FT_UInt)size->metrics.y_ppem == query->height );
  }
Ejemplo n.º 9
0
  ftc_cmap_node_remove_faceid( FTC_Node    ftcnode,
                               FT_Pointer  ftcface_id,
                               FTC_Cache   cache )
  {
    FTC_CMapNode  node    = (FTC_CMapNode)ftcnode;
    FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
    FT_UNUSED( cache );

    return FT_BOOL( node->face_id == face_id );
  }
Ejemplo n.º 10
0
  /* helper function used by ftc_face_node_done */
  static FT_Bool
  ftc_size_node_compare_faceid( FTC_MruNode  ftcnode,
                                FT_Pointer   ftcface_id )
  {
    FTC_SizeNode  node    = (FTC_SizeNode)ftcnode;
    FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;


    return FT_BOOL( node->scaler.face_id == face_id );
  }
Ejemplo n.º 11
0
  ftc_gnode_compare( FTC_Node    ftcgnode,
                     FT_Pointer  ftcgquery,
                     FTC_Cache   cache )
  {
    FTC_GNode   gnode  = (FTC_GNode)ftcgnode;
    FTC_GQuery  gquery = (FTC_GQuery)ftcgquery;
    FT_UNUSED( cache );


    return FT_BOOL( gnode->family == gquery->family &&
                    gnode->gindex == gquery->gindex );
  }
Ejemplo n.º 12
0
  ftc_image_family_compare( FTC_ImageFamily  ifam,
                            FTC_ImageQuery   iquery )
  {
    FT_Bool  result;


    result = FT_BOOL( FTC_IMAGE_TYPE_COMPARE( &ifam->type, &iquery->type ) );
    if ( result )
      FTC_GLYPH_FAMILY_FOUND( ifam, iquery );

    return result;
  }
Ejemplo n.º 13
0
  ftc_cmap_node_remove_faceid( FTC_Node    ftcnode,
                               FT_Pointer  ftcface_id,
                               FTC_Cache   cache,
                               FT_Bool*    list_changed )
  {
    FTC_CMapNode  node    = (FTC_CMapNode)ftcnode;
    FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
    FT_UNUSED( cache );


    if ( list_changed )
      *list_changed = FALSE;
    return FT_BOOL( node->face_id == face_id );
  }
Ejemplo n.º 14
0
  ftc_gnode_compare( FTC_Node    ftcgnode,
                     FT_Pointer  ftcgquery,
                     FTC_Cache   cache,
                     FT_Bool*    list_changed )
  {
    FTC_GNode   gnode  = (FTC_GNode)ftcgnode;
    FTC_GQuery  gquery = (FTC_GQuery)ftcgquery;
    FT_UNUSED( cache );


    if ( list_changed )
      *list_changed = FALSE;
    return FT_BOOL( gnode->family == gquery->family &&
                    gnode->gindex == gquery->gindex );
  }
Ejemplo n.º 15
0
  ftc_cmap_node_compare( FTC_Node    ftcnode,
                         FT_Pointer  ftcquery,
                         FTC_Cache   cache )
  {
    FTC_CMapNode   node  = (FTC_CMapNode)ftcnode;
    FTC_CMapQuery  query = (FTC_CMapQuery)ftcquery;
    FT_UNUSED( cache );


    if ( node->face_id    == query->face_id    &&
         node->cmap_index == query->cmap_index )
    {
      FT_UInt32  offset = (FT_UInt32)( query->char_code - node->first );


      return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
    }

    return 0;
  }
Ejemplo n.º 16
0
  ftc_basic_gnode_compare_faceid( FTC_Node    ftcgnode,
                                  FT_Pointer  ftcface_id,
                                  FTC_Cache   cache )
  {
    FTC_GNode        gnode   = (FTC_GNode)ftcgnode;
    FTC_FaceID       face_id = (FTC_FaceID)ftcface_id;
    FTC_BasicFamily  family  = (FTC_BasicFamily)gnode->family;
    FT_Bool          result;


    result = FT_BOOL( family->attrs.scaler.face_id == face_id );
    if ( result )
    {
      /* we must call this function to avoid this node from appearing
       * in later lookups with the same face_id!
       */
      FTC_GNode_UnselectFamily( gnode, cache );
    }
    return result;
  }
Ejemplo n.º 17
0
  ftc_cmap_family_compare( FTC_CMapFamily  cfam,
                           FTC_CMapQuery   cquery )
  {
    FT_Int  result = 0;


    /* first, compare face id and type */
    if ( cfam->desc.face_id != cquery->desc->face_id ||
         cfam->desc.type    != cquery->desc->type    )
      goto Exit;

    switch ( cfam->desc.type )
    {
    case FTC_CMAP_BY_INDEX:
      result = ( cfam->desc.u.index == cquery->desc->u.index );
      break;

    case FTC_CMAP_BY_ENCODING:
      result = ( cfam->desc.u.encoding == cquery->desc->u.encoding );
      break;

    case FTC_CMAP_BY_ID:
      result = ( cfam->desc.u.id.platform == cquery->desc->u.id.platform &&
                 cfam->desc.u.id.encoding == cquery->desc->u.id.encoding );
      break;

    default:
      ;
    }

    if ( result )
    {
      /* when found, update the 'family' and 'hash' field of the query */
      FTC_QUERY( cquery )->family = FTC_FAMILY( cfam );
      FTC_QUERY( cquery )->hash   = FTC_CMAP_HASH( cfam, cquery );
    }

  Exit:
    return FT_BOOL( result );
  }
Ejemplo n.º 18
0
  static FT_Bool
  ft_conic_is_small_enough( FT_Vector*  base,
                            FT_Angle   *angle_in,
                            FT_Angle   *angle_out )
  {
    FT_Vector  d1, d2;
    FT_Angle   theta;
    FT_Int     close1, close2;


    d1.x = base[1].x - base[2].x;
    d1.y = base[1].y - base[2].y;
    d2.x = base[0].x - base[1].x;
    d2.y = base[0].y - base[1].y;

    close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
    close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );

    if ( close1 )
    {
      if ( close2 )
        *angle_in = *angle_out = 0;
      else
        *angle_in = *angle_out = FT_Atan2( d2.x, d2.y );
    }
    else if ( close2 )
    {
      *angle_in = *angle_out = FT_Atan2( d1.x, d1.y );
    }
    else
    {
      *angle_in  = FT_Atan2( d1.x, d1.y );
      *angle_out = FT_Atan2( d2.x, d2.y );
    }

    theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) );

    return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD );
  }
Ejemplo n.º 19
0
  static FT_Bool
  gxv_kern_coverage_classic_microsoft_validate( FT_UShort      coverage,
                                                FT_UShort*     format,
                                                GXV_Validator  valid )
  {
    /* classic Microsoft-dialect */
    FT_Bool  horizontal;
    FT_Bool  minimum;
    FT_Bool  cross_stream;
    FT_Bool  override;

    FT_UNUSED( valid );


    /* reserved bits = 0 */
    if ( coverage & 0xFDF0 )
      return 0;

    horizontal   = FT_BOOL(   coverage        & 1 );
    minimum      = FT_BOOL( ( coverage >> 1 ) & 1 );
    cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 );
    override     = FT_BOOL( ( coverage >> 3 ) & 1 );
Ejemplo n.º 20
0
  cff_font_load( FT_Stream  stream,
                 FT_Int     face_index,
                 CFF_Font   font,
                 FT_Bool    pure_cff )
  {
    static const FT_Frame_Field  cff_header_fields[] =
    {
#undef  FT_STRUCTURE
#define FT_STRUCTURE  CFF_FontRec

      FT_FRAME_START( 4 ),
        FT_FRAME_BYTE( version_major ),
        FT_FRAME_BYTE( version_minor ),
        FT_FRAME_BYTE( header_size ),
        FT_FRAME_BYTE( absolute_offsize ),
      FT_FRAME_END
    };

    FT_Error         error;
    FT_Memory        memory = stream->memory;
    FT_ULong         base_offset;
    CFF_FontRecDict  dict;


    FT_ZERO( font );

    font->stream = stream;
    font->memory = memory;
    dict         = &font->top_font.font_dict;
    base_offset  = FT_STREAM_POS();

    /* read CFF font header */
    if ( FT_STREAM_READ_FIELDS( cff_header_fields, font ) )
      goto Exit;

    /* check format */
    if ( font->version_major   != 1 ||
         font->header_size      < 4 ||
         font->absolute_offsize > 4 )
    {
      FT_TRACE2(( "[not a CFF font header!]\n" ));
      error = CFF_Err_Unknown_File_Format;
      goto Exit;
    }

    /* skip the rest of the header */
    if ( FT_STREAM_SKIP( font->header_size - 4 ) )
      goto Exit;

    /* read the name, top dict, string and global subrs index */
    if ( FT_SET_ERROR( cff_index_init( &font->name_index,
                                       stream, 0 ) )              ||
         FT_SET_ERROR( cff_index_init( &font->font_dict_index,
                                       stream, 0 ) )              ||
         FT_SET_ERROR( cff_index_init( &font->string_index,
                                       stream, 0 ) )              ||
         FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
                                       stream, 1 ) )              )
      goto Exit;

    /* well, we don't really forget the `disabled' fonts... */
    font->num_faces = font->name_index.count;
    if ( face_index >= (FT_Int)font->num_faces )
    {
      FT_ERROR(( "cff_font_load: incorrect face index = %d\n",
                 face_index ));
      error = CFF_Err_Invalid_Argument;
    }

    /* in case of a font format check, simply exit now */
    if ( face_index < 0 )
      goto Exit;

    /* now, parse the top-level font dictionary */
    error = cff_subfont_load( &font->top_font,
                              &font->font_dict_index,
                              face_index,
                              stream,
                              base_offset );
    if ( error )
      goto Exit;

    if ( FT_STREAM_SEEK( base_offset + dict->charstrings_offset ) )
      goto Exit;

    error = cff_index_init( &font->charstrings_index, stream, 0 );
    if ( error )
      goto Exit;

    /* now, check for a CID font */
    if ( dict->cid_registry != 0xFFFFU )
    {
      CFF_IndexRec  fd_index;
      CFF_SubFont   sub;
      FT_UInt       idx;


      /* this is a CID-keyed font, we must now allocate a table of */
      /* sub-fonts, then load each of them separately              */
      if ( FT_STREAM_SEEK( base_offset + dict->cid_fd_array_offset ) )
        goto Exit;

      error = cff_index_init( &fd_index, stream, 0 );
      if ( error )
        goto Exit;

      if ( fd_index.count > CFF_MAX_CID_FONTS )
      {
        FT_ERROR(( "cff_font_load: FD array too large in CID font\n" ));
        goto Fail_CID;
      }

      /* allocate & read each font dict independently */
      font->num_subfonts = fd_index.count;
      if ( FT_NEW_ARRAY( sub, fd_index.count ) )
        goto Fail_CID;

      /* set up pointer table */
      for ( idx = 0; idx < fd_index.count; idx++ )
        font->subfonts[idx] = sub + idx;

      /* now load each subfont independently */
      for ( idx = 0; idx < fd_index.count; idx++ )
      {
        sub = font->subfonts[idx];
        error = cff_subfont_load( sub, &fd_index, idx,
                                  stream, base_offset );
        if ( error )
          goto Fail_CID;
      }

      /* now load the FD Select array */
      error = CFF_Load_FD_Select( &font->fd_select,
                                  font->charstrings_index.count,
                                  stream,
                                  base_offset + dict->cid_fd_select_offset );

    Fail_CID:
      cff_index_done( &fd_index );

      if ( error )
        goto Exit;
    }
    else
      font->num_subfonts = 0;

    /* read the charstrings index now */
    if ( dict->charstrings_offset == 0 )
    {
      FT_ERROR(( "cff_font_load: no charstrings offset!\n" ));
      error = CFF_Err_Unknown_File_Format;
      goto Exit;
    }

    /* explicit the global subrs */
    font->num_global_subrs = font->global_subrs_index.count;
    font->num_glyphs       = font->charstrings_index.count;

    error = cff_index_get_pointers( &font->global_subrs_index,
                                    &font->global_subrs ) ;

    if ( error )
      goto Exit;

    /* read the Charset and Encoding tables if available */
    if ( font->num_glyphs > 0 )
    {
      FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );


      error = cff_charset_load( &font->charset, font->num_glyphs, stream,
                                base_offset, dict->charset_offset, invert );
      if ( error )
        goto Exit;

      /* CID-keyed CFFs don't have an encoding */
      if ( dict->cid_registry == 0xFFFFU )
      {
        error = cff_encoding_load( &font->encoding,
                                   &font->charset,
                                   font->num_glyphs,
                                   stream,
                                   base_offset,
                                   dict->encoding_offset );
        if ( error )
          goto Exit;
      }
      else
        /* CID-keyed fonts only need CIDs */
        FT_FREE( font->charset.sids );
    }

    /* get the font name (/CIDFontName for CID-keyed fonts, */
    /* /FontName otherwise)                                 */
    font->font_name = cff_index_get_name( &font->name_index, face_index );

  Exit:
    return error;
  }
Ejemplo n.º 21
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;
  }
Ejemplo n.º 22
0
  pfr_slot_load( FT_GlyphSlot  pfrslot,         /* PFR_Slot */
                 FT_Size       pfrsize,         /* PFR_Size */
                 FT_UInt       gindex,
                 FT_Int32      load_flags )
  {
    PFR_Slot     slot    = (PFR_Slot)pfrslot;
    PFR_Size     size    = (PFR_Size)pfrsize;
    FT_Error     error;
    PFR_Face     face    = (PFR_Face)pfrslot->face;
    PFR_Char     gchar;
    FT_Outline*  outline = &pfrslot->outline;
    FT_ULong     gps_offset;


    if ( gindex > 0 )
      gindex--;

    /* check that the glyph index is correct */
    FT_ASSERT( gindex < face->phy_font.num_chars );

    /* try to load an embedded bitmap */
    if ( ( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP ) ) == 0 )
    {
      error = pfr_slot_load_bitmap( slot, size, gindex );
      if ( error == 0 )
        goto Exit;
    }

    if ( load_flags & FT_LOAD_SBITS_ONLY )
    {
      error = PFR_Err_Invalid_Argument;
      goto Exit;
    }

    gchar               = face->phy_font.chars + gindex;
    pfrslot->format     = FT_GLYPH_FORMAT_OUTLINE;
    outline->n_points   = 0;
    outline->n_contours = 0;
    gps_offset          = face->header.gps_section_offset;

    /* load the glyph outline (FT_LOAD_NO_RECURSE isn't supported) */
    error = pfr_glyph_load( &slot->glyph, face->root.stream,
                            gps_offset, gchar->gps_offset, gchar->gps_size );

    if ( !error )
    {
      FT_BBox            cbox;
      FT_Glyph_Metrics*  metrics = &pfrslot->metrics;
      FT_Pos             advance;
      FT_Int             em_metrics, em_outline;
      FT_Bool            scaling;


      scaling = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );

      /* copy outline data */
      *outline = slot->glyph.loader->base.outline;

      outline->flags &= ~FT_OUTLINE_OWNER;
      outline->flags |= FT_OUTLINE_REVERSE_FILL;

      if ( size && pfrsize->metrics.y_ppem < 24 )
        outline->flags |= FT_OUTLINE_HIGH_PRECISION;

      /* compute the advance vector */
      metrics->horiAdvance = 0;
      metrics->vertAdvance = 0;

      advance    = gchar->advance;
      em_metrics = face->phy_font.metrics_resolution;
      em_outline = face->phy_font.outline_resolution;

      if ( em_metrics != em_outline )
        advance = FT_MulDiv( advance, em_outline, em_metrics );

      if ( face->phy_font.flags & PFR_PHY_VERTICAL )
        metrics->vertAdvance = advance;
      else
        metrics->horiAdvance = advance;

      pfrslot->linearHoriAdvance = metrics->horiAdvance;
      pfrslot->linearVertAdvance = metrics->vertAdvance;

      /* make-up vertical metrics(?) */
      metrics->vertBearingX = 0;
      metrics->vertBearingY = 0;

      /* Apply the font matrix, if any.                 */
      /* TODO: Test existing fonts with unusual matrix  */
      /* whether we have to adjust Units per EM.        */
      {
        FT_Matrix font_matrix;


        font_matrix.xx = face->log_font.matrix[0] << 8;
        font_matrix.yx = face->log_font.matrix[1] << 8;
        font_matrix.xy = face->log_font.matrix[2] << 8;
        font_matrix.yy = face->log_font.matrix[3] << 8;

        FT_Outline_Transform( outline, &font_matrix );
      }

      /* scale when needed */
      if ( scaling )
      {
        FT_Int      n;
        FT_Fixed    x_scale = pfrsize->metrics.x_scale;
        FT_Fixed    y_scale = pfrsize->metrics.y_scale;
        FT_Vector*  vec     = outline->points;


        /* scale outline points */
        for ( n = 0; n < outline->n_points; n++, vec++ )
        {
          vec->x = FT_MulFix( vec->x, x_scale );
          vec->y = FT_MulFix( vec->y, y_scale );
        }

        /* scale the advance */
        metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
        metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
      }

      /* compute the rest of the metrics */
      FT_Outline_Get_CBox( outline, &cbox );

      metrics->width        = cbox.xMax - cbox.xMin;
      metrics->height       = cbox.yMax - cbox.yMin;
      metrics->horiBearingX = cbox.xMin;
      metrics->horiBearingY = cbox.yMax - metrics->height;
    }

  Exit:
    return error;
  }
Ejemplo n.º 23
0
  T1_Load_Glyph( FT_GlyphSlot  t1glyph,          /* T1_GlyphSlot */
                 FT_Size       t1size,           /* T1_Size      */
                 FT_UInt       glyph_index,
                 FT_Int32      load_flags )
  {
    T1_GlyphSlot            glyph = (T1_GlyphSlot)t1glyph;
    FT_Error                error;
#ifdef __REACTOS__
    T1_DecoderRec *decoder = malloc(sizeof(T1_DecoderRec));
/* Ugly but it allows us to reduce the diff */
#define decoder (*decoder)
#else
    T1_DecoderRec           decoder;
#endif
    T1_Face                 face = (T1_Face)t1glyph->face;
    FT_Bool                 hinting;
    T1_Font                 type1         = &face->type1;
    PSAux_Service           psaux         = (PSAux_Service)face->psaux;
    const T1_Decoder_Funcs  decoder_funcs = psaux->t1_decoder_funcs;

    FT_Matrix               font_matrix;
    FT_Vector               font_offset;
    FT_Data                 glyph_data;
    FT_Bool                 must_finish_decoder = FALSE;
#ifdef FT_CONFIG_OPTION_INCREMENTAL
    FT_Bool                 glyph_data_loaded = 0;
#endif


#ifdef FT_CONFIG_OPTION_INCREMENTAL
    if ( glyph_index >= (FT_UInt)face->root.num_glyphs &&
         !face->root.internal->incremental_interface   )
#else
    if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
    {
      error = FT_THROW( Invalid_Argument );
      goto Exit;
    }

    FT_TRACE1(( "T1_Load_Glyph: glyph index %d\n", glyph_index ));

    FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );

    if ( load_flags & FT_LOAD_NO_RECURSE )
      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;

    if ( t1size )
    {
      glyph->x_scale = t1size->metrics.x_scale;
      glyph->y_scale = t1size->metrics.y_scale;
    }
    else
    {
      glyph->x_scale = 0x10000L;
      glyph->y_scale = 0x10000L;
    }

    t1glyph->outline.n_points   = 0;
    t1glyph->outline.n_contours = 0;

    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );

    t1glyph->format = FT_GLYPH_FORMAT_OUTLINE;

    error = decoder_funcs->init( &decoder,
                                 t1glyph->face,
                                 t1size,
                                 t1glyph,
                                 (FT_Byte**)type1->glyph_names,
                                 face->blend,
                                 FT_BOOL( hinting ),
                                 FT_LOAD_TARGET_MODE( load_flags ),
                                 T1_Parse_Glyph );
    if ( error )
      goto Exit;

    must_finish_decoder = TRUE;

    decoder.builder.no_recurse = FT_BOOL(
                                   ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );

    decoder.num_subrs     = type1->num_subrs;
    decoder.subrs         = type1->subrs;
    decoder.subrs_len     = type1->subrs_len;

    decoder.buildchar     = face->buildchar;
    decoder.len_buildchar = face->len_buildchar;

    /* now load the unscaled outline */
    error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index,
                                                &glyph_data );
    if ( error )
      goto Exit;
#ifdef FT_CONFIG_OPTION_INCREMENTAL
    glyph_data_loaded = 1;
#endif

    font_matrix = decoder.font_matrix;
    font_offset = decoder.font_offset;

    /* save new glyph tables */
    decoder_funcs->done( &decoder );

    must_finish_decoder = FALSE;

    /* now, set the metrics -- this is rather simple, as   */
    /* the left side bearing is the xMin, and the top side */
    /* bearing the yMax                                    */
    if ( !error )
    {
      t1glyph->outline.flags &= FT_OUTLINE_OWNER;
      t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL;

      /* for composite glyphs, return only left side bearing and */
      /* advance width                                           */
      if ( load_flags & FT_LOAD_NO_RECURSE )
      {
        FT_Slot_Internal  internal = t1glyph->internal;


        t1glyph->metrics.horiBearingX =
          FIXED_TO_INT( decoder.builder.left_bearing.x );
        t1glyph->metrics.horiAdvance  =
          FIXED_TO_INT( decoder.builder.advance.x );

        internal->glyph_matrix      = font_matrix;
        internal->glyph_delta       = font_offset;
        internal->glyph_transformed = 1;
      }
      else
      {
        FT_BBox            cbox;
        FT_Glyph_Metrics*  metrics = &t1glyph->metrics;


        /* copy the _unscaled_ advance width */
        metrics->horiAdvance =
          FIXED_TO_INT( decoder.builder.advance.x );
        t1glyph->linearHoriAdvance =
          FIXED_TO_INT( decoder.builder.advance.x );
        t1glyph->internal->glyph_transformed = 0;

        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
        {
          /* make up vertical ones */
          metrics->vertAdvance = ( face->type1.font_bbox.yMax -
                                   face->type1.font_bbox.yMin ) >> 16;
          t1glyph->linearVertAdvance = metrics->vertAdvance;
        }
        else
        {
Ejemplo n.º 24
0
  T1_Get_Private_Dict( T1_Parser      parser,
                       PSAux_Service  psaux )
  {
    FT_Stream  stream = parser->stream;
    FT_Memory  memory = parser->root.memory;
    FT_Error   error  = FT_Err_Ok;
    FT_ULong   size;


    if ( parser->in_pfb )
    {
      /* in the case of the PFB format, the private dictionary can be  */
      /* made of several segments.  We thus first read the number of   */
      /* segments to compute the total size of the private dictionary  */
      /* then re-read them into memory.                                */
      FT_ULong   start_pos = FT_STREAM_POS();
      FT_UShort  tag;


      parser->private_len = 0;
      for (;;)
      {
        error = read_pfb_tag( stream, &tag, &size );
        if ( error )
          goto Fail;

        if ( tag != 0x8002U )
          break;

        parser->private_len += size;

        if ( FT_STREAM_SKIP( size ) )
          goto Fail;
      }

      /* Check that we have a private dictionary there */
      /* and allocate private dictionary buffer        */
      if ( parser->private_len == 0 )
      {
        FT_ERROR(( "T1_Get_Private_Dict:"
                   " invalid private dictionary section\n" ));
        error = FT_THROW( Invalid_File_Format );
        goto Fail;
      }

      if ( FT_STREAM_SEEK( start_pos )                           ||
           FT_ALLOC( parser->private_dict, parser->private_len ) )
        goto Fail;

      parser->private_len = 0;
      for (;;)
      {
        error = read_pfb_tag( stream, &tag, &size );
        if ( error || tag != 0x8002U )
        {
          error = FT_Err_Ok;
          break;
        }

        if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
                             size ) )
          goto Fail;

        parser->private_len += size;
      }
    }
    else
    {
      /* We have already `loaded' the whole PFA font file into memory; */
      /* if this is a memory resource, allocate a new block to hold    */
      /* the private dict.  Otherwise, simply overwrite into the base  */
      /* dictionary block in the heap.                                 */

      /* first of all, look at the `eexec' keyword */
      FT_Byte*    cur   = parser->base_dict;
      FT_Byte*    limit = cur + parser->base_len;
      FT_Byte     c;
      FT_Pointer  pos_lf;
      FT_Bool     test_cr;


    Again:
      for (;;)
      {
        c = cur[0];
        if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
                                            /* whitespace + 4 chars        */
        {
          if ( cur[1] == 'e' &&
               cur[2] == 'x' &&
               cur[3] == 'e' &&
               cur[4] == 'c' )
            break;
        }
        cur++;
        if ( cur >= limit )
        {
          FT_ERROR(( "T1_Get_Private_Dict:"
                     " could not find `eexec' keyword\n" ));
          error = FT_THROW( Invalid_File_Format );
          goto Exit;
        }
      }

      /* check whether `eexec' was real -- it could be in a comment */
      /* or string (as e.g. in u003043t.gsf from ghostscript)       */

      parser->root.cursor = parser->base_dict;
      /* set limit to `eexec' + whitespace + 4 characters */
      parser->root.limit  = cur + 10;

      cur   = parser->root.cursor;
      limit = parser->root.limit;

      while ( cur < limit )
      {
        if ( *cur == 'e' && strncmp( (char*)cur, "eexec", 5 ) == 0 )
          goto Found;

        T1_Skip_PS_Token( parser );
        if ( parser->root.error )
          break;
        T1_Skip_Spaces  ( parser );
        cur = parser->root.cursor;
      }

      /* we haven't found the correct `eexec'; go back and continue */
      /* searching                                                  */

      cur   = limit;
      limit = parser->base_dict + parser->base_len;
      goto Again;

      /* now determine where to write the _encrypted_ binary private  */
      /* dictionary.  We overwrite the base dictionary for disk-based */
      /* resources and allocate a new block otherwise                 */

    Found:
      parser->root.limit = parser->base_dict + parser->base_len;

      T1_Skip_PS_Token( parser );
      cur   = parser->root.cursor;
      limit = parser->root.limit;

      /* According to the Type 1 spec, the first cipher byte must not be */
      /* an ASCII whitespace character code (blank, tab, carriage return */
      /* or line feed).  We have seen Type 1 fonts with two line feed    */
      /* characters...  So skip now all whitespace character codes.      */
      /*                                                                 */
      /* On the other hand, Adobe's Type 1 parser handles fonts just     */
      /* fine that are violating this limitation, so we add a heuristic  */
      /* test to stop at \r only if it is not used for EOL.              */

      pos_lf  = ft_memchr( cur, '\n', (size_t)( limit - cur ) );
      test_cr = FT_BOOL( !pos_lf                                       ||
                         pos_lf > ft_memchr( cur,
                                             '\r',
                                             (size_t)( limit - cur ) ) );

      while ( cur < limit                    &&
              ( *cur == ' '                ||
                *cur == '\t'               ||
                (test_cr && *cur == '\r' ) ||
                *cur == '\n'               ) )
        ++cur;
      if ( cur >= limit )
      {
        FT_ERROR(( "T1_Get_Private_Dict:"
                   " `eexec' not properly terminated\n" ));
        error = FT_THROW( Invalid_File_Format );
        goto Exit;
      }

      size = parser->base_len - (FT_ULong)( cur - parser->base_dict );

      if ( parser->in_memory )
      {
        /* note that we allocate one more byte to put a terminating `0' */
        if ( FT_ALLOC( parser->private_dict, size + 1 ) )
          goto Fail;
        parser->private_len = size;
      }
      else
      {
        parser->single_block = 1;
        parser->private_dict = parser->base_dict;
        parser->private_len  = size;
        parser->base_dict    = NULL;
        parser->base_len     = 0;
      }

      /* now determine whether the private dictionary is encoded in binary */
      /* or hexadecimal ASCII format -- decode it accordingly              */

      /* we need to access the next 4 bytes (after the final whitespace */
      /* following the `eexec' keyword); if they all are hexadecimal    */
      /* digits, then we have a case of ASCII storage                   */

      if ( cur + 3 < limit                                &&
           ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
           ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
      {
        /* ASCII hexadecimal encoding */
        FT_ULong  len;


        parser->root.cursor = cur;
        (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
                                                parser->private_dict,
                                                parser->private_len,
                                                &len,
                                                0 );
        parser->private_len = len;

        /* put a safeguard */
        parser->private_dict[len] = '\0';
      }
      else
        /* binary encoding -- copy the private dict */
        FT_MEM_MOVE( parser->private_dict, cur, size );
    }

    /* we now decrypt the encoded binary private dictionary */
    psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );

    if ( parser->private_len < 4 )
    {
      FT_ERROR(( "T1_Get_Private_Dict:"
                 " invalid private dictionary section\n" ));
      error = FT_THROW( Invalid_File_Format );
      goto Fail;
    }

    /* replace the four random bytes at the beginning with whitespace */
    parser->private_dict[0] = ' ';
    parser->private_dict[1] = ' ';
    parser->private_dict[2] = ' ';
    parser->private_dict[3] = ' ';

    parser->root.base   = parser->private_dict;
    parser->root.cursor = parser->private_dict;
    parser->root.limit  = parser->root.cursor + parser->private_len;

  Fail:
  Exit:
    return error;
  }
Ejemplo n.º 25
0
sfnt_load_face(FT_Stream stream,
               TT_Face face,
               FT_Int face_index,
               FT_Int num_params,
               FT_Parameter * params)
{
    FT_Error error;

#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    FT_Error psnames_error;
#endif
    FT_Bool has_outline;
    FT_Bool is_apple_sbit;
    FT_Bool ignore_preferred_family    = FALSE;
    FT_Bool ignore_preferred_subfamily = FALSE;

    SFNT_Service sfnt = (SFNT_Service)face->sfnt;

    FT_UNUSED(face_index);

    /* Check parameters */

    {
        FT_Int i;


        for (i = 0; i < num_params; i++)
        {
            if (params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY)
                ignore_preferred_family = TRUE;
            else if (params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY)
                ignore_preferred_subfamily = TRUE;
        }
    }

    /* Load tables */

    /* We now support two SFNT-based bitmapped font formats.  They */
    /* are recognized easily as they do not include a `glyf'       */
    /* table.                                                      */
    /*                                                             */
    /* The first format comes from Apple, and uses a table named   */
    /* `bhed' instead of `head' to store the font header (using    */
    /* the same format).  It also doesn't include horizontal and   */
    /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
    /* missing).                                                   */
    /*                                                             */
    /* The other format comes from Microsoft, and is used with     */
    /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
    /* it doesn't contain outlines.                                */
    /*                                                             */

    FT_TRACE2(("sfnt_load_face: %08p\n\n", face));

    /* do we have outlines in there? */
#ifdef FT_CONFIG_OPTION_INCREMENTAL
    has_outline = FT_BOOL(face->root.internal->incremental_interface != 0 ||
                          tt_face_lookup_table(face, TTAG_glyf) != 0 ||
                          tt_face_lookup_table(face, TTAG_CFF) != 0);
#else
    has_outline = FT_BOOL(tt_face_lookup_table(face, TTAG_glyf) != 0 ||
                          tt_face_lookup_table(face, TTAG_CFF) != 0);
#endif

    is_apple_sbit = 0;

    /* if this font doesn't contain outlines, we try to load */
    /* a `bhed' table                                        */
    if (!has_outline && sfnt->load_bhed)
    {
        LOAD_(bhed);
        is_apple_sbit = FT_BOOL(!error);
    }

    /* load the font header (`head' table) if this isn't an Apple */
    /* sbit font file                                             */
    if (!is_apple_sbit)
    {
        LOAD_(head);
        if (error)
            goto Exit;
    }

    if (face->header.Units_Per_EM == 0)
    {
        error = SFNT_Err_Invalid_Table;

        goto Exit;
    }

    /* the following tables are often not present in embedded TrueType */
    /* fonts within PDF documents, so don't check for them.            */
    LOAD_(maxp);
    LOAD_(cmap);

    /* the following tables are optional in PCL fonts -- */
    /* don't check for errors                            */
    LOAD_(name);
    LOAD_(post);

#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    psnames_error = error;
#endif

    /* do not load the metrics headers and tables if this is an Apple */
    /* sbit font file                                                 */
    if (!is_apple_sbit)
    {
        /* load the `hhea' and `hmtx' tables */
        LOADM_(hhea, 0);
        if (!error)
        {
            LOADM_(hmtx, 0);
            if (error == SFNT_Err_Table_Missing)
            {
                error = SFNT_Err_Hmtx_Table_Missing;

#ifdef FT_CONFIG_OPTION_INCREMENTAL
                /* If this is an incrementally loaded font and there are */
                /* overriding metrics, tolerate a missing `hmtx' table.  */
                if (face->root.internal->incremental_interface &&
                    face->root.internal->incremental_interface->funcs->
                    get_glyph_metrics)
                {
                    face->horizontal.number_Of_HMetrics = 0;
                    error                               = SFNT_Err_Ok;
                }
#endif
            }
        }
        else if (error == SFNT_Err_Table_Missing)
        {
            /* No `hhea' table necessary for SFNT Mac fonts. */
            if (face->format_tag == TTAG_true)
            {
                FT_TRACE2(("This is an SFNT Mac font.\n"));
                has_outline = 0;
                error       = SFNT_Err_Ok;
            }
            else
            {
                error = SFNT_Err_Horiz_Header_Missing;

#ifdef FT_CONFIG_OPTION_INCREMENTAL
                /* If this is an incrementally loaded font and there are */
                /* overriding metrics, tolerate a missing `hhea' table.  */
                if (face->root.internal->incremental_interface &&
                    face->root.internal->incremental_interface->funcs->
                    get_glyph_metrics)
                {
                    face->horizontal.number_Of_HMetrics = 0;
                    error                               = SFNT_Err_Ok;
                }
#endif
            }
        }

        if (error)
            goto Exit;

        /* try to load the `vhea' and `vmtx' tables */
        LOADM_(hhea, 1);
        if (!error)
        {
            LOADM_(hmtx, 1);
            if (!error)
                face->vertical_info = 1;
        }

        if (error && error != SFNT_Err_Table_Missing)
            goto Exit;

        LOAD_(os2);
        if (error)
        {
            if (error != SFNT_Err_Table_Missing)
                goto Exit;

            face->os2.version = 0xFFFFU;
        }
    }

    /* the optional tables */

    /* embedded bitmap support */
    if (sfnt->load_eblc)
    {
        LOAD_(eblc);
        if (error)
        {
            /* a font which contains neither bitmaps nor outlines is */
            /* still valid (although rather useless in most cases);  */
            /* however, you can find such stripped fonts in PDFs     */
            if (error == SFNT_Err_Table_Missing)
                error = SFNT_Err_Ok;
            else
                goto Exit;
        }
    }

    LOAD_(pclt);
    if (error)
    {
        if (error != SFNT_Err_Table_Missing)
            goto Exit;

        face->pclt.Version = 0;
    }

    /* consider the kerning and gasp tables as optional */
    LOAD_(gasp);
    LOAD_(kern);

    face->root.num_glyphs = face->max_profile.numGlyphs;

    /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
    /* a WWS-only font face.  `WWS' stands for `weight', width', and */
    /* `slope', a term used by Microsoft's Windows Presentation      */
    /* Foundation (WPF).  This flag has been introduced in version   */
    /* 1.5 of the OpenType specification (May 2008).                 */

    face->root.family_name = NULL;
    face->root.style_name  = NULL;
    if (face->os2.version != 0xFFFFU && face->os2.fsSelection & 256)
    {
        if (!ignore_preferred_family)
            GET_NAME(PREFERRED_FAMILY, &face->root.family_name);

        if (!face->root.family_name)
            GET_NAME(FONT_FAMILY, &face->root.family_name);

        if (!ignore_preferred_subfamily)
            GET_NAME(PREFERRED_SUBFAMILY, &face->root.style_name);

        if (!face->root.style_name)
            GET_NAME(FONT_SUBFAMILY, &face->root.style_name);
    }
    else
    {
        GET_NAME(WWS_FAMILY, &face->root.family_name);
        if (!face->root.family_name && !ignore_preferred_family)
            GET_NAME(PREFERRED_FAMILY, &face->root.family_name);

        if (!face->root.family_name)
            GET_NAME(FONT_FAMILY, &face->root.family_name);

        GET_NAME(WWS_SUBFAMILY, &face->root.style_name);
        if (!face->root.style_name && !ignore_preferred_subfamily)
            GET_NAME(PREFERRED_SUBFAMILY, &face->root.style_name);

        if (!face->root.style_name)
            GET_NAME(FONT_SUBFAMILY, &face->root.style_name);
    }

    /* now set up root fields */
    {
        FT_Face root  = &face->root;
        FT_Long flags = root->face_flags;


        /*********************************************************************/
        /*                                                                   */
        /* Compute face flags.                                               */
        /*                                                                   */
        if (has_outline == TRUE)
            flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */

        /* The sfnt driver only supports bitmap fonts natively, thus we */
        /* don't set FT_FACE_FLAG_HINTER.                               */
        flags |= FT_FACE_FLAG_SFNT |      /* SFNT file format  */
                 FT_FACE_FLAG_HORIZONTAL; /* horizontal data   */

#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
        if (psnames_error == SFNT_Err_Ok &&
            face->postscript.FormatType != 0x00030000L)
            flags |= FT_FACE_FLAG_GLYPH_NAMES;
#endif

        /* fixed width font? */
        if (face->postscript.isFixedPitch)
            flags |= FT_FACE_FLAG_FIXED_WIDTH;

        /* vertical information? */
        if (face->vertical_info)
            flags |= FT_FACE_FLAG_VERTICAL;

        /* kerning available ? */
        if (TT_FACE_HAS_KERNING(face))
            flags |= FT_FACE_FLAG_KERNING;

#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
        /* Don't bother to load the tables unless somebody asks for them. */
        /* No need to do work which will (probably) not be used.          */
        if (tt_face_lookup_table(face, TTAG_glyf) != 0 &&
            tt_face_lookup_table(face, TTAG_fvar) != 0 &&
            tt_face_lookup_table(face, TTAG_gvar) != 0)
            flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
#endif

        root->face_flags = flags;

        /*********************************************************************/
        /*                                                                   */
        /* Compute style flags.                                              */
        /*                                                                   */

        flags = 0;
        if (has_outline == TRUE && face->os2.version != 0xFFFFU)
        {
            /* We have an OS/2 table; use the `fsSelection' field.  Bit 9 */
            /* indicates an oblique font face.  This flag has been        */
            /* introduced in version 1.5 of the OpenType specification.   */

            if (face->os2.fsSelection & 512)     /* bit 9 */
                flags |= FT_STYLE_FLAG_ITALIC;
            else if (face->os2.fsSelection & 1)  /* bit 0 */
                flags |= FT_STYLE_FLAG_ITALIC;

            if (face->os2.fsSelection & 32)      /* bit 5 */
                flags |= FT_STYLE_FLAG_BOLD;
        }
        else
        {
            /* this is an old Mac font, use the header field */

            if (face->header.Mac_Style & 1)
                flags |= FT_STYLE_FLAG_BOLD;

            if (face->header.Mac_Style & 2)
                flags |= FT_STYLE_FLAG_ITALIC;
        }

        root->style_flags = flags;

        /*********************************************************************/
        /*                                                                   */
        /* Polish the charmaps.                                              */
        /*                                                                   */
        /*   Try to set the charmap encoding according to the platform &     */
        /*   encoding ID of each charmap.                                    */
        /*                                                                   */

        tt_face_build_cmaps(face);  /* ignore errors */


        /* set the encoding fields */
        {
            FT_Int m;


            for (m = 0; m < root->num_charmaps; m++)
            {
                FT_CharMap charmap = root->charmaps[m];


                charmap->encoding = sfnt_find_encoding(charmap->platform_id,
                                                       charmap->encoding_id);

#if 0
                if (root->charmap == NULL &&
                    charmap->encoding == FT_ENCODING_UNICODE)
                {
                    /* set 'root->charmap' to the first Unicode encoding we find */
                    root->charmap = charmap;
                }
#endif
            }
        }

#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
        /*
         *  Now allocate the root array of FT_Bitmap_Size records and
         *  populate them.  Unfortunately, it isn't possible to indicate bit
         *  depths in the FT_Bitmap_Size record.  This is a design error.
         */
        {
            FT_UInt i, count;


#ifndef FT_CONFIG_OPTION_OLD_INTERNALS
            count = face->sbit_num_strikes;
#else
            count = (FT_UInt)face->num_sbit_strikes;
#endif

            if (count > 0)
            {
                FT_Memory       memory   = face->root.stream->memory;
                FT_UShort       em_size  = face->header.Units_Per_EM;
                FT_Short        avgwidth = face->os2.xAvgCharWidth;
                FT_Size_Metrics metrics;


                if (em_size == 0 || face->os2.version == 0xFFFFU)
                {
                    avgwidth = 0;
                    em_size  = 1;
                }

                if (FT_NEW_ARRAY(root->available_sizes, count))
                    goto Exit;

                for (i = 0; i < count; i++)
                {
                    FT_Bitmap_Size *bsize = root->available_sizes + i;


                    error = sfnt->load_strike_metrics(face, i, &metrics);
                    if (error)
                        goto Exit;

                    bsize->height = (FT_Short)(metrics.height >> 6);
                    bsize->width  = (FT_Short)(
                        (avgwidth * metrics.x_ppem + em_size / 2) / em_size);

                    bsize->x_ppem = metrics.x_ppem << 6;
                    bsize->y_ppem = metrics.y_ppem << 6;

                    /* assume 72dpi */
                    bsize->size = metrics.y_ppem << 6;
                }

                root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
                root->num_fixed_sizes = (FT_Int)count;
            }
        }
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */

        /* a font with no bitmaps and no outlines is scalable; */
        /* it has only empty glyphs then                       */
        if (!FT_HAS_FIXED_SIZES(root) && !FT_IS_SCALABLE(root))
            root->face_flags |= FT_FACE_FLAG_SCALABLE;


        /*********************************************************************/
        /*                                                                   */
        /*  Set up metrics.                                                  */
        /*                                                                   */
        if (FT_IS_SCALABLE(root))
        {
            /* XXX What about if outline header is missing */
            /*     (e.g. sfnt wrapped bitmap)?             */
            root->bbox.xMin    = face->header.xMin;
            root->bbox.yMin    = face->header.yMin;
            root->bbox.xMax    = face->header.xMax;
            root->bbox.yMax    = face->header.yMax;
            root->units_per_EM = face->header.Units_Per_EM;


            /* XXX: Computing the ascender/descender/height is very different */
            /*      from what the specification tells you.  Apparently, we    */
            /*      must be careful because                                   */
            /*                                                                */
            /*      - not all fonts have an OS/2 table; in this case, we take */
            /*        the values in the horizontal header.  However, these    */
            /*        values very often are not reliable.                     */
            /*                                                                */
            /*      - otherwise, the correct typographic values are in the    */
            /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
            /*                                                                */
            /*        However, certain fonts have these fields set to 0.      */
            /*        Rather, they have usWinAscent & usWinDescent correctly  */
            /*        set (but with different values).                        */
            /*                                                                */
            /*      As an example, Arial Narrow is implemented through four   */
            /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
            /*                                                                */
            /*      Strangely, all fonts have the same values in their        */
            /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
            /*                                                                */
            /*      On the other hand, they all have different                */
            /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
            /*      table cannot be used to compute the text height reliably! */
            /*                                                                */

            /* The ascender/descender/height are computed from the OS/2 table */
            /* when found.  Otherwise, they're taken from the horizontal      */
            /* header.                                                        */
            /*                                                                */

            root->ascender  = face->horizontal.Ascender;
            root->descender = face->horizontal.Descender;

            root->height = (FT_Short)(root->ascender - root->descender +
                                      face->horizontal.Line_Gap);

#if 0
            /* if the line_gap is 0, we add an extra 15% to the text height --  */
            /* this computation is based on various versions of Times New Roman */
            if (face->horizontal.Line_Gap == 0)
                root->height = (FT_Short)((root->height * 115 + 50) / 100);
#endif /* 0 */

#if 0
            /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
            /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
            if (face->os2.version != 0xFFFFU && root->ascender)
            {
                FT_Int height;


                root->ascender  = face->os2.sTypoAscender;
                root->descender = -face->os2.sTypoDescender;

                height = root->ascender + root->descender + face->os2.sTypoLineGap;
                if (height > root->height)
                    root->height = height;
            }
#endif /* 0 */

            root->max_advance_width  = face->horizontal.advance_Width_Max;
            root->max_advance_height = (FT_Short)(face->vertical_info
                                                  ? face->vertical.advance_Height_Max
                                                  : root->height);

            /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
            /* Adjust underline position from top edge to centre of     */
            /* stroke to convert TrueType meaning to FreeType meaning.  */
            root->underline_position = face->postscript.underlinePosition -
                                       face->postscript.underlineThickness / 2;
            root->underline_thickness = face->postscript.underlineThickness;
        }
    }
Ejemplo n.º 26
0
static FT_Error
tt_face_get_name(TT_Face face,
                 FT_UShort nameid,
                 FT_String **name)
{
    FT_Memory       memory  = face->root.memory;
    FT_Error        error   = SFNT_Err_Ok;
    FT_String       *result = NULL;
    FT_UShort       n;
    TT_NameEntryRec *rec;
    FT_Int          found_apple         = -1;
    FT_Int          found_apple_roman   = -1;
    FT_Int          found_apple_english = -1;
    FT_Int          found_win           = -1;
    FT_Int          found_unicode       = -1;

    FT_Bool is_english = 0;

    TT_NameEntry_ConvertFunc convert;


    FT_ASSERT(name);

    rec = face->name_table.names;

    for (n = 0; n < face->num_names; n++, rec++)
    {
        /* According to the OpenType 1.3 specification, only Microsoft or  */
        /* Apple platform IDs might be used in the `name' table.  The      */
        /* `Unicode' platform is reserved for the `cmap' table, and the    */
        /* `ISO' one is deprecated.                                        */
        /*                                                                 */
        /* However, the Apple TrueType specification doesn't say the same  */
        /* thing and goes to suggest that all Unicode `name' table entries */
        /* should be coded in UTF-16 (in big-endian format I suppose).     */
        /*                                                                 */
        if (rec->nameID == nameid && rec->stringLength > 0)
        {
            switch (rec->platformID)
            {
            case TT_PLATFORM_APPLE_UNICODE:
            case TT_PLATFORM_ISO:
                /* there is `languageID' to check there.  We should use this */
                /* field only as a last solution when nothing else is        */
                /* available.                                                */
                /*                                                           */
                found_unicode = n;
                break;

            case TT_PLATFORM_MACINTOSH:
                /* This is a bit special because some fonts will use either    */
                /* an English language id, or a Roman encoding id, to indicate */
                /* the English version of its font name.                       */
                /*                                                             */
                if (rec->languageID == TT_MAC_LANGID_ENGLISH)
                    found_apple_english = n;
                else if (rec->encodingID == TT_MAC_ID_ROMAN)
                    found_apple_roman = n;

                break;

            case TT_PLATFORM_MICROSOFT:
                /* we only take a non-English name when there is nothing */
                /* else available in the font                            */
                /*                                                       */
                if (found_win == -1 || (rec->languageID & 0x3FF) == 0x009)
                {
                    switch (rec->encodingID)
                    {
                    case TT_MS_ID_SYMBOL_CS:
                    case TT_MS_ID_UNICODE_CS:
                    case TT_MS_ID_UCS_4:
                        is_english = FT_BOOL((rec->languageID & 0x3FF) == 0x009);
                        found_win  = n;
                        break;

                    default:
                        ;
                    }
                }

                break;

            default:
                ;
            }
        }
    }

    found_apple = found_apple_roman;
    if (found_apple_english >= 0)
        found_apple = found_apple_english;

    /* some fonts contain invalid Unicode or Macintosh formatted entries; */
    /* we will thus favor names encoded in Windows formats if available   */
    /* (provided it is an English name)                                   */
    /*                                                                    */
    convert = NULL;
    if (found_win >= 0 && !(found_apple >= 0 && !is_english))
    {
        rec = face->name_table.names + found_win;

        switch (rec->encodingID)
        {
        /* all Unicode strings are encoded using UTF-16BE */
        case TT_MS_ID_UNICODE_CS:
        case TT_MS_ID_SYMBOL_CS:
            convert = tt_name_entry_ascii_from_utf16;
            break;

        case TT_MS_ID_UCS_4:
            /* Apparently, if this value is found in a name table entry, it is */
            /* documented as `full Unicode repertoire'.  Experience with the   */
            /* MsGothic font shipped with Windows Vista shows that this really */
            /* means UTF-16 encoded names (UCS-4 values are only used within   */
            /* charmaps).                                                      */
            convert = tt_name_entry_ascii_from_utf16;
            break;

        default:
            ;
        }
    }
    else if (found_apple >= 0)
    {
        rec     = face->name_table.names + found_apple;
        convert = tt_name_entry_ascii_from_other;
    }
    else if (found_unicode >= 0)
    {
        rec     = face->name_table.names + found_unicode;
        convert = tt_name_entry_ascii_from_utf16;
    }

    if (rec && convert)
    {
        if (rec->string == NULL)
        {
            FT_Stream stream = face->name_table.stream;


            if (FT_QNEW_ARRAY (rec->string, rec->stringLength) ||
                FT_STREAM_SEEK(rec->stringOffset) ||
                FT_STREAM_READ(rec->string, rec->stringLength))
            {
                FT_FREE(rec->string);
                rec->stringLength = 0;
                result            = NULL;
                goto Exit;
            }
        }

        result = convert(rec, memory);
    }

Exit:
    *name = result;
    return error;
}
Ejemplo n.º 27
0
Archivo: cffgload.c Proyecto: 93i/godot
  cff_slot_load( CFF_GlyphSlot  glyph,
                 CFF_Size       size,
                 FT_UInt        glyph_index,
                 FT_Int32       load_flags )
  {
    FT_Error     error;
    CFF_Decoder  decoder;
    PS_Decoder   psdecoder;
    TT_Face      face = (TT_Face)glyph->root.face;
    FT_Bool      hinting, scaled, force_scaling;
    CFF_Font     cff  = (CFF_Font)face->extra.data;

    PSAux_Service            psaux         = (PSAux_Service)face->psaux;
    const CFF_Decoder_Funcs  decoder_funcs = psaux->cff_decoder_funcs;

    FT_Matrix    font_matrix;
    FT_Vector    font_offset;


    force_scaling = FALSE;

    /* in a CID-keyed font, consider `glyph_index' as a CID and map */
    /* it immediately to the real glyph_index -- if it isn't a      */
    /* subsetted font, glyph_indices and CIDs are identical, though */
    if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
         cff->charset.cids                               )
    {
      /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */
      if ( glyph_index != 0 )
      {
        glyph_index = cff_charset_cid_to_gindex( &cff->charset,
                                                 glyph_index );
        if ( glyph_index == 0 )
          return FT_THROW( Invalid_Argument );
      }
    }
    else if ( glyph_index >= cff->num_glyphs )
      return FT_THROW( Invalid_Argument );

    if ( load_flags & FT_LOAD_NO_RECURSE )
      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;

    glyph->x_scale = 0x10000L;
    glyph->y_scale = 0x10000L;
    if ( size )
    {
      glyph->x_scale = size->root.metrics.x_scale;
      glyph->y_scale = size->root.metrics.y_scale;
    }

#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS

    /* try to load embedded bitmap if any              */
    /*                                                 */
    /* XXX: The convention should be emphasized in     */
    /*      the documents because it can be confusing. */
    if ( size )
    {
      CFF_Face      cff_face = (CFF_Face)size->root.face;
      SFNT_Service  sfnt     = (SFNT_Service)cff_face->sfnt;
      FT_Stream     stream   = cff_face->root.stream;


      if ( size->strike_index != 0xFFFFFFFFUL      &&
           sfnt->load_eblc                         &&
           ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
      {
        TT_SBit_MetricsRec  metrics;


        error = sfnt->load_sbit_image( face,
                                       size->strike_index,
                                       glyph_index,
                                       (FT_UInt)load_flags,
                                       stream,
                                       &glyph->root.bitmap,
                                       &metrics );

        if ( !error )
        {
          FT_Bool    has_vertical_info;
          FT_UShort  advance;
          FT_Short   dummy;


          glyph->root.outline.n_points   = 0;
          glyph->root.outline.n_contours = 0;

          glyph->root.metrics.width  = (FT_Pos)metrics.width  << 6;
          glyph->root.metrics.height = (FT_Pos)metrics.height << 6;

          glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
          glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
          glyph->root.metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;

          glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
          glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
          glyph->root.metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;

          glyph->root.format = FT_GLYPH_FORMAT_BITMAP;

          if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
          {
            glyph->root.bitmap_left = metrics.vertBearingX;
            glyph->root.bitmap_top  = metrics.vertBearingY;
          }
          else
          {
            glyph->root.bitmap_left = metrics.horiBearingX;
            glyph->root.bitmap_top  = metrics.horiBearingY;
          }

          /* compute linear advance widths */

          (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
                                                           glyph_index,
                                                           &dummy,
                                                           &advance );
          glyph->root.linearHoriAdvance = advance;

          has_vertical_info = FT_BOOL(
                                face->vertical_info                   &&
                                face->vertical.number_Of_VMetrics > 0 );

          /* get the vertical metrics from the vmtx table if we have one */
          if ( has_vertical_info )
          {
            (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
                                                             glyph_index,
                                                             &dummy,
                                                             &advance );
            glyph->root.linearVertAdvance = advance;
          }
          else
          {
            /* make up vertical ones */
            if ( face->os2.version != 0xFFFFU )
              glyph->root.linearVertAdvance = (FT_Pos)
                ( face->os2.sTypoAscender - face->os2.sTypoDescender );
            else
              glyph->root.linearVertAdvance = (FT_Pos)
                ( face->horizontal.Ascender - face->horizontal.Descender );
          }

          return error;
        }
      }
    }

#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */

    /* return immediately if we only want the embedded bitmaps */
    if ( load_flags & FT_LOAD_SBITS_ONLY )
      return FT_THROW( Invalid_Argument );

    /* if we have a CID subfont, use its matrix (which has already */
    /* been multiplied with the root matrix)                       */

    /* this scaling is only relevant if the PS hinter isn't active */
    if ( cff->num_subfonts )
    {
      FT_Long  top_upm, sub_upm;
      FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select,
                                             glyph_index );


      if ( fd_index >= cff->num_subfonts )
        fd_index = (FT_Byte)( cff->num_subfonts - 1 );

      top_upm = (FT_Long)cff->top_font.font_dict.units_per_em;
      sub_upm = (FT_Long)cff->subfonts[fd_index]->font_dict.units_per_em;


      font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
      font_offset = cff->subfonts[fd_index]->font_dict.font_offset;

      if ( top_upm != sub_upm )
      {
        glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm );
        glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm );

        force_scaling = TRUE;
      }
    }
    else
    {
      font_matrix = cff->top_font.font_dict.font_matrix;
      font_offset = cff->top_font.font_dict.font_offset;
    }

    glyph->root.outline.n_points   = 0;
    glyph->root.outline.n_contours = 0;

    /* top-level code ensures that FT_LOAD_NO_HINTING is set */
    /* if FT_LOAD_NO_SCALE is active                         */
    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
    scaled  = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 );

    glyph->hint        = hinting;
    glyph->scaled      = scaled;
    glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;  /* by default */

    {
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
      PS_Driver  driver = (PS_Driver)FT_FACE_DRIVER( face );
#endif


      FT_Byte*  charstring;
      FT_ULong  charstring_len;


      decoder_funcs->init( &decoder, face, size, glyph, hinting,
                           FT_LOAD_TARGET_MODE( load_flags ),
                           cff_get_glyph_data,
                           cff_free_glyph_data );

      /* this is for pure CFFs */
      if ( load_flags & FT_LOAD_ADVANCE_ONLY )
        decoder.width_only = TRUE;

      decoder.builder.no_recurse =
        (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );

      /* now load the unscaled outline */
      error = cff_get_glyph_data( face, glyph_index,
                                  &charstring, &charstring_len );
      if ( error )
        goto Glyph_Build_Finished;

      error = decoder_funcs->prepare( &decoder, size, glyph_index );
      if ( error )
        goto Glyph_Build_Finished;

#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
      /* choose which CFF renderer to use */
      if ( driver->hinting_engine == FT_HINTING_FREETYPE )
        error = decoder_funcs->parse_charstrings_old( &decoder,
                                                      charstring,
                                                      charstring_len,
                                                      0 );
      else
#endif
      {
        psaux->ps_decoder_init( &psdecoder, &decoder, FALSE );

        error = decoder_funcs->parse_charstrings( &psdecoder,
                                                  charstring,
                                                  charstring_len );

        /* Adobe's engine uses 16.16 numbers everywhere;              */
        /* as a consequence, glyphs larger than 2000ppem get rejected */
        if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
        {
          /* this time, we retry unhinted and scale up the glyph later on */
          /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
          /* 0x400 for both `x_scale' and `y_scale' in this case)         */
          hinting       = FALSE;
          force_scaling = TRUE;
          glyph->hint   = hinting;

          error = decoder_funcs->parse_charstrings( &psdecoder,
                                                    charstring,
                                                    charstring_len );
        }
      }

      cff_free_glyph_data( face, &charstring, charstring_len );

      if ( error )
        goto Glyph_Build_Finished;

#ifdef FT_CONFIG_OPTION_INCREMENTAL
      /* Control data and length may not be available for incremental */
      /* fonts.                                                       */
      if ( face->root.internal->incremental_interface )
      {
        glyph->root.control_data = NULL;
        glyph->root.control_len = 0;
      }
      else
#endif /* FT_CONFIG_OPTION_INCREMENTAL */

      /* We set control_data and control_len if charstrings is loaded. */
      /* See how charstring loads at cff_index_access_element() in     */
      /* cffload.c.                                                    */
      {
        CFF_Index  csindex = &cff->charstrings_index;


        if ( csindex->offsets )
        {
          glyph->root.control_data = csindex->bytes +
                                     csindex->offsets[glyph_index] - 1;
          glyph->root.control_len  = (FT_Long)charstring_len;
        }
      }

  Glyph_Build_Finished:
      /* save new glyph tables, if no error */
      if ( !error )
        decoder.builder.funcs.done( &decoder.builder );
      /* XXX: anything to do for broken glyph entry? */
    }

#ifdef FT_CONFIG_OPTION_INCREMENTAL

    /* Incremental fonts can optionally override the metrics. */
    if ( !error                                                               &&
         face->root.internal->incremental_interface                           &&
         face->root.internal->incremental_interface->funcs->get_glyph_metrics )
    {
      FT_Incremental_MetricsRec  metrics;


      metrics.bearing_x = decoder.builder.left_bearing.x;
      metrics.bearing_y = 0;
      metrics.advance   = decoder.builder.advance.x;
      metrics.advance_v = decoder.builder.advance.y;

      error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
                face->root.internal->incremental_interface->object,
                glyph_index, FALSE, &metrics );

      decoder.builder.left_bearing.x = metrics.bearing_x;
      decoder.builder.advance.x      = metrics.advance;
      decoder.builder.advance.y      = metrics.advance_v;
    }

#endif /* FT_CONFIG_OPTION_INCREMENTAL */

    if ( !error )
    {
      /* Now, set the metrics -- this is rather simple, as   */
      /* the left side bearing is the xMin, and the top side */
      /* bearing the yMax.                                   */

      /* For composite glyphs, return only left side bearing and */
      /* advance width.                                          */
      if ( load_flags & FT_LOAD_NO_RECURSE )
      {
        FT_Slot_Internal  internal = glyph->root.internal;


        glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
        glyph->root.metrics.horiAdvance  = decoder.glyph_width;
        internal->glyph_matrix           = font_matrix;
        internal->glyph_delta            = font_offset;
        internal->glyph_transformed      = 1;
      }
      else
      {
        FT_BBox            cbox;
        FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
        FT_Bool            has_vertical_info;


        if ( face->horizontal.number_Of_HMetrics )
        {
          FT_Short   horiBearingX = 0;
          FT_UShort  horiAdvance  = 0;


          ( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
                                                     glyph_index,
                                                     &horiBearingX,
                                                     &horiAdvance );
          metrics->horiAdvance          = horiAdvance;
          metrics->horiBearingX         = horiBearingX;
          glyph->root.linearHoriAdvance = horiAdvance;
        }
        else
        {
          /* copy the _unscaled_ advance width */
          metrics->horiAdvance          = decoder.glyph_width;
          glyph->root.linearHoriAdvance = decoder.glyph_width;
        }

        glyph->root.internal->glyph_transformed = 0;

        has_vertical_info = FT_BOOL( face->vertical_info                   &&
                                     face->vertical.number_Of_VMetrics > 0 );

        /* get the vertical metrics from the vmtx table if we have one */
        if ( has_vertical_info )
        {
          FT_Short   vertBearingY = 0;
          FT_UShort  vertAdvance  = 0;


          ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
                                                     glyph_index,
                                                     &vertBearingY,
                                                     &vertAdvance );
          metrics->vertBearingY = vertBearingY;
          metrics->vertAdvance  = vertAdvance;
        }
        else
        {
          /* make up vertical ones */
          if ( face->os2.version != 0xFFFFU )
            metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -
                                             face->os2.sTypoDescender );
          else
            metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -
                                             face->horizontal.Descender );
        }

        glyph->root.linearVertAdvance = metrics->vertAdvance;

        glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;

        glyph->root.outline.flags = 0;
        if ( size && size->root.metrics.y_ppem < 24 )
          glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;

        glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;

        /* apply the font matrix, if any */
        if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L ||
             font_matrix.xy != 0        || font_matrix.yx != 0        )
        {
          FT_Outline_Transform( &glyph->root.outline, &font_matrix );

          metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
                                            font_matrix.xx );
          metrics->vertAdvance = FT_MulFix( metrics->vertAdvance,
                                            font_matrix.yy );
        }

        if ( font_offset.x || font_offset.y )
        {
          FT_Outline_Translate( &glyph->root.outline,
                                font_offset.x,
                                font_offset.y );

          metrics->horiAdvance += font_offset.x;
          metrics->vertAdvance += font_offset.y;
        }

        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
        {
          /* scale the outline and the metrics */
          FT_Int       n;
          FT_Outline*  cur     = &glyph->root.outline;
          FT_Vector*   vec     = cur->points;
          FT_Fixed     x_scale = glyph->x_scale;
          FT_Fixed     y_scale = glyph->y_scale;


          /* First of all, scale the points */
          if ( !hinting || !decoder.builder.hints_funcs )
            for ( n = cur->n_points; n > 0; n--, vec++ )
            {
              vec->x = FT_MulFix( vec->x, x_scale );
              vec->y = FT_MulFix( vec->y, y_scale );
            }

          /* Then scale the metrics */
          metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
          metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
        }

        /* compute the other metrics */
        FT_Outline_Get_CBox( &glyph->root.outline, &cbox );

        metrics->width  = cbox.xMax - cbox.xMin;
        metrics->height = cbox.yMax - cbox.yMin;

        metrics->horiBearingX = cbox.xMin;
        metrics->horiBearingY = cbox.yMax;

        if ( has_vertical_info )
          metrics->vertBearingX = metrics->horiBearingX -
                                    metrics->horiAdvance / 2;
        else
        {
          if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
            ft_synthesize_vertical_metrics( metrics,
                                            metrics->vertAdvance );
        }
      }
    }

    return error;
  }
Ejemplo n.º 28
0
  /* reset the blues table when the device transform changes */
  static void
  psh_blues_scale_zones( PSH_Blues  blues,
                         FT_Fixed   scale,
                         FT_Pos     delta )
  {
    FT_UInt         count;
    FT_UInt         num;
    PSH_Blue_Table  table = 0;

    /*                                                        */
    /* Determine whether we need to suppress overshoots or    */
    /* not.  We simply need to compare the vertical scale     */
    /* parameter to the raw bluescale value.  Here is why:    */
    /*                                                        */
    /*   We need to suppress overshoots for all pointsizes.   */
    /*   At 300dpi that satisfies:                            */
    /*                                                        */
    /*      pointsize < 240*bluescale + 0.49                  */
    /*                                                        */
    /*   This corresponds to:                                 */
    /*                                                        */
    /*      pixelsize < 1000*bluescale + 49/24                */
    /*                                                        */
    /*      scale*EM_Size < 1000*bluescale + 49/24            */
    /*                                                        */
    /*   However, for normal Type 1 fonts, EM_Size is 1000!   */
    /*   We thus only check:                                  */
    /*                                                        */
    /*      scale < bluescale + 49/24000                      */
    /*                                                        */
    /*   which we shorten to                                  */
    /*                                                        */
    /*      "scale < bluescale"                               */
    /*                                                        */
    /* Note that `blue_scale' is stored 1000 times its real   */
    /* value, and that `scale' converts from font units to    */
    /* fractional pixels.                                     */
    /*                                                        */

    /* 1000 / 64 = 125 / 8 */
    if ( scale >= 0x20C49BAL )
      blues->no_overshoots = FT_BOOL( scale < blues->blue_scale * 8 / 125 );
    else
      blues->no_overshoots = FT_BOOL( scale * 125 < blues->blue_scale * 8 );

    /*                                                        */
    /*  The blue threshold is the font units distance under   */
    /*  which overshoots are suppressed due to the BlueShift  */
    /*  even if the scale is greater than BlueScale.          */
    /*                                                        */
    /*  It is the smallest distance such that                 */
    /*                                                        */
    /*    dist <= BlueShift && dist*scale <= 0.5 pixels       */
    /*                                                        */
    {
      FT_Int  threshold = blues->blue_shift;


      while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 )
        threshold--;

      blues->blue_threshold = threshold;
    }

    for ( num = 0; num < 4; num++ )
    {
      PSH_Blue_Zone  zone;


      switch ( num )
      {
      case 0:
        table = &blues->normal_top;
        break;
      case 1:
        table = &blues->normal_bottom;
        break;
      case 2:
        table = &blues->family_top;
        break;
      default:
        table = &blues->family_bottom;
        break;
      }

      zone  = table->zones;
      count = table->count;
      for ( ; count > 0; count--, zone++ )
      {
        zone->cur_top    = FT_MulFix( zone->org_top,    scale ) + delta;
        zone->cur_bottom = FT_MulFix( zone->org_bottom, scale ) + delta;
        zone->cur_ref    = FT_MulFix( zone->org_ref,    scale ) + delta;
        zone->cur_delta  = FT_MulFix( zone->org_delta,  scale );

        /* round scaled reference position */
        zone->cur_ref = FT_PIX_ROUND( zone->cur_ref );

#if 0
        if ( zone->cur_ref > zone->cur_top )
          zone->cur_ref -= 64;
        else if ( zone->cur_ref < zone->cur_bottom )
          zone->cur_ref += 64;
#endif
      }
    }

    /* process the families now */

    for ( num = 0; num < 2; num++ )
    {
      PSH_Blue_Zone   zone1, zone2;
      FT_UInt         count1, count2;
      PSH_Blue_Table  normal, family;


      switch ( num )
      {
      case 0:
        normal = &blues->normal_top;
        family = &blues->family_top;
        break;

      default:
        normal = &blues->normal_bottom;
        family = &blues->family_bottom;
      }

      zone1  = normal->zones;
      count1 = normal->count;

      for ( ; count1 > 0; count1--, zone1++ )
      {
        /* try to find a family zone whose reference position is less */
        /* than 1 pixel far from the current zone                     */
        zone2  = family->zones;
        count2 = family->count;

        for ( ; count2 > 0; count2--, zone2++ )
        {
          FT_Pos  Delta;


          Delta = zone1->org_ref - zone2->org_ref;
          if ( Delta < 0 )
            Delta = -Delta;

          if ( FT_MulFix( Delta, scale ) < 64 )
          {
            zone1->cur_top    = zone2->cur_top;
            zone1->cur_bottom = zone2->cur_bottom;
            zone1->cur_ref    = zone2->cur_ref;
            zone1->cur_delta  = zone2->cur_delta;
            break;
          }
        }
      }
    }
  }
Ejemplo n.º 29
0
  T1_Load_Glyph( FT_GlyphSlot  t1glyph,          /* T1_GlyphSlot */
                 FT_Size       t1size,           /* T1_Size      */
                 FT_UInt       glyph_index,
                 FT_Int32      load_flags )
  {
    T1_GlyphSlot            glyph = (T1_GlyphSlot)t1glyph;
    FT_Error                error;
#ifdef __REACTOS__
    T1_DecoderRec *decoder = malloc(sizeof(T1_DecoderRec));
    if (!decoder)
      return FT_THROW( Out_Of_Memory );
/* Ugly but it allows us to reduce the diff */
#define decoder (*decoder)
    {
#else
    T1_DecoderRec           decoder;
#endif
    T1_Face                 face = (T1_Face)t1glyph->face;
    FT_Bool                 hinting;
    FT_Bool                 scaled;
    FT_Bool                 force_scaling = FALSE;
    T1_Font                 type1         = &face->type1;
    PSAux_Service           psaux         = (PSAux_Service)face->psaux;
    const T1_Decoder_Funcs  decoder_funcs = psaux->t1_decoder_funcs;

    FT_Matrix               font_matrix;
    FT_Vector               font_offset;
    FT_Data                 glyph_data;
    FT_Bool                 must_finish_decoder = FALSE;
#ifdef FT_CONFIG_OPTION_INCREMENTAL
    FT_Bool                 glyph_data_loaded = 0;
#endif


#ifdef FT_CONFIG_OPTION_INCREMENTAL
    if ( glyph_index >= (FT_UInt)face->root.num_glyphs &&
         !face->root.internal->incremental_interface   )
#else
    if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
    {
      error = FT_THROW( Invalid_Argument );
      goto Exit;
    }

    FT_TRACE1(( "T1_Load_Glyph: glyph index %d\n", glyph_index ));

    FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );

    if ( load_flags & FT_LOAD_NO_RECURSE )
      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;

    if ( t1size )
    {
      glyph->x_scale = t1size->metrics.x_scale;
      glyph->y_scale = t1size->metrics.y_scale;
    }
    else
    {
      glyph->x_scale = 0x10000L;
      glyph->y_scale = 0x10000L;
    }

    t1glyph->outline.n_points   = 0;
    t1glyph->outline.n_contours = 0;

    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
    scaled  = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 );

    glyph->hint     = hinting;
    glyph->scaled   = scaled;
    t1glyph->format = FT_GLYPH_FORMAT_OUTLINE;

    error = decoder_funcs->init( &decoder,
                                 t1glyph->face,
                                 t1size,
                                 t1glyph,
                                 (FT_Byte**)type1->glyph_names,
                                 face->blend,
                                 FT_BOOL( hinting ),
                                 FT_LOAD_TARGET_MODE( load_flags ),
                                 T1_Parse_Glyph );
    if ( error )
      goto Exit;

    must_finish_decoder = TRUE;

    decoder.builder.no_recurse = FT_BOOL(
                                   ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );

    decoder.num_subrs     = type1->num_subrs;
    decoder.subrs         = type1->subrs;
    decoder.subrs_len     = type1->subrs_len;
    decoder.subrs_hash    = type1->subrs_hash;

    decoder.buildchar     = face->buildchar;
    decoder.len_buildchar = face->len_buildchar;

    /* now load the unscaled outline */
    error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index,
                                                &glyph_data,
                                                &force_scaling );
    if ( error )
      goto Exit;
#ifdef FT_CONFIG_OPTION_INCREMENTAL
    glyph_data_loaded = 1;
#endif

    hinting     = glyph->hint;
    font_matrix = decoder.font_matrix;
    font_offset = decoder.font_offset;

    /* save new glyph tables */
    decoder_funcs->done( &decoder );

    must_finish_decoder = FALSE;

    /* now, set the metrics -- this is rather simple, as   */
    /* the left side bearing is the xMin, and the top side */
    /* bearing the yMax                                    */
    if ( !error )
    {
      t1glyph->outline.flags &= FT_OUTLINE_OWNER;
      t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL;

      /* for composite glyphs, return only left side bearing and */
      /* advance width                                           */
      if ( load_flags & FT_LOAD_NO_RECURSE )
      {
        FT_Slot_Internal  internal = t1glyph->internal;


        t1glyph->metrics.horiBearingX =
          FIXED_TO_INT( decoder.builder.left_bearing.x );
        t1glyph->metrics.horiAdvance  =
          FIXED_TO_INT( decoder.builder.advance.x );

        internal->glyph_matrix      = font_matrix;
        internal->glyph_delta       = font_offset;
        internal->glyph_transformed = 1;
      }
      else
      {
        FT_BBox            cbox;
        FT_Glyph_Metrics*  metrics = &t1glyph->metrics;


        /* copy the _unscaled_ advance width */
        metrics->horiAdvance =
          FIXED_TO_INT( decoder.builder.advance.x );
        t1glyph->linearHoriAdvance =
          FIXED_TO_INT( decoder.builder.advance.x );
        t1glyph->internal->glyph_transformed = 0;

        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
        {
          /* make up vertical ones */
          metrics->vertAdvance = ( face->type1.font_bbox.yMax -
                                   face->type1.font_bbox.yMin ) >> 16;
          t1glyph->linearVertAdvance = metrics->vertAdvance;
        }
        else
        {
          metrics->vertAdvance =
            FIXED_TO_INT( decoder.builder.advance.y );
          t1glyph->linearVertAdvance =
            FIXED_TO_INT( decoder.builder.advance.y );
        }

        t1glyph->format = FT_GLYPH_FORMAT_OUTLINE;

        if ( t1size && t1size->metrics.y_ppem < 24 )
          t1glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;

#if 1
        /* apply the font matrix, if any */
        if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L ||
             font_matrix.xy != 0        || font_matrix.yx != 0        )
        {
          FT_Outline_Transform( &t1glyph->outline, &font_matrix );

          metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
                                            font_matrix.xx );
          metrics->vertAdvance = FT_MulFix( metrics->vertAdvance,
                                            font_matrix.yy );
        }

        if ( font_offset.x || font_offset.y )
        {
          FT_Outline_Translate( &t1glyph->outline,
                                font_offset.x,
                                font_offset.y );

          metrics->horiAdvance += font_offset.x;
          metrics->vertAdvance += font_offset.y;
        }
#endif

        if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
        {
          /* scale the outline and the metrics */
          FT_Int       n;
          FT_Outline*  cur = decoder.builder.base;
          FT_Vector*   vec = cur->points;
          FT_Fixed     x_scale = glyph->x_scale;
          FT_Fixed     y_scale = glyph->y_scale;


          /* First of all, scale the points, if we are not hinting */
          if ( !hinting || ! decoder.builder.hints_funcs )
            for ( n = cur->n_points; n > 0; n--, vec++ )
            {
              vec->x = FT_MulFix( vec->x, x_scale );
              vec->y = FT_MulFix( vec->y, y_scale );
            }

          /* Then scale the metrics */
          metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
          metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
        }

        /* compute the other metrics */
        FT_Outline_Get_CBox( &t1glyph->outline, &cbox );

        metrics->width  = cbox.xMax - cbox.xMin;
        metrics->height = cbox.yMax - cbox.yMin;

        metrics->horiBearingX = cbox.xMin;
        metrics->horiBearingY = cbox.yMax;

        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
        {
          /* make up vertical ones */
          ft_synthesize_vertical_metrics( metrics,
                                          metrics->vertAdvance );
        }
      }
Ejemplo n.º 30
0
  afm_parser_read_vals( AFM_Parser  parser,
                        AFM_Value   vals,
                        FT_UInt     n )
  {
    AFM_Stream  stream = parser->stream;
    char*       str;
    FT_UInt     i;


    if ( n > AFM_MAX_ARGUMENTS )
      return 0;

    for ( i = 0; i < n; i++ )
    {
      FT_Offset  len;
      AFM_Value  val = vals + i;


      if ( val->type == AFM_VALUE_TYPE_STRING )
        str = afm_stream_read_string( stream );
      else
        str = afm_stream_read_one( stream );

      if ( !str )
        break;

      len = AFM_STREAM_KEY_LEN( stream, str );

      switch ( val->type )
      {
      case AFM_VALUE_TYPE_STRING:
      case AFM_VALUE_TYPE_NAME:
        {
          FT_Memory  memory = parser->memory;
          FT_Error   error;


          if ( !FT_QALLOC( val->u.s, len + 1 ) )
          {
            ft_memcpy( val->u.s, str, len );
            val->u.s[len] = '\0';
          }
        }
        break;

      case AFM_VALUE_TYPE_FIXED:
        val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str,
                                    (FT_Byte*)str + len, 0 );
        break;

      case AFM_VALUE_TYPE_INTEGER:
        val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str,
                                  (FT_Byte*)str + len );
        break;

      case AFM_VALUE_TYPE_BOOL:
        val->u.b = FT_BOOL( len == 4                      &&
                            !ft_strncmp( str, "true", 4 ) );
        break;

      case AFM_VALUE_TYPE_INDEX:
        if ( parser->get_index )
          val->u.i = parser->get_index( str, len, parser->user_data );
        else
          val->u.i = 0;
        break;
      }
    }

    return i;
  }