Ejemplo n.º 1
0
static FT_Error  Load_LigGlyph( HB_LigGlyph*  lg,
				FT_Stream      stream )
{
  FT_Memory memory = stream->memory;
  FT_Error  error;

  FT_UShort        n, m, count;
  FT_ULong         cur_offset, new_offset, base_offset;

  HB_CaretValue*  cv;


  base_offset = FILE_Pos();

  if ( ACCESS_Frame( 2L ) )
    return error;

  count = lg->CaretCount = GET_UShort();

  FORGET_Frame();

  lg->CaretValue = NULL;

  if ( ALLOC_ARRAY( lg->CaretValue, count, HB_CaretValue ) )
    return error;

  cv = lg->CaretValue;

  for ( n = 0; n < count; n++ )
  {
    if ( ACCESS_Frame( 2L ) )
      goto Fail;

    new_offset = GET_UShort() + base_offset;

    FORGET_Frame();

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_CaretValue( &cv[n], stream ) ) != FT_Err_Ok )
      goto Fail;
    (void)FILE_Seek( cur_offset );
  }

  return FT_Err_Ok;

Fail:
  for ( m = 0; m < n; m++ )
    Free_CaretValue( &cv[m], memory );

  FREE( cv );
  return error;
}
Ejemplo n.º 2
0
  FT_LOCAL
  FT_Error  TT_Init_Face( FT_Stream      stream,
                          TT_Face        face,
                          FT_Int         face_index,
                          FT_Int         num_params,
                          FT_Parameter*  params )
  {
    FT_Error         error;
    FT_Library       library;
    SFNT_Interface*  sfnt;


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

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

    /* check that we have a valid TrueType file */
    error = sfnt->init_face( stream, face, face_index, num_params, params );
    if ( error )
      goto Exit;

    /* We must also be able to accept Mac/GX fonts, as well as OT ones */
    if ( face->format_tag != 0x00010000L &&    /* MS fonts  */
         face->format_tag != TTAG_true   )     /* Mac fonts */
    {
      FT_TRACE2(( "[not a valid TTF font]\n" ));
      goto Bad_Format;
    }

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

    /* Load font directory */
    error = sfnt->load_face( stream, face, face_index, num_params, params );
    if ( error )
      goto Exit;

    if ( face->root.face_flags & FT_FACE_FLAG_SCALABLE )
      error = TT_Load_Locations( face, stream ) ||
              TT_Load_CVT      ( face, stream ) ||
              TT_Load_Programs ( face, stream );

    /* initialize standard glyph loading routines */
    TT_Init_Glyph_Loading( face );

  Exit:
    return error;

  Bad_Format:
    error = FT_Err_Unknown_File_Format;
    goto Exit;
  }
Ejemplo n.º 3
0
  static FT_Error
  fnt_font_load( FNT_Font*  font,
                 FT_Stream  stream )
  {
    FT_Error        error;
    WinFNT_Header*  header = &font->header;


    /* first of all, read the FNT header */
    if ( FILE_Seek( font->offset )                   ||
         READ_Fields( winfnt_header_fields, header ) )
      goto Exit;

    /* check header */
    if ( header->version != 0x200 &&
         header->version != 0x300 )
    {
      FT_TRACE2(( "[not a valid FNT file]\n" ));
      error = FNT_Err_Unknown_File_Format;
      goto Exit;
    }

    if ( header->file_type & 1 )
    {
      FT_TRACE2(( "[can't handle vector FNT fonts]\n" ));
      error = FNT_Err_Unknown_File_Format;
      goto Exit;
    }

    /* small fixup -- some fonts have the `pixel_width' field set to 0 */
    if ( header->pixel_width == 0 )
      header->pixel_width = header->pixel_height;

    /* this is a FNT file/table, we now extract its frame */
    if ( FILE_Seek( font->offset )                           ||
         EXTRACT_Frame( header->file_size, font->fnt_frame ) )
      goto Exit;

  Exit:
    return error;
  }
Ejemplo n.º 4
0
  EXPORT_FUNC
  TT_Error  TT_Load_Kerning_Table( TT_Face    face,
                                   TT_UShort  kern_index )
  {
    TT_Error   error;
    TT_Stream  stream;

    TT_Kerning*        kern;
    TT_Kern_Subtable*  sub;


    PFace  faze = HANDLE_Face( face );

    if ( !faze )
      return TT_Err_Invalid_Face_Handle;

    error = TT_Extension_Get( faze, KERNING_ID, (void**)&kern );
    if ( error )
      return error;

    if ( kern->nTables == 0 )
      return TT_Err_Table_Missing;

    if ( kern_index >= kern->nTables )
      return TT_Err_Invalid_Argument;

    sub = kern->tables + kern_index;

    if ( sub->format != 0 && sub->format != 2 )
      return TT_Err_Invalid_Kerning_Table_Format;

    /* now access stream */
    if ( USE_Stream( faze->stream, stream ) )
      return error;

    if ( FILE_Seek( sub->offset ) )
      goto Fail;

    if ( sub->format == 0 )
      error = Subtable_Load_0( &sub->t.kern0, faze );
    else if ( sub->format == 2 )
      error = Subtable_Load_2( &sub->t.kern2, faze );

    if ( !error )
      sub->loaded = TRUE;

  Fail:
    /* release stream */
    DONE_Stream( stream );

    return error;
  }
