Ejemplo n.º 1
0
  tt_face_load_hmtx( TT_Face    face,
                     FT_Stream  stream,
                     FT_Bool    vertical )
  {
    FT_Error   error;
    FT_Memory  memory = stream->memory;

    FT_ULong   table_len;
    FT_Long    num_shorts, num_longs, num_shorts_checked;

    TT_LongMetrics *   longs;
    TT_ShortMetrics**  shorts;


    if ( vertical )
    {
      error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
      if ( error )
        goto Fail;

      num_longs = face->vertical.number_Of_VMetrics;
      if ( (FT_ULong)num_longs > table_len / 4 )
        num_longs = (FT_Long)(table_len / 4);

      face->vertical.number_Of_VMetrics = 0;

      longs  = (TT_LongMetrics *)&face->vertical.long_metrics;
      shorts = (TT_ShortMetrics**)&face->vertical.short_metrics;
    }
    else
    {
      error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
      if ( error )
        goto Fail;

      num_longs = face->horizontal.number_Of_HMetrics;
      if ( (FT_ULong)num_longs > table_len / 4 )
        num_longs = (FT_Long)(table_len / 4);

      face->horizontal.number_Of_HMetrics = 0;

      longs  = (TT_LongMetrics *)&face->horizontal.long_metrics;
      shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics;
    }

    /* never trust derived values */

    num_shorts         = face->max_profile.numGlyphs - num_longs;
    num_shorts_checked = ( table_len - num_longs * 4L ) / 2;

    if ( num_shorts < 0 )
    {
      FT_ERROR(( "%cmtx has more metrics than glyphs.\n" ));

      /* Adobe simply ignores this problem.  So we shall do the same. */
#if 0
      error = vertical ? SFNT_Err_Invalid_Vert_Metrics
                       : SFNT_Err_Invalid_Horiz_Metrics;
      goto Exit;
#else
      num_shorts = 0;
#endif
    }

    if ( FT_QNEW_ARRAY( *longs,  num_longs  ) ||
         FT_QNEW_ARRAY( *shorts, num_shorts ) )
      goto Fail;

    if ( FT_FRAME_ENTER( table_len ) )
      goto Fail;

    {
      TT_LongMetrics  cur   = *longs;
      TT_LongMetrics  limit = cur + num_longs;


      for ( ; cur < limit; cur++ )
      {
        cur->advance = FT_GET_USHORT();
        cur->bearing = FT_GET_SHORT();
      }
    }

    /* do we have an inconsistent number of metric values? */
    {
      TT_ShortMetrics*  cur   = *shorts;
      TT_ShortMetrics*  limit = cur +
                                FT_MIN( num_shorts, num_shorts_checked );


      for ( ; cur < limit; cur++ )
        *cur = FT_GET_SHORT();

      /* We fill up the missing left side bearings with the     */
      /* last valid value.  Since this will occur for buggy CJK */
      /* fonts usually only, nothing serious will happen.       */
      if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
      {
        FT_Short  val = (*shorts)[num_shorts_checked - 1];


        limit = *shorts + num_shorts;
        for ( ; cur < limit; cur++ )
          *cur = val;
      }
    }

    FT_FRAME_EXIT();

    if ( vertical )
      face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
    else
      face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;

  Fail:
    return error;
  }