Ejemplo n.º 5
0
static FT_Error  GDEF_Create( void*  ext,
			      PFace  face )
{
  DEFINE_LOAD_LOCALS( face->stream );

  HB_GDEFHeader*  gdef = (HB_GDEFHeader*)ext;
  Long             table;


  /* by convention */

  if ( !gdef )
    return FT_Err_Ok;

  /* a null offset indicates that there is no GDEF table */

  gdef->offset = 0;

  /* we store the start offset and the size of the subtable */

  table = HB_LookUp_Table( face, TTAG_GDEF );
  if ( table < 0 )
    return FT_Err_Ok;             /* The table is optional */

  if ( FILE_Seek( face->dirTables[table].Offset ) ||
       ACCESS_Frame( 4L ) )
    return error;

  gdef->offset  = FILE_Pos() - 4L;    /* undo ACCESS_Frame() */
  gdef->Version = GET_ULong();

  FORGET_Frame();

  gdef->loaded = FALSE;

  return FT_Err_Ok;
}
Ejemplo n.º 6
0
static FT_Error  Load_CaretValue( HB_CaretValue*  cv,
				  FT_Stream        stream )
{
  FT_Error  error;

  FT_ULong cur_offset, new_offset, base_offset;


  base_offset = FILE_Pos();

  if ( ACCESS_Frame( 2L ) )
    return error;

  cv->CaretValueFormat = GET_UShort();

  FORGET_Frame();

  switch ( cv->CaretValueFormat )
  {
  case 1:
    if ( ACCESS_Frame( 2L ) )
      return error;

    cv->cvf.cvf1.Coordinate = GET_Short();

    FORGET_Frame();

    break;

  case 2:
    if ( ACCESS_Frame( 2L ) )
      return error;

    cv->cvf.cvf2.CaretValuePoint = GET_UShort();

    FORGET_Frame();

    break;

  case 3:
    if ( ACCESS_Frame( 4L ) )
      return error;

    cv->cvf.cvf3.Coordinate = GET_Short();

    new_offset = GET_UShort() + base_offset;

    FORGET_Frame();

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device,
				stream ) ) != FT_Err_Ok )
      return error;
    (void)FILE_Seek( cur_offset );

    break;

  case 4:
    if ( ACCESS_Frame( 2L ) )
      return error;

    cv->cvf.cvf4.IdCaretValue = GET_UShort();

    FORGET_Frame();
    break;

  default:
    return HB_Err_Invalid_GDEF_SubTable_Format;
  }

  return FT_Err_Ok;
}
Ejemplo n.º 7
0
static FT_Error  Load_AttachList( HB_AttachList*  al,
				  FT_Stream        stream )
{
  FT_Memory memory = stream->memory;
  FT_Error  error;

  FT_UShort         n, m, count;
  FT_ULong          cur_offset, new_offset, base_offset;

  HB_AttachPoint*  ap;


  base_offset = FILE_Pos();

  if ( ACCESS_Frame( 2L ) )
    return error;

  new_offset = GET_UShort() + base_offset;

  FORGET_Frame();

  cur_offset = FILE_Pos();
  if ( FILE_Seek( new_offset ) ||
       ( error = _HB_OPEN_Load_Coverage( &al->Coverage, stream ) ) != FT_Err_Ok )
    return error;
  (void)FILE_Seek( cur_offset );

  if ( ACCESS_Frame( 2L ) )
    goto Fail2;

  count = al->GlyphCount = GET_UShort();

  FORGET_Frame();

  al->AttachPoint = NULL;

  if ( ALLOC_ARRAY( al->AttachPoint, count, HB_AttachPoint ) )
    goto Fail2;

  ap = al->AttachPoint;

  for ( n = 0; n < count; n++ )
  {
    if ( ACCESS_Frame( 2L ) )
      goto Fail1;

    new_offset = GET_UShort() + base_offset;

    FORGET_Frame();

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_AttachPoint( &ap[n], stream ) ) != FT_Err_Ok )
      goto Fail1;
    (void)FILE_Seek( cur_offset );
  }

  al->loaded = TRUE;

  return FT_Err_Ok;

Fail1:
  for ( m = 0; m < n; m++ )
    Free_AttachPoint( &ap[m], memory );

  FREE( ap );

Fail2:
  _HB_OPEN_Free_Coverage( &al->Coverage, memory );
  return error;
}
Ejemplo n.º 8
0
FT_Error  HB_Load_GDEF_Table( FT_Face          face,
			      HB_GDEFHeader** retptr )
{
  FT_Error         error;
  FT_Memory        memory = face->memory;
  FT_Stream        stream = face->stream;
  FT_ULong         cur_offset, new_offset, base_offset;

  HB_GDEFHeader*  gdef;


  if ( !retptr )
    return FT_Err_Invalid_Argument;

  if (( error = _hb_ftglue_face_goto_table( face, TTAG_GDEF, stream ) ))
    return error;

  if (( error = HB_New_GDEF_Table ( face, &gdef ) ))
    return error;

  base_offset = FILE_Pos();

  /* skip version */

  if ( FILE_Seek( base_offset + 4L ) ||
       ACCESS_Frame( 2L ) )
    goto Fail0;

  new_offset = GET_UShort();

  FORGET_Frame();

  /* all GDEF subtables are optional */

  if ( new_offset )
  {
    new_offset += base_offset;

    /* only classes 1-4 are allowed here */

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = _HB_OPEN_Load_ClassDefinition( &gdef->GlyphClassDef, 5,
					 stream ) ) != FT_Err_Ok )
      goto Fail0;
    (void)FILE_Seek( cur_offset );
  }

  if ( ACCESS_Frame( 2L ) )
    goto Fail1;

  new_offset = GET_UShort();

  FORGET_Frame();

  if ( new_offset )
  {
    new_offset += base_offset;

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_AttachList( &gdef->AttachList,
				    stream ) ) != FT_Err_Ok )
      goto Fail1;
    (void)FILE_Seek( cur_offset );
  }

  if ( ACCESS_Frame( 2L ) )
    goto Fail2;

  new_offset = GET_UShort();

  FORGET_Frame();

  if ( new_offset )
  {
    new_offset += base_offset;

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_LigCaretList( &gdef->LigCaretList,
				      stream ) ) != FT_Err_Ok )
      goto Fail2;
    (void)FILE_Seek( cur_offset );
  }

  /* OpenType 1.2 has introduced the `MarkAttachClassDef' field.  We
     first have to scan the LookupFlag values to find out whether we
     must load it or not.  Here we only store the offset of the table. */

  if ( ACCESS_Frame( 2L ) )
    goto Fail3;

  new_offset = GET_UShort();

  FORGET_Frame();

  if ( new_offset )
    gdef->MarkAttachClassDef_offset = new_offset + base_offset;
  else
    gdef->MarkAttachClassDef_offset = 0;

  *retptr = gdef;

  return FT_Err_Ok;

Fail3:
  Free_LigCaretList( &gdef->LigCaretList, memory );
  
Fail2:
  Free_AttachList( &gdef->AttachList, memory );

Fail1:
  _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory );

Fail0:
  FREE( gdef );

  return error;
}
Ejemplo n.º 9
0
  static FT_Error
  fnt_face_get_dll_fonts( FNT_Face  face )
  {
    FT_Error      error;
    FT_Stream     stream = FT_FACE(face)->stream;
    FT_Memory     memory = FT_FACE(face)->memory;
    WinMZ_Header  mz_header;


    face->fonts     = 0;
    face->num_fonts = 0;

    /* does it begin with a MZ header? */
    if ( FILE_Seek( 0 )                                 ||
         READ_Fields( winmz_header_fields, &mz_header ) )
      goto Exit;

    error = FNT_Err_Unknown_File_Format;
    if ( mz_header.magic == WINFNT_MZ_MAGIC )
    {
      /* yes, now look for a NE header in the file */
      WinNE_Header  ne_header;


      if ( FILE_Seek( mz_header.lfanew )                  ||
           READ_Fields( winne_header_fields, &ne_header ) )
        goto Exit;

      error = FNT_Err_Unknown_File_Format;
      if ( ne_header.magic == WINFNT_NE_MAGIC )
      {
        /* good, now look in the resource table for each FNT resource */
        FT_ULong   res_offset = mz_header.lfanew +
                                ne_header.resource_tab_offset;

        FT_UShort  size_shift;
        FT_UShort  font_count  = 0;
        FT_ULong   font_offset = 0;


        if ( FILE_Seek( res_offset ) ||
             ACCESS_Frame( ne_header.rname_tab_offset -
                           ne_header.resource_tab_offset ) )
          goto Exit;

        size_shift = GET_UShortLE();

        for (;;)
        {
          FT_UShort  type_id, count;


          type_id = GET_UShortLE();
          if ( !type_id )
            break;

          count = GET_UShortLE();

          if ( type_id == 0x8008 )
          {
            font_count  = count;
            font_offset = (FT_ULong)( FILE_Pos() + 4 +
                                      ( stream->cursor - stream->limit ) );
            break;
          }

          stream->cursor += 4 + count * 12;
        }
        FORGET_Frame();

        if ( !font_count || !font_offset )
        {
          FT_TRACE2(( "this file doesn't contain any FNT resources!\n" ));
          error = FNT_Err_Unknown_File_Format;
          goto Exit;
        }

        if ( FILE_Seek( font_offset )                         ||
             ALLOC_ARRAY( face->fonts, font_count, FNT_Font ) )
          goto Exit;

        face->num_fonts = font_count;

        if ( ACCESS_Frame( (FT_Long)font_count * 12 ) )
          goto Exit;

        /* now read the offset and position of each FNT font */
        {
          FNT_Font*  cur   = face->fonts;
          FNT_Font*  limit = cur + font_count;


          for ( ; cur < limit; cur++ )
          {
            cur->offset     = (FT_ULong)GET_UShortLE() << size_shift;
            cur->fnt_size   = (FT_ULong)GET_UShortLE() << size_shift;
            cur->size_shift = size_shift;
            stream->cursor += 8;
          }
        }
        FORGET_Frame();

        /* finally, try to load each font there */
        {
          FNT_Font*  cur   = face->fonts;
          FNT_Font*  limit = cur + font_count;


          for ( ; cur < limit; cur++ )
          {
            error = fnt_font_load( cur, stream );
            if ( error )
              goto Fail;
          }
        }
      }
    }

  Fail:
    if ( error )
      fnt_face_done_fonts( face );

  Exit:
    return error;
  }
Ejemplo n.º 10
0
Load_TrueType_Glyph( PInstance  instance,
                     PGlyph     glyph,
                     UShort     glyph_index,
                     UShort     load_flags )
{
    enum TPhases_
    {
        Load_Exit,
        Load_Glyph,
        Load_Header,
        Load_Simple,
        Load_Composite,
        Load_End
    };

    typedef enum TPhases_  TPhases;

    DEFINE_ALL_LOCALS;

    PFace   face;

    UShort  num_points;
    Short   num_contours;
    UShort  left_points;
    Short   left_contours;
    UShort  num_elem_points;

    Long    table;
    UShort  load_top;
    Long    k, l;
    UShort  new_flags;
    Long    index;
    UShort  u, v;

    Long  glyph_offset, offset;

    TT_F26Dot6  x, y, nx, ny;

    Fixed  xx, xy, yx, yy;

    PExecution_Context  exec;

    PSubglyph_Record  subglyph, subglyph2;

    TGlyph_Zone base_pts;

    TPhases     phase;
    PByte       widths;

    /*  TT_Glyph_Loader_Callback  cacheCb;        */
    /*  TT_Outline                cached_outline; */


    /* first of all, check arguments */
    if ( !glyph )
        return TT_Err_Invalid_Glyph_Handle;

    face = glyph->face;
    if ( !face )
        return TT_Err_Invalid_Glyph_Handle;

    if ( glyph_index >= face->numGlyphs )
        return TT_Err_Invalid_Glyph_Index;

    if ( instance && (load_flags & TTLOAD_SCALE_GLYPH) == 0 )
    {
        instance    = 0;
        load_flags &= ~( TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH );
    }

    table = TT_LookUp_Table( face, TTAG_glyf );
    if ( table < 0 )
    {
        PTRACE0(( "ERROR: There is no glyph table in this font file!\n" ));
        return TT_Err_Glyf_Table_Missing;
    }

    glyph_offset = face->dirTables[table].Offset;

    /* query new execution context */

    if ( instance && instance->debug )
        exec = instance->context;
    else
        exec = New_Context( face );

    if ( !exec )
        return TT_Err_Could_Not_Find_Context;

    Context_Load( exec, face, instance );

    if ( instance )
    {
        if ( instance->GS.instruct_control & 2 )
            exec->GS = Default_GraphicsState;
        else
            exec->GS = instance->GS;
        /* load default graphics state */

        glyph->outline.high_precision = ( instance->metrics.y_ppem < 24 );
    }

    /* save its critical pointers, as they'll be modified during load */
    base_pts = exec->pts;

    /* init variables */
    left_points   = face->maxPoints;
    left_contours = face->maxContours;

    num_points   = 0;
    num_contours = 0;

    load_top = 0;
    subglyph = exec->loadStack;

    Init_Glyph_Component( subglyph, NULL, exec );

    subglyph->index     = glyph_index;
    subglyph->is_hinted = load_flags & TTLOAD_HINT_GLYPH;

    /* when the cvt program has disabled hinting, the argument */
    /* is ignored.                                             */
    if ( instance && instance->GS.instruct_control & 1 )
        subglyph->is_hinted = FALSE;


    /* now access stream */

    if ( USE_Stream( face->stream, stream ) )
        goto Fin;

    /* Main loading loop */

    phase = Load_Glyph;
    index = 0;

    while ( phase != Load_Exit )
    {
        subglyph = exec->loadStack + load_top;

        switch ( phase )
        {
        /************************************************************/
        /*                                                          */
        /* Load_Glyph state                                         */
        /*                                                          */
        /*   reading a glyph's generic header to determine          */
        /*   whether it's simple or composite                       */
        /*                                                          */
        /* exit states: Load_Header and Load_End                    */

        case Load_Glyph:
            /* check glyph index and table */

            index = subglyph->index;
            if ( index < 0 || index >= face->numGlyphs )
            {
                error = TT_Err_Invalid_Glyph_Index;
                goto Fail;
            }

            /* get horizontal metrics */

            {
                Short   left_bearing;
                UShort  advance_width;


                Get_HMetrics( face, (UShort)index,
                              !(load_flags & TTLOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
                              &left_bearing,
                              &advance_width );

                subglyph->metrics.horiBearingX = left_bearing;
                subglyph->metrics.horiAdvance  = advance_width;
            }

            phase = Load_Header;


            /* The cache callback isn't part of the FreeType release yet */
            /* It is discarded for the moment..                          */
            /*                                                           */
#if 0
            if ( instance )
            {
                /* is the glyph in an outline cache ? */
                cacheCb = instance->owner->engine->glCallback;
                if ( cacheCb && 0 )   /* disabled */
                {
                    /* we have a callback */
                    error = cacheCb( instance->generic,
                                     index, &cached_outline, &x, &y );
                    if ( !error )
                    {
                        /* no error, then append the outline to the current subglyph */
                        /* error = Append_Outline( subglyph,
                                                   &left_points,
                                                   &left_contours,
                                                   &cached_outline ); */
                        phase = Load_End;
                    }
                }
            }
#endif
            break;


        /************************************************************/
        /*                                                          */
        /* Load_Header state                                        */
        /*                                                          */
        /*   reading a glyph's generic header to determine          */
        /*   wether it's simple or composite                        */
        /*                                                          */
        /* exit states: Load_Simple and Load_Composite              */
        /*                                                          */

        case Load_Header: /* load glyph */

            if ( (TT_UInt)( index + 1 ) < (TT_UInt)face->numLocations &&
                    face->glyphLocations[index] == face->glyphLocations[index + 1] )
            {
                /* as described by Frederic Loyer, these are spaces, and */
                /* not the unknown glyph.                                */

                num_contours = 0;
                num_points   = 0;

                subglyph->metrics.bbox.xMin = 0;
                subglyph->metrics.bbox.xMax = 0;
                subglyph->metrics.bbox.yMin = 0;
                subglyph->metrics.bbox.yMax = 0;

                subglyph->pp1.x = 0;
                subglyph->pp2.x = subglyph->metrics.horiAdvance;
                if (load_flags & TTLOAD_SCALE_GLYPH)
                    subglyph->pp2.x = Scale_X( &exec->metrics, subglyph->pp2.x );

                exec->glyphSize = 0;
                phase = Load_End;
                break;
            }

            offset = glyph_offset + face->glyphLocations[index];

            /* read first glyph header */
            if ( FILE_Seek( offset ) ||
                    ACCESS_Frame( 10L ) )
                goto Fail_File;

            num_contours = GET_Short();

            subglyph->metrics.bbox.xMin = GET_Short();
            subglyph->metrics.bbox.yMin = GET_Short();
            subglyph->metrics.bbox.xMax = GET_Short();
            subglyph->metrics.bbox.yMax = GET_Short();

            FORGET_Frame();

            PTRACE6(( "Glyph %ld:\n", index ));
            PTRACE6(( " # of contours: %d\n", num_contours ));
            PTRACE6(( " xMin: %4d  xMax: %4d\n",
                      subglyph->metrics.bbox.xMin,
                      subglyph->metrics.bbox.xMax ));
            PTRACE6(( " yMin: %4d  yMax: %4d\n",
                      subglyph->metrics.bbox.yMin,
                      subglyph->metrics.bbox.yMax ));

            if ( num_contours > left_contours )
            {
                PTRACE0(( "ERROR: Too many contours for glyph %ld\n", index ));
                error = TT_Err_Too_Many_Contours;
                goto Fail;
            }

            subglyph->pp1.x = subglyph->metrics.bbox.xMin -
                              subglyph->metrics.horiBearingX;
            subglyph->pp1.y = 0;
            subglyph->pp2.x = subglyph->pp1.x + subglyph->metrics.horiAdvance;
            if (load_flags & TTLOAD_SCALE_GLYPH)
            {
                subglyph->pp1.x = Scale_X( &exec->metrics, subglyph->pp1.x );
                subglyph->pp2.x = Scale_X( &exec->metrics, subglyph->pp2.x );
            }

            /* is it a simple glyph ? */
            if ( num_contours > 0 )
                phase = Load_Simple;
            else
                phase = Load_Composite;

            break;


        /************************************************************/
        /*                                                          */
        /* Load_Simple state                                        */
        /*                                                          */
        /*   reading a simple glyph (num_contours must be set to    */
        /*   the glyph's number of contours.)                       */
        /*                                                          */
        /* exit states : Load_End                                   */
        /*                                                          */

        case Load_Simple:
            new_flags = load_flags;

            /* disable hinting when scaling */
            if ( !subglyph->is_hinted )
                new_flags &= ~TTLOAD_HINT_GLYPH;

            error = Load_Simple_Glyph( exec,
                                       stream,
                                       num_contours,
                                       left_contours,
                                       left_points,
                                       new_flags,
                                       subglyph );
            if ( error )
                goto Fail;

            /* Note: We could have put the simple loader source there */
            /*       but the code is fat enough already :-)           */

            num_points = exec->pts.n_points - 2;

            phase = Load_End;

            break;


        /************************************************************/
        /*                                                          */
        /* Load_Composite state                                     */
        /*                                                          */
        /*   reading a composite glyph header a pushing a new       */
        /*   load element on the stack.                             */
        /*                                                          */
        /* exit states: Load_Glyph                                  */
        /*                                                          */

        case Load_Composite:

            /* create a new element on the stack */
            load_top++;

            if ( load_top > face->maxComponents )
            {
                error = TT_Err_Invalid_Composite;
                goto Fail;
            }

            subglyph2 = exec->loadStack + load_top;

            Init_Glyph_Component( subglyph2, subglyph, NULL );
            subglyph2->is_hinted = subglyph->is_hinted;

            /* now read composite header */

            if ( ACCESS_Frame( 4L ) )
                goto Fail_File;

            subglyph->element_flag = new_flags = GET_UShort();

            subglyph2->index = GET_UShort();

            FORGET_Frame();

            k = 1 + 1;

            if ( new_flags & ARGS_ARE_WORDS )
                k *= 2;

            if ( new_flags & WE_HAVE_A_SCALE )
                k += 2;

            else if ( new_flags & WE_HAVE_AN_XY_SCALE )
                k += 4;

            else if ( new_flags & WE_HAVE_A_2X2 )
                k += 8;

            if ( ACCESS_Frame( k ) )
                goto Fail_File;

            if ( new_flags & ARGS_ARE_WORDS )
            {
                k = GET_Short();
                l = GET_Short();
            }
            else
            {
                k = GET_Char();
                l = GET_Char();
            }

            subglyph->arg1 = k;
            subglyph->arg2 = l;

            if ( new_flags & ARGS_ARE_XY_VALUES )
            {
                subglyph->transform.ox = k;
                subglyph->transform.oy = l;
            }

            xx = 1L << 16;
            xy = 0;
            yx = 0;
            yy = 1L << 16;

            if ( new_flags & WE_HAVE_A_SCALE )
            {
                xx = (Fixed)GET_Short() << 2;
                yy = xx;
                subglyph2->is_scaled = TRUE;
            }
            else if ( new_flags & WE_HAVE_AN_XY_SCALE )
            {
                xx = (Fixed)GET_Short() << 2;
                yy = (Fixed)GET_Short() << 2;
                subglyph2->is_scaled = TRUE;
            }
            else if ( new_flags & WE_HAVE_A_2X2 )
            {
                xx = (Fixed)GET_Short() << 2;
                xy = (Fixed)GET_Short() << 2;
                yx = (Fixed)GET_Short() << 2;
                yy = (Fixed)GET_Short() << 2;
                subglyph2->is_scaled = TRUE;
            }

            FORGET_Frame();

            subglyph->transform.xx = xx;
            subglyph->transform.xy = xy;
            subglyph->transform.yx = yx;
            subglyph->transform.yy = yy;

            k = TT_MulFix( xx, yy ) -  TT_MulFix( xy, yx );

            /* disable hinting in case of scaling/slanting */
            if ( ABS( k ) != (1L << 16) )
                subglyph2->is_hinted = FALSE;

            subglyph->file_offset = FILE_Pos();

            phase = Load_Glyph;

            break;


        /************************************************************/
        /*                                                          */
        /* Load_End state                                           */
        /*                                                          */
        /*   after loading a glyph, apply transformation and offset */
        /*   where necessary, pops element and continue or          */
        /*   stop process.                                          */
        /*                                                          */
        /* exit states : Load_Composite and Load_Exit               */
        /*                                                          */

        case Load_End:
            if ( load_top > 0 )
            {
                subglyph2 = subglyph;

                load_top--;
                subglyph = exec->loadStack + load_top;

                /* check advance width and left side bearing */

                if ( !subglyph->preserve_pps &&
                        subglyph->element_flag & USE_MY_METRICS )
                {
                    subglyph->metrics.horiBearingX = subglyph2->metrics.horiBearingX;
                    subglyph->metrics.horiAdvance  = subglyph2->metrics.horiAdvance;

                    subglyph->pp1 = subglyph2->pp1;
                    subglyph->pp2 = subglyph2->pp2;

                    subglyph->preserve_pps = TRUE;
                }

                /* apply scale */

                if ( subglyph2->is_scaled )
                {
                    TT_Vector*  cur = subglyph2->zone.cur;
                    TT_Vector*  org = subglyph2->zone.org;

                    for ( u = 0; u < num_points; u++ )
                    {
                        nx = TT_MulFix( cur->x, subglyph->transform.xx ) +
                             TT_MulFix( cur->y, subglyph->transform.yx );

                        ny = TT_MulFix( cur->x, subglyph->transform.xy ) +
                             TT_MulFix( cur->y, subglyph->transform.yy );

                        cur->x = nx;
                        cur->y = ny;

                        nx = TT_MulFix( org->x, subglyph->transform.xx ) +
                             TT_MulFix( org->y, subglyph->transform.yx );

                        ny = TT_MulFix( org->x, subglyph->transform.xy ) +
                             TT_MulFix( org->y, subglyph->transform.yy );

                        org->x = nx;
                        org->y = ny;

                        cur++;
                        org++;
                    }
                }

                /* adjust counts */

                num_elem_points = subglyph->zone.n_points;

                for ( k = 0; k < num_contours; k++ )
                    subglyph2->zone.contours[k] += num_elem_points;

                subglyph->zone.n_points   += num_points;
                subglyph->zone.n_contours += num_contours;

                left_points   -= num_points;
                left_contours -= num_contours;

                if ( !(subglyph->element_flag & ARGS_ARE_XY_VALUES) )
                {
                    /* move second glyph according to control points */
                    /* the attach points are relative to the specific component */

                    u = (UShort)subglyph->arg1;
                    v = (UShort)subglyph->arg2;

                    if ( u >= num_elem_points ||
                            v >= num_points )
                    {
                        error = TT_Err_Invalid_Composite;
                        goto Fail;
                    }

                    /* adjust count */
                    v += num_elem_points;

                    x = subglyph->zone.cur[u].x - subglyph->zone.cur[v].x;
                    y = subglyph->zone.cur[u].y - subglyph->zone.cur[v].y;
                }
                else
                {
                    /* apply offset */

                    x = subglyph->transform.ox;
                    y = subglyph->transform.oy;

                    if ( load_flags & TTLOAD_SCALE_GLYPH )
                    {
                        x = Scale_X( &exec->metrics, x );
                        y = Scale_Y( &exec->metrics, y );

                        if ( subglyph->element_flag & ROUND_XY_TO_GRID )
                        {
                            x = (x+32) & -64;
                            y = (y+32) & -64;
                        }
                    }
                }

                translate_array( num_points, subglyph2->zone.cur, x, y );

                cur_to_org( num_points, &subglyph2->zone );

                num_points   = subglyph->zone.n_points;
                num_contours = subglyph->zone.n_contours;

                /* check for last component */

                if ( FILE_Seek( subglyph->file_offset ) )
                    goto Fail_File;

                if ( subglyph->element_flag & MORE_COMPONENTS )
                    phase = Load_Composite;
                else
                {
                    error = Load_Composite_End( num_points,
                                                num_contours,
                                                exec,
                                                subglyph,
                                                load_flags,
                                                stream );
                    if ( error )
                        goto Fail;

                    phase = Load_End;
                }
            }
            else
                phase = Load_Exit;

            break;


        case Load_Exit:
            break;
        }
    }

    /* finally, copy the points arrays to the glyph object */

    exec->pts = base_pts;

    for ( u = 0; u < num_points + 2; u++ )
    {
        glyph->outline.points[u] = exec->pts.cur[u];
        glyph->outline.flags [u] = exec->pts.touch[u];
    }

    for ( k = 0; k < num_contours; k++ )
        glyph->outline.contours[k] = exec->pts.contours[k];

    glyph->outline.n_points    = num_points;
    glyph->outline.n_contours  = num_contours;
    glyph->outline.second_pass = TRUE;

    /* translate array so that (0,0) is the glyph's origin */
    translate_array( num_points + 2,
                     glyph->outline.points,
                     -subglyph->pp1.x,
                     0 );

    TT_Get_Outline_BBox( &glyph->outline, &glyph->metrics.bbox );

    if ( subglyph->is_hinted )
    {
        /* grid-fit the bounding box */
        glyph->metrics.bbox.xMin &= -64;
        glyph->metrics.bbox.yMin &= -64;
        glyph->metrics.bbox.xMax  = (glyph->metrics.bbox.xMax+63) & -64;
        glyph->metrics.bbox.yMax  = (glyph->metrics.bbox.yMax+63) & -64;
    }

    /* get the device-independent scaled horizontal metrics */
    /* take care of fixed-pitch fonts...                    */
    {
        TT_Pos  left_bearing;
        TT_Pos  advance;


        left_bearing = subglyph->metrics.horiBearingX;
        advance      = subglyph->metrics.horiAdvance;

        if ( face->postscript.isFixedPitch )
            advance = face->horizontalHeader.advance_Width_Max;

        if ( load_flags & TTLOAD_SCALE_GLYPH )
        {
            left_bearing = Scale_X( &exec->metrics, left_bearing );
            advance      = Scale_X( &exec->metrics, advance      );
        }

        glyph->metrics.linearHoriBearingX = left_bearing;
        glyph->metrics.linearHoriAdvance  = advance;
    }

    glyph->metrics.horiBearingX = glyph->metrics.bbox.xMin;
    glyph->metrics.horiBearingY = glyph->metrics.bbox.yMax;
    glyph->metrics.horiAdvance  = subglyph->pp2.x - subglyph->pp1.x;

    /* Now take care of vertical metrics.  In the case where there is    */
    /* no vertical information within the font (relatively common), make */
    /* up some metrics `by hand' ...                                     */

    {
        Short   top_bearing;    /* vertical top side bearing (EM units) */
        UShort  advance_height; /* vertical advance height (EM units)   */

        TT_Pos  left;     /* scaled vertical left side bearing          */
        TT_Pos  orig_top; /* scaled original vertical top side bearing  */
        TT_Pos  top;      /* scaled vertical top side bearing           */
        TT_Pos  advance;  /* scaled vertical advance height             */


        /* Get the unscaled `tsb' and `ah' values */
        if ( face->verticalInfo                          &&
                face->verticalHeader.number_Of_VMetrics > 0 )
        {
            /* Don't assume that both the vertical header and vertical */
            /* metrics are present in the same font :-)                */

            TT_Get_Metrics( (TT_Horizontal_Header*)&face->verticalHeader,
                            glyph_index,
                            &top_bearing,
                            &advance_height );
        }
        else
        {

            /* Make up the distances from the horizontal header..     */

            /* NOTE: The OS/2 values are the only `portable' ones,    */
            /*       which is why we use them...                      */
            /*                                                        */
            /* NOTE2: The sTypoDescender is negative, which is why    */
            /*        we compute the baseline-to-baseline distance    */
            /*        here with :                                     */
            /*             ascender - descender + linegap             */
            /*                                                        */

            /* XXX What happens here with these Apple fonts without OS/2 table ? */

            top_bearing    = (Short) (face->os2.sTypoLineGap / 2);
            advance_height = (UShort)(face->os2.sTypoAscender -
                                      face->os2.sTypoDescender +
                                      face->os2.sTypoLineGap);
        }

        /* We must adjust the top_bearing value from the bounding box   */
        /* given in the glyph header to te bounding box calculated with */
        /* TT_Get_Outline_BBox()                                        */

        /* scale the metrics */
        if ( load_flags & TTLOAD_SCALE_GLYPH )
        {
            orig_top = Scale_Y( &exec->metrics, top_bearing );
            top      = Scale_Y( &exec->metrics,
                                top_bearing + subglyph->metrics.bbox.yMax ) -
                       glyph->metrics.bbox.yMax;
            advance  = Scale_Y( &exec->metrics, advance_height );
        }
        else
        {
            orig_top = top_bearing;
            top      = top_bearing + subglyph->metrics.bbox.yMax -
                       glyph->metrics.bbox.yMax;
            advance  = advance_height;
        }

        glyph->metrics.linearVertBearingY = orig_top;
        glyph->metrics.linearVertAdvance  = advance;

        /* XXX : for now, we have no better algo for the lsb, but it should */
        /*       work ok..                                                  */
        /*                                                                  */
        left = ( glyph->metrics.bbox.xMin - glyph->metrics.bbox.xMax ) / 2;

        /* grid-fit them if necessary */
        if ( subglyph->is_hinted )
        {
            left   &= -64;
            top     = (top + 63) & -64;
            advance = (advance + 32) & -64;
        }

        glyph->metrics.vertBearingX = left;
        glyph->metrics.vertBearingY = top;
        glyph->metrics.vertAdvance  = advance;
    }

    /* Adjust advance width to the value contained in the hdmx table. */
    if ( !exec->face->postscript.isFixedPitch && instance &&
            subglyph->is_hinted )
    {
        widths = Get_Advance_Widths( exec->face,
                                     exec->instance->metrics.x_ppem );
        if ( widths )
            glyph->metrics.horiAdvance = widths[glyph_index] << 6;
    }

    glyph->outline.dropout_mode = (Char)exec->GS.scan_type;

    error = TT_Err_Ok;

Fail_File:
Fail:
    DONE_Stream( stream );

Fin:

    /* reset the execution context */
    exec->pts = base_pts;

    if ( !instance || !instance->debug )
        Done_Context( exec );

    return error;
}
Ejemplo n.º 11
0
  TT_Get_Face_Widths( TT_Face     face,
                      TT_UShort   first_glyph,
                      TT_UShort   last_glyph,
                      TT_UShort*  widths,
                      TT_UShort*  heights )
  {
    DEFINE_ALL_LOCALS;

    PFace     faze = HANDLE_Face(face);
    UShort    n;
    Long      table;

    ULong     glyf_offset;      /* offset of glyph table in file */
    UShort    zero_width  = 0;  /* width of glyph 0  */
    UShort    zero_height = 0;  /* height of glyph 0 */

    Bool      zero_loaded = 0;

#ifndef TT_HUGE_PTR
    PStorage  locations;
#else
    Storage TT_HUGE_PTR * locations;
#endif
    TT_BBox   bbox;


    if ( !faze )
      return TT_Err_Invalid_Face_Handle;

    if ( last_glyph >= faze->numGlyphs ||
         first_glyph > last_glyph      )
      return TT_Err_Invalid_Argument;

    /* find "glyf" table */
    table = TT_LookUp_Table( faze, TTAG_glyf );
    if ( table < 0 )
    {
      PERROR(( "ERROR: there is no glyph table in this font file!\n" ));
      return TT_Err_Glyf_Table_Missing;
    }
    glyf_offset = faze->dirTables[table].Offset;

    /* now access stream */
    if ( USE_Stream( faze->stream, stream ) )
      return error;

    locations = faze->glyphLocations + first_glyph;

    /* loop to load each glyph in the range */
    for ( n = first_glyph; n <= last_glyph; n++ )
    {
      if ( n + 1 < faze->numGlyphs &&
           locations[0] == locations[1] )
      {
        /* Note : Glyph 0 is always used to indicate a missing glyph   */
        /*        in a range. We must thus return its width and height */
        /*        where appropriate when we find an undefined glyph.   */
        if ( zero_loaded == 0 )
        {
          if ( FILE_Seek( glyf_offset + faze->glyphLocations[0] ) ||
               ACCESS_Frame( 10L ) )
            goto Fail;

          (void)GET_Short();   /* skip number of contours */

          bbox.xMin = GET_Short();
          bbox.yMin = GET_Short();
          bbox.xMax = GET_Short();
          bbox.yMax = GET_Short();

          FORGET_Frame();

          zero_width  = (UShort)(bbox.xMax - bbox.xMin);
          zero_height = (UShort)(bbox.yMax - bbox.yMin);
          zero_loaded = 1;
        }

        if ( widths )
          *widths++  = zero_width;

        if ( heights )
          *heights++ = zero_height;
      }
      else
      {
        /* normal glyph, read header */
        if ( FILE_Seek( glyf_offset + locations[0] ) ||
             ACCESS_Frame( 10L ) )
          goto Fail;

        (void)GET_Short();  /* skip number of contours */

        bbox.xMin = GET_Short();
        bbox.yMin = GET_Short();
        bbox.xMax = GET_Short();
        bbox.yMax = GET_Short();

        FORGET_Frame();

        if ( widths )
          *widths++  = (UShort)(bbox.xMax - bbox.xMin);

        if ( heights )
          *heights++ = (UShort)(bbox.yMax - bbox.yMin);
      }
    }

  Fail:
    DONE_Stream( stream );
    return error;
  }
Ejemplo n.º 12
0
  static TT_Error
  Kerning_Create( void*  ext,
                  PFace  face )
  {
    DEFINE_LOAD_LOCALS( face->stream );

    TT_Kerning*  kern = (TT_Kerning*)ext;
    UShort       num_tables;
    Long         table;

    TT_Kern_Subtable*  sub;


    /* by convention */
    if ( !kern )
      return TT_Err_Ok;

    /* Now load the kerning directory. We're called from the face */
    /* constructor.  We thus need not use the stream.             */

    kern->version = 0;
    kern->nTables = 0;
    kern->tables  = NULL;

    table = TT_LookUp_Table( face, TTAG_kern );
    if ( table < 0 )
      return TT_Err_Ok;  /* The table is optional */

    if ( FILE_Seek( face->dirTables[table].Offset ) ||
         ACCESS_Frame( 4L ) )
      return error;

    kern->version = GET_UShort();
    num_tables    = GET_UShort();

    FORGET_Frame();

    /* we don't set kern->nTables until we have allocated the array */

    if ( ALLOC_ARRAY( kern->tables, num_tables, TT_Kern_Subtable ) )
      return error;

    kern->nTables = num_tables;

    /* now load the directory entries, but do _not_ load the tables ! */

    sub = kern->tables;

    for ( table = 0; table < num_tables; table++ )
    {
      if ( ACCESS_Frame( 6L ) )
        return error;

      sub->loaded   = FALSE;             /* redundant, but good to see */
      sub->version  = GET_UShort();
      sub->length   = GET_UShort() - 6;  /* substract header length */
      sub->format   = GET_Byte();
      sub->coverage = GET_Byte();

      FORGET_Frame();

      sub->offset = FILE_Pos();

      /* now skip to the next table */

      if ( FILE_Skip( sub->length ) )
        return error;

      sub++;
    }

    /* that's fine, leave now */

    return TT_Err_Ok;
  }
Ejemplo n.º 13
0
  static TT_Error
  Subtable_Load_2( TT_Kern_2*  kern2,
                   PFace       input )
  {
    DEFINE_LOAD_LOCALS( input->stream );

    Long  table_base;

    UShort  left_offset, right_offset, array_offset;
    ULong   array_size;
    UShort  left_max, right_max, n;


    /* record the table offset */
    table_base = FILE_Pos();

    if ( ACCESS_Frame( 8L ) )
      return error;

    kern2->rowWidth = GET_UShort();
    left_offset     = GET_UShort();
    right_offset    = GET_UShort();
    array_offset    = GET_UShort();

    FORGET_Frame();

    /* first load left and right glyph classes */

    if ( FILE_Seek( table_base + left_offset ) ||
         ACCESS_Frame( 4L ) )
      return error;

    kern2->leftClass.firstGlyph = GET_UShort();
    kern2->leftClass.nGlyphs    = GET_UShort();

    FORGET_Frame();

    if ( ALLOC_ARRAY( kern2->leftClass.classes,
                      kern2->leftClass.nGlyphs,
                      UShort ) )
      return error;

    /* load left offsets */

    if ( ACCESS_Frame( kern2->leftClass.nGlyphs * 2L ) )
      goto Fail_Left;

    for ( n = 0; n < kern2->leftClass.nGlyphs; n++ )
      kern2->leftClass.classes[n] = GET_UShort();

    FORGET_Frame();

    /* right class */

    if ( FILE_Seek( table_base + right_offset ) ||
         ACCESS_Frame( 4L ) )
      goto Fail_Left;

    kern2->rightClass.firstGlyph = GET_UShort();
    kern2->rightClass.nGlyphs    = GET_UShort();

    FORGET_Frame();

    if ( ALLOC_ARRAY( kern2->rightClass.classes,
                      kern2->rightClass.nGlyphs,
                      UShort ) )
      goto Fail_Left;

    /* load right offsets */

    if ( ACCESS_Frame( kern2->rightClass.nGlyphs * 2L ) )
      goto Fail_Right;

    for ( n = 0; n < kern2->rightClass.nGlyphs; n++ )
      kern2->rightClass.classes[n] = GET_UShort();

    FORGET_Frame();

    /* Now load the kerning array.  We don't have its size, we */
    /* must compute it from what we know.                      */

    /* We thus compute the maximum left and right offsets and  */
    /* add them to get the array size.                         */

    left_max = right_max = 0;

    for ( n = 0; n < kern2->leftClass.nGlyphs; n++ )
      left_max = MAX( left_max, kern2->leftClass.classes[n] );

    for ( n = 0; n < kern2->rightClass.nGlyphs; n++ )
      right_max = MAX( right_max, kern2->leftClass.classes[n] );

    array_size = left_max + right_max + 2;

    if ( ALLOC( kern2->array, array_size ) )
      goto Fail_Right;

    if ( ACCESS_Frame( array_size ) )
      goto Fail_Array;

    for ( n = 0; (UInt)n < array_size/2; n++ )
      kern2->array[n] = GET_Short();

    FORGET_Frame();

    /* we're good now */

    return TT_Err_Ok;

  Fail_Array:
    FREE( kern2->array );

  Fail_Right:
    FREE( kern2->rightClass.classes );
    kern2->rightClass.nGlyphs = 0;

  Fail_Left:
    FREE( kern2->leftClass.classes );
    kern2->leftClass.nGlyphs = 0;

    return error;
  }
Ejemplo n.º 14
0
  FT_LOCAL_DEF
  FT_Error  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_UShort  u, l;

    TT_CMap0*  cmap0;
    TT_CMap2*  cmap2;
    TT_CMap4*  cmap4;
    TT_CMap6*  cmap6;

    TT_CMap2SubHeader*  cmap2sub;
    TT_CMap4Segment*    segments;


    if ( cmap->loaded )
      return TT_Err_Ok;

    memory = stream->memory;

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

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

      if ( ALLOC( cmap0->glyphIdArray, 256L )            ||
           FILE_Read( cmap0->glyphIdArray, 256L ) )
         goto Fail;

      cmap->get_index = code_to_index0;
      break;

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

      /* allocate subheader keys */

      if ( ALLOC_ARRAY( cmap2->subHeaderKeys, 256, FT_UShort ) ||
           ACCESS_Frame( 512L )                                )
        goto Fail;

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

        if ( num_SH < u )
          num_SH = u;
      }

      FORGET_Frame();

      /* load subheaders */

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

      if ( ALLOC_ARRAY( cmap2->subHeaders,
                        num_SH + 1,
                        TT_CMap2SubHeader )    ||
           ACCESS_Frame( ( num_SH + 1 ) * 8L ) )
        goto Fail;

      cmap2sub = cmap2->subHeaders;

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

        cmap2sub++;
      }

      FORGET_Frame();

      /* load glyph IDs */

      if ( ALLOC_ARRAY( cmap2->glyphIdArray, l, FT_UShort ) ||
           ACCESS_Frame( l * 2L )                           )
        goto Fail;

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

      FORGET_Frame();

      cmap->get_index = code_to_index2;
      break;

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

      /* load header */

      if ( ACCESS_Frame( 8L ) )
        goto Fail;

      cmap4->segCountX2    = GET_UShort();
      cmap4->searchRange   = GET_UShort();
      cmap4->entrySelector = GET_UShort();
      cmap4->rangeShift    = GET_UShort();

      num_Seg = cmap4->segCountX2 / 2;

      FORGET_Frame();

      /* load segments */

      if ( ALLOC_ARRAY( cmap4->segments,
                        num_Seg,
                        TT_CMap4Segment )           ||
           ACCESS_Frame( ( num_Seg * 4 + 1 ) * 2L ) )
        goto Fail;

      segments = cmap4->segments;

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

      (void)GET_UShort();

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

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

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

      FORGET_Frame();

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

      /* load IDs */

      if ( ALLOC_ARRAY( cmap4->glyphIdArray, l, FT_UShort ) ||
           ACCESS_Frame( l * 2L )                           )
        goto Fail;

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

      FORGET_Frame();

      cmap->get_index = code_to_index4;

      cmap4->last_segment = cmap4->segments;
      break;

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

      if ( ACCESS_Frame( 4L ) )
        goto Fail;

      cmap6->firstCode  = GET_UShort();
      cmap6->entryCount = GET_UShort();

      FORGET_Frame();

      l = cmap6->entryCount;

      if ( ALLOC_ARRAY( cmap6->glyphIdArray,
                        cmap6->entryCount,
                        FT_Short )           ||
           ACCESS_Frame( l * 2L )            )
        goto Fail;

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

      FORGET_Frame();
      cmap->get_index = code_to_index6;
      break;

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

    }

    return TT_Err_Ok;

  Fail:
    TT_CharMap_Free( face, cmap );
    return error;
  }