Ejemplo n.º 2
0
  static FT_Error
  pcf_get_encodings( FT_Stream  stream,
                     PCF_Face   face )
  {
    FT_Error      error;
    FT_Memory     memory = FT_FACE( face )->memory;
    FT_ULong      format, size;
    int           firstCol, lastCol;
    int           firstRow, lastRow;
    int           nencoding, encodingOffset;
    int           i, j, k;
    PCF_Encoding  encoding = NULL;


    error = pcf_seek_to_table_type( stream,
                                    face->toc.tables,
                                    face->toc.count,
                                    PCF_BDF_ENCODINGS,
                                    &format,
                                    &size );
    if ( error )
      return error;

    error = FT_Stream_EnterFrame( stream, 14 );
    if ( error )
      return error;

    format = FT_GET_ULONG_LE();

    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
    {
      firstCol          = FT_GET_SHORT();
      lastCol           = FT_GET_SHORT();
      firstRow          = FT_GET_SHORT();
      lastRow           = FT_GET_SHORT();
      face->defaultChar = FT_GET_SHORT();
    }
    else
    {
      firstCol          = FT_GET_SHORT_LE();
      lastCol           = FT_GET_SHORT_LE();
      firstRow          = FT_GET_SHORT_LE();
      lastRow           = FT_GET_SHORT_LE();
      face->defaultChar = FT_GET_SHORT_LE();
    }

    FT_Stream_ExitFrame( stream );

    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
      return FT_THROW( Invalid_File_Format );

    /* sanity checks */
    if ( firstCol < 0       ||
         firstCol > lastCol ||
         lastCol  > 0xFF    ||
         firstRow < 0       ||
         firstRow > lastRow ||
         lastRow  > 0xFF    )
      return FT_THROW( Invalid_Table );

    FT_TRACE4(( "pdf_get_encodings:\n" ));

    FT_TRACE4(( "  firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
                firstCol, lastCol, firstRow, lastRow ));

    nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );

    if ( FT_NEW_ARRAY( encoding, nencoding ) )
      return FT_THROW( Out_Of_Memory );

    error = FT_Stream_EnterFrame( stream, 2 * nencoding );
    if ( error )
      goto Bail;

    k = 0;
    for ( i = firstRow; i <= lastRow; i++ )
    {
      for ( j = firstCol; j <= lastCol; j++ )
      {
        if ( PCF_BYTE_ORDER( format ) == MSBFirst )
          encodingOffset = FT_GET_SHORT();
        else
          encodingOffset = FT_GET_SHORT_LE();

        if ( encodingOffset != -1 )
        {
          encoding[k].enc   = i * 256 + j;
          encoding[k].glyph = (FT_Short)encodingOffset;

          FT_TRACE5(( "  code %d (0x%04X): idx %d\n",
                      encoding[k].enc, encoding[k].enc, encoding[k].glyph ));

          k++;
        }
      }
    }
    FT_Stream_ExitFrame( stream );

    if ( FT_RENEW_ARRAY( encoding, nencoding, k ) )
      goto Bail;

    face->nencodings = k;
    face->encodings  = encoding;

    return error;

  Bail:
    FT_FREE( encoding );
    return error;
  }
Ejemplo n.º 3
0
  static FT_Error
  pcf_get_encodings( FT_Stream  stream,
                     PCF_Face   face )
  {
    FT_Error      error  = PCF_Err_Ok;
    FT_Memory     memory = FT_FACE(face)->memory;
    FT_ULong      format, size;
    int           firstCol, lastCol;
    int           firstRow, lastRow;
    int           nencoding, encodingOffset;
    int           i, j;
    PCF_Encoding  tmpEncoding, encoding = 0;


    error = pcf_seek_to_table_type( stream,
                                    face->toc.tables,
                                    face->toc.count,
                                    PCF_BDF_ENCODINGS,
                                    &format,
                                    &size );
    if ( error )
      return error;

    error = FT_Stream_EnterFrame( stream, 14 );
    if ( error )
      return error;

    format = FT_GET_ULONG_LE();

    if ( PCF_BYTE_ORDER( format ) == MSBFirst )
    {
      firstCol          = FT_GET_SHORT();
      lastCol           = FT_GET_SHORT();
      firstRow          = FT_GET_SHORT();
      lastRow           = FT_GET_SHORT();
      face->defaultChar = FT_GET_SHORT();
    }
    else
    {
      firstCol          = FT_GET_SHORT_LE();
      lastCol           = FT_GET_SHORT_LE();
      firstRow          = FT_GET_SHORT_LE();
      lastRow           = FT_GET_SHORT_LE();
      face->defaultChar = FT_GET_SHORT_LE();
    }

    FT_Stream_ExitFrame( stream );

    if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
      return PCF_Err_Invalid_File_Format;

    FT_TRACE4(( "pdf_get_encodings:\n" ));

    FT_TRACE4(( "  firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
                firstCol, lastCol, firstRow, lastRow ));

    nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );

    if ( FT_NEW_ARRAY( tmpEncoding, nencoding ) )
      return PCF_Err_Out_Of_Memory;

    error = FT_Stream_EnterFrame( stream, 2 * nencoding );
    if ( error )
      goto Bail;

    for ( i = 0, j = 0 ; i < nencoding; i++ )
    {
      if ( PCF_BYTE_ORDER( format ) == MSBFirst )
        encodingOffset = FT_GET_SHORT();
      else
        encodingOffset = FT_GET_SHORT_LE();

      if ( encodingOffset != -1 )
      {
        tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
                                 firstRow ) * 256 ) +
                               ( ( i % ( lastCol - firstCol + 1 ) ) +
                                 firstCol );

        tmpEncoding[j].glyph = (FT_Short)encodingOffset;

        FT_TRACE5(( "  code %d (0x%04X): idx %d\n",
                    tmpEncoding[j].enc, tmpEncoding[j].enc,
                    tmpEncoding[j].glyph ));

        j++;
      }
    }
    FT_Stream_ExitFrame( stream );

    if ( FT_NEW_ARRAY( encoding, j ) )
      goto Bail;

    for ( i = 0; i < j; i++ )
    {
      encoding[i].enc   = tmpEncoding[i].enc;
      encoding[i].glyph = tmpEncoding[i].glyph;
    }

    face->nencodings = j;
    face->encodings  = encoding;
    FT_FREE( tmpEncoding );

    return error;

  Bail:
    FT_FREE( encoding );
    FT_FREE( tmpEncoding );
    return error;
  }