Ejemplo n.º 15
0
  cid_load_glyph( T1_Decoder*  decoder,
                  FT_UInt      glyph_index )
  {
    CID_Face   face = (CID_Face)decoder->builder.face;
    CID_Info*  cid  = &face->cid;
    FT_Byte*   p;
    FT_UInt    entry_len = cid->fd_bytes + cid->gd_bytes;
    FT_UInt    fd_select;
    FT_ULong   off1, glyph_len;
    FT_Stream  stream = face->root.stream;
    FT_Error   error  = 0;


    /* read the CID font dict index and charstring offset from the CIDMap */
    if ( FILE_Seek( cid->data_offset + cid->cidmap_offset +
                    glyph_index * entry_len )               ||
         ACCESS_Frame( 2 * entry_len )                      )
      goto Exit;

    p = (FT_Byte*)stream->cursor;
    fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
    off1      = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
    p        += cid->fd_bytes;
    glyph_len = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1;

    FORGET_Frame();

    /* now, if the glyph is not empty, set up the subrs array, and parse */
    /* the charstrings                                                   */
    if ( glyph_len > 0 )
    {
      CID_FontDict*  dict;
      CID_Subrs*     cid_subrs = face->subrs + fd_select;
      FT_Byte*       charstring;
      FT_Memory      memory = face->root.memory;


      /* setup subrs */
      decoder->num_subrs = cid_subrs->num_subrs;
      decoder->subrs     = cid_subrs->code;
      decoder->subrs_len = 0;

      /* setup font matrix */
      dict                 = cid->font_dicts + fd_select;

      decoder->font_matrix = dict->font_matrix;
      decoder->font_offset = dict->font_offset;
      decoder->lenIV       = dict->private_dict.lenIV;

      /* the charstrings are encoded (stupid!)  */
      /* load the charstrings, then execute it  */

      if ( ALLOC( charstring, glyph_len ) )
        goto Exit;

      if ( !FILE_Read_At( cid->data_offset + off1, charstring, glyph_len ) )
      {
        FT_Int cs_offset;


        /* Adjustment for seed bytes. */
        cs_offset = ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );

        /* Decrypt only if lenIV >= 0. */
        if ( decoder->lenIV >= 0 )
          cid_decrypt( charstring, glyph_len, 4330 );

        error = decoder->funcs.parse_charstrings( decoder,
                                                  charstring + cs_offset,
                                                  glyph_len  - cs_offset  );
      }

      FREE( charstring );
    }

  Exit:
    return error;
  }
Ejemplo n.º 16
0
static FT_Error  Load_LigCaretList( HB_LigCaretList*  lcl,
				    FT_Stream          stream )
{
  FT_Memory memory = stream->memory;
  FT_Error  error;

  FT_UShort      m, n, count;
  FT_ULong       cur_offset, new_offset, base_offset;

  HB_LigGlyph*  lg;


  base_offset = FILE_Pos();

  if ( ACCESS_Frame( 2L ) )
    return error;

  new_offset = GET_UShort() + base_offset;

  FORGET_Frame();

  cur_offset = FILE_Pos();
  if ( FILE_Seek( new_offset ) ||
       ( error = _HB_OPEN_Load_Coverage( &lcl->Coverage, stream ) ) != FT_Err_Ok )
    return error;
  (void)FILE_Seek( cur_offset );

  if ( ACCESS_Frame( 2L ) )
    goto Fail2;

  count = lcl->LigGlyphCount = GET_UShort();

  FORGET_Frame();

  lcl->LigGlyph = NULL;

  if ( ALLOC_ARRAY( lcl->LigGlyph, count, HB_LigGlyph ) )
    goto Fail2;

  lg = lcl->LigGlyph;

  for ( n = 0; n < count; n++ )
  {
    if ( ACCESS_Frame( 2L ) )
      goto Fail1;

    new_offset = GET_UShort() + base_offset;

    FORGET_Frame();

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = Load_LigGlyph( &lg[n], stream ) ) != FT_Err_Ok )
      goto Fail1;
    (void)FILE_Seek( cur_offset );
  }

  lcl->loaded = TRUE;

  return FT_Err_Ok;