Ejemplo n.º 4
0
  TT_CharMap_Load( TT_Face       face,
                   TT_CMapTable  cmap,
                   FT_Stream     stream )
  {
    FT_Error     error;
    FT_Memory    memory;
    FT_UShort    num_SH, num_Seg, i;
    FT_ULong     j, n;

    FT_UShort    u, l;

    TT_CMap0     cmap0;
    TT_CMap2     cmap2;
    TT_CMap4     cmap4;
    TT_CMap6     cmap6;
    TT_CMap8_12  cmap8_12;
    TT_CMap10    cmap10;

    TT_CMap2SubHeader  cmap2sub;
    TT_CMap4Segment    segments;
    TT_CMapGroup       groups;


    if ( cmap->loaded )
      return SFNT_Err_Ok;

    memory = stream->memory;

    if ( FT_STREAM_SEEK( cmap->offset ) )
      return error;

    switch ( cmap->format )
    {
    case 0:
      cmap0 = &cmap->c.cmap0;

      if ( FT_READ_USHORT( cmap0->language )           ||
           FT_ALLOC( cmap0->glyphIdArray, 256L )       ||
           FT_STREAM_READ( cmap0->glyphIdArray, 256L ) )
        goto Fail;

      cmap->get_index     = code_to_index0;
      cmap->get_next_char = code_to_next0;
      break;

    case 2:
      num_SH = 0;
      cmap2  = &cmap->c.cmap2;

      /* allocate subheader keys */

      if ( FT_NEW_ARRAY( cmap2->subHeaderKeys, 256 ) ||
           FT_FRAME_ENTER( 2L + 512L )               )
        goto Fail;

      cmap2->language = FT_GET_USHORT();

      for ( i = 0; i < 256; i++ )
      {
        u = (FT_UShort)( FT_GET_USHORT() / 8 );
        cmap2->subHeaderKeys[i] = u;

        if ( num_SH < u )
          num_SH = u;
      }

      FT_FRAME_EXIT();

      /* load subheaders */

      cmap2->numGlyphId = l = (FT_UShort)(
        ( ( cmap->length - 2L * ( 256 + 3 ) - num_SH * 8L ) & 0xFFFFU ) / 2 );

      if ( FT_NEW_ARRAY( cmap2->subHeaders, num_SH + 1 ) ||
           FT_FRAME_ENTER( ( num_SH + 1 ) * 8L )         )
      {
        FT_FREE( cmap2->subHeaderKeys );
        goto Fail;
      }

      cmap2sub = cmap2->subHeaders;

      for ( i = 0; i <= num_SH; i++ )
      {
        cmap2sub->firstCode     = FT_GET_USHORT();
        cmap2sub->entryCount    = FT_GET_USHORT();
        cmap2sub->idDelta       = FT_GET_SHORT();
        /* we apply the location offset immediately */
        cmap2sub->idRangeOffset = (FT_UShort)(
          FT_GET_USHORT() - ( num_SH - i ) * 8 - 2 );

        cmap2sub++;
      }

      FT_FRAME_EXIT();

      /* load glyph IDs */

      if ( FT_NEW_ARRAY( cmap2->glyphIdArray, l ) ||
           FT_FRAME_ENTER( l * 2L )               )
      {
        FT_FREE( cmap2->subHeaders );
        FT_FREE( cmap2->subHeaderKeys );
        goto Fail;
      }

      for ( i = 0; i < l; i++ )
        cmap2->glyphIdArray[i] = FT_GET_USHORT();

      FT_FRAME_EXIT();

      cmap->get_index = code_to_index2;
      cmap->get_next_char = code_to_next2;
      break;

    case 4:
      cmap4 = &cmap->c.cmap4;

      /* load header */

      if ( FT_FRAME_ENTER( 10L ) )
        goto Fail;

      cmap4->language      = FT_GET_USHORT();
      cmap4->segCountX2    = FT_GET_USHORT();
      cmap4->searchRange   = FT_GET_USHORT();
      cmap4->entrySelector = FT_GET_USHORT();
      cmap4->rangeShift    = FT_GET_USHORT();

      num_Seg = (FT_UShort)( cmap4->segCountX2 / 2 );

      FT_FRAME_EXIT();

      /* load segments */

      if ( FT_NEW_ARRAY( cmap4->segments, num_Seg )   ||
           FT_FRAME_ENTER( ( num_Seg * 4 + 1 ) * 2L ) )
        goto Fail;

      segments = cmap4->segments;

      for ( i = 0; i < num_Seg; i++ )
        segments[i].endCount = FT_GET_USHORT();

      (void)FT_GET_USHORT();

      for ( i = 0; i < num_Seg; i++ )
        segments[i].startCount = FT_GET_USHORT();

      for ( i = 0; i < num_Seg; i++ )
        segments[i].idDelta = FT_GET_SHORT();

      for ( i = 0; i < num_Seg; i++ )
        segments[i].idRangeOffset = FT_GET_USHORT();

      FT_FRAME_EXIT();

      cmap4->numGlyphId = l = (FT_UShort)(
        ( ( cmap->length - ( 16L + 8L * num_Seg ) ) & 0xFFFFU ) / 2 );

      /* load IDs */

      if ( FT_NEW_ARRAY( cmap4->glyphIdArray, l ) ||
           FT_FRAME_ENTER( l * 2L )               )
      {
        FT_FREE( cmap4->segments );
        goto Fail;
      }

      for ( i = 0; i < l; i++ )
        cmap4->glyphIdArray[i] = FT_GET_USHORT();

      FT_FRAME_EXIT();

      cmap4->last_segment = cmap4->segments;

      cmap->get_index     = code_to_index4;
      cmap->get_next_char = code_to_next4;
      break;

    case 6:
      cmap6 = &cmap->c.cmap6;

      if ( FT_FRAME_ENTER( 6L ) )
        goto Fail;

      cmap6->language   = FT_GET_USHORT();
      cmap6->firstCode  = FT_GET_USHORT();
      cmap6->entryCount = FT_GET_USHORT();

      FT_FRAME_EXIT();

      l = cmap6->entryCount;

      if ( FT_NEW_ARRAY( cmap6->glyphIdArray, l ) ||
           FT_FRAME_ENTER( l * 2L )               )
        goto Fail;

      for ( i = 0; i < l; i++ )
        cmap6->glyphIdArray[i] = FT_GET_USHORT();

      FT_FRAME_EXIT();
      cmap->get_index     = code_to_index6;
      cmap->get_next_char = code_to_next6;
      break;

    case 8:
    case 12:
      cmap8_12 = &cmap->c.cmap8_12;

      if ( FT_FRAME_ENTER( 8L ) )
        goto Fail;

      cmap->length       = FT_GET_ULONG();
      cmap8_12->language = FT_GET_ULONG();

      FT_FRAME_EXIT();

      if ( cmap->format == 8 )
        if ( FT_STREAM_SKIP( 8192L ) )
          goto Fail;

      if ( FT_READ_ULONG( cmap8_12->nGroups ) )
        goto Fail;

      n = cmap8_12->nGroups;

      if ( FT_NEW_ARRAY( cmap8_12->groups, n ) ||
           FT_FRAME_ENTER( n * 3 * 4L )        )
        goto Fail;

      groups = cmap8_12->groups;

      for ( j = 0; j < n; j++ )
      {
        groups[j].startCharCode = FT_GET_ULONG();
        groups[j].endCharCode   = FT_GET_ULONG();
        groups[j].startGlyphID  = FT_GET_ULONG();
      }

      FT_FRAME_EXIT();

      cmap8_12->last_group = cmap8_12->groups;

      cmap->get_index     = code_to_index8_12;
      cmap->get_next_char = code_to_next8_12;
      break;

    case 10:
      cmap10 = &cmap->c.cmap10;

      if ( FT_FRAME_ENTER( 16L ) )
        goto Fail;

      cmap->length          = FT_GET_ULONG();
      cmap10->language      = FT_GET_ULONG();
      cmap10->startCharCode = FT_GET_ULONG();
      cmap10->numChars      = FT_GET_ULONG();

      FT_FRAME_EXIT();

      n = cmap10->numChars;

      if ( FT_NEW_ARRAY( cmap10->glyphs, n ) ||
           FT_FRAME_ENTER( n * 2L )          )
        goto Fail;

      for ( j = 0; j < n; j++ )
        cmap10->glyphs[j] = FT_GET_USHORT();

      FT_FRAME_EXIT();
      cmap->get_index     = code_to_index10;
      cmap->get_next_char = code_to_next10;
      break;

    default:   /* corrupt character mapping table */
      return SFNT_Err_Invalid_CharMap_Format;

    }

    return SFNT_Err_Ok;

  Fail:
    TT_CharMap_Free( face, cmap );
    return error;
  }