Fail1:
  for ( m = 0; m < n; m++ )
    Free_LigGlyph( &lg[m], memory );

  FREE( lg );

Fail2:
  _HB_OPEN_Free_Coverage( &lcl->Coverage, memory );
  return error;
}
Ejemplo n.º 17
0
static HB_Error  Load_CaretValue( HB_CaretValue*  cv,
				  HB_Stream        stream )
{
  HB_Error  error;

  HB_UInt cur_offset, new_offset, base_offset;


  base_offset = FILE_Pos();

  if ( ACCESS_Frame( 2L ) )
    return error;

  cv->CaretValueFormat = GET_UShort();

  FORGET_Frame();

  switch ( cv->CaretValueFormat )
  {
  case 1:
    if ( ACCESS_Frame( 2L ) )
      return error;

    cv->cvf.cvf1.Coordinate = GET_Short();

    FORGET_Frame();

    break;

  case 2:
    if ( ACCESS_Frame( 2L ) )
      return error;

    cv->cvf.cvf2.CaretValuePoint = GET_UShort();

    FORGET_Frame();

    break;

  case 3:
    if ( ACCESS_Frame( 4L ) )
      return error;

    cv->cvf.cvf3.Coordinate = GET_Short();

    new_offset = GET_UShort() + base_offset;

    FORGET_Frame();

    cur_offset = FILE_Pos();
    if ( FILE_Seek( new_offset ) ||
	 ( error = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device,
				stream ) ) != HB_Err_Ok )
      return error;
    (void)FILE_Seek( cur_offset );

    break;

  case 4:
    if ( ACCESS_Frame( 2L ) )
      return error;

#ifdef HB_SUPPORT_MULTIPLE_MASTER
    cv->cvf.cvf4.IdCaretValue = GET_UShort();
#else
    (void) GET_UShort();
#endif

    FORGET_Frame();
    break;

  default:
    return ERR(HB_Err_Invalid_SubTable_Format);
  }

  return HB_Err_Ok;
}