Пример #1
0
BASE_FUNC(FT_Error) FT_Read_Fields(FT_Stream stream,
                                   const FT_Frame_Field   *fields,
                                   void                  *structure)
{
    FT_Error error;
    FT_Bool frame_accessed = 0;


    if(!fields || !stream)
    {
        return FT_Err_Invalid_Argument;
    }

    error = FT_Err_Ok;

    do
    {
        FT_ULong value;
        FT_Int sign_shift;
        FT_Byte  *p;


        switch(fields->value)
        {
        case ft_frame_start: /* access a new frame */
            error = FT_Access_Frame(stream, fields->offset);

            if(error)
            {
                goto Exit;
            }

            frame_accessed = 1;
            fields++;
            continue; /* loop! */

        case ft_frame_bytes: /* read a byte sequence */
        case ft_frame_skip: /* skip some bytes      */
        {
            FT_Int len = fields->size;


            if(stream->cursor + len > stream->limit)
            {
                error = FT_Err_Invalid_Stream_Operation;
                goto Exit;
            }

            if(fields->value == ft_frame_bytes)
            {
                p = (FT_Byte *)structure + fields->offset;
                MEM_Copy(p, stream->cursor, len);
            }

            stream->cursor += len;
            fields++;
            continue;
        }

        case ft_frame_byte:
        case ft_frame_schar: /* read a single byte */
            value = GET_Byte();
            sign_shift = 24;
            break;

        case ft_frame_short_be:
        case ft_frame_ushort_be: /* read a 2-byte big-endian short */
            value = GET_UShort();
            sign_shift = 16;
            break;

        case ft_frame_short_le:
        case ft_frame_ushort_le: /* read a 2-byte little-endian short */
        {
            FT_Byte  *p;


            value = 0;
            p     = stream->cursor;

            if(p + 1 < stream->limit)
            {
                value = (FT_UShort)p[0] | ((FT_UShort)p[1] << 8);
                stream->cursor += 2;
            }

            sign_shift = 16;
            break;
        }

        case ft_frame_long_be:
        case ft_frame_ulong_be: /* read a 4-byte big-endian long */
            value = GET_ULong();
            sign_shift = 0;
            break;

        case ft_frame_long_le:
        case ft_frame_ulong_le: /* read a 4-byte little-endian long */
        {
            FT_Byte  *p;


            value = 0;
            p     = stream->cursor;

            if(p + 3 < stream->limit)
            {
                value = (FT_ULong)p[0]         |
                        ((FT_ULong)p[1] << 8) |
                        ((FT_ULong)p[2] << 16) |
                        ((FT_ULong)p[3] << 24);
                stream->cursor += 4;
            }

            sign_shift = 0;
            break;
        }

        case ft_frame_off3_be:
        case ft_frame_uoff3_be: /* read a 3-byte big-endian long */
            value = GET_UOffset();
            sign_shift = 8;
            break;

        case ft_frame_off3_le:
        case ft_frame_uoff3_le: /* read a 3-byte little-endian long */
        {
            FT_Byte  *p;


            value = 0;
            p     = stream->cursor;

            if(p + 2 < stream->limit)
            {
                value = (FT_ULong)p[0]         |
                        ((FT_ULong)p[1] << 8) |
                        ((FT_ULong)p[2] << 16);
                stream->cursor += 3;
            }

            sign_shift = 8;
            break;
        }

        default:
            /* otherwise, exit the loop */
            goto Exit;
        }

        /* now, compute the signed value is necessary */
        if(fields->value & FT_FRAME_OP_SIGNED)
        {
            value = (FT_ULong)((FT_Int32)(value << sign_shift) >> sign_shift);
        }

        /* finally, store the value in the object */

        p = (FT_Byte *)structure + fields->offset;

        switch(fields->size)
        {
        case 1:
            *(FT_Byte *)p = (FT_Byte)value;
            break;

        case 2:
            *(FT_UShort *)p = (FT_UShort)value;
            break;

        case 4:
            *(FT_UInt32 *)p = (FT_UInt32)value;
            break;

        default: /* for 64-bit systems */
            *(FT_ULong *)p = (FT_ULong)value;
        }

        /* go to next field */
        fields++;
    }
Пример #2
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;
  }
Пример #3
0
static TT_Error  Load_Simple_Glyph( PExecution_Context  exec,
                                    TT_Stream           input,
                                    Short               n_contours,
                                    Short               left_contours,
                                    UShort              left_points,
                                    UShort              load_flags,
                                    PSubglyph_Record    subg )
{
    DEFINE_LOAD_LOCALS( input );

    PGlyph_Zone  pts;
    Short        k;
    UShort       j;
    UShort       n_points, n_ins;
    PFace        face;
    Byte*        flag;
    TT_Vector*   vec;
    TT_F26Dot6   x, y;


    face = exec->face;

    /* simple check */
    if ( n_contours > left_contours )
    {
        PTRACE0(( "ERROR: Glyph index %ld has %d contours > left %d\n",
                  subg->index, n_contours, left_contours ));
        return TT_Err_Too_Many_Contours;
    }


    /* preparing the execution context */
    mount_zone( &subg->zone, &exec->pts );

    /* reading the contours endpoints */
    if ( ACCESS_Frame( (n_contours + 1) * 2L ) )
        return error;

    PTRACE4(( " Contour endpoints:" ));

    for ( k = 0; k < n_contours; k++ )
    {
        exec->pts.contours[k] = GET_UShort();
        PTRACE4(( " %d", exec->pts.contours[k] ));
    }
    PTRACE4(( "\n" ));

    if ( n_contours > 0 )
        n_points = exec->pts.contours[n_contours - 1] + 1;
    else
        n_points = 0;

    n_ins = GET_UShort();

    FORGET_Frame();

    if ( n_points > left_points )
    {
        PTRACE0(( "ERROR: Too many points in glyph %ld\n", subg->index ));
        return TT_Err_Too_Many_Points;
    }

    /* loading instructions */

    PTRACE4(( " Instructions size: %d\n", n_ins ));

    if ( n_ins > face->maxProfile.maxSizeOfInstructions )
    {
        PTRACE0(( "ERROR: Too many instructions!\n" ));
        return TT_Err_Too_Many_Ins;
    }

    if ( FILE_Read( exec->glyphIns, n_ins ) )
        return error;

    if ( (error = Set_CodeRange( exec,
                                 TT_CodeRange_Glyph,
                                 exec->glyphIns,
                                 n_ins )) != TT_Err_Ok )
        return error;


    /* read the flags */

    if ( CHECK_AND_ACCESS_Frame( n_points * 5L ) )
        return error;

    j    = 0;
    flag = exec->pts.touch;

    while ( j < n_points )
    {
        Byte  c, cnt;

        flag[j] = c = GET_Byte();
        j++;

        if ( c & 8 )
        {
            cnt = GET_Byte();
            while( cnt > 0 )
            {
                flag[j++] = c;
                cnt--;
            }
        }
    }

    /* read the X */

    x    = 0;
    vec  = exec->pts.org;

    for ( j = 0; j < n_points; j++ )
    {
        if ( flag[j] & 2 )
        {
            if ( flag[j] & 16 )
                x += GET_Byte();
            else
                x -= GET_Byte();
        }
        else
        {
            if ( (flag[j] & 16) == 0 )
                x += GET_Short();
        }

        vec[j].x = x;
    }


    /* read the Y */

    y    = 0;

    for ( j = 0; j < n_points; j++ )
    {
        if ( flag[j] & 4 )
        {
            if ( flag[j] & 32 )
                y += GET_Byte();
            else
                y -= GET_Byte();
        }
        else
        {
            if ( (flag[j] & 32) == 0 )
                y += GET_Short();
        }

        vec[j].y = y;
    }

    FORGET_Frame();
    /* Now add the two shadow points at n and n + 1.    */
    /* We need the left side bearing and advance width. */

    /* pp1 = xMin - lsb */
    vec[n_points].x = subg->metrics.bbox.xMin - subg->metrics.horiBearingX;
    vec[n_points].y = 0;

    /* pp2 = pp1 + aw */
    vec[n_points+1].x = vec[n_points].x + subg->metrics.horiAdvance;
    vec[n_points+1].y = 0;

    /* clear the touch flags */

    for ( j = 0; j < n_points; j++ )
        exec->pts.touch[j] &= TT_Flag_On_Curve;

    exec->pts.touch[n_points    ] = 0;
    exec->pts.touch[n_points + 1] = 0;

    /* Note that we return two more points that are not */
    /* part of the glyph outline.                       */

    n_points += 2;

    /* now eventually scale and hint the glyph */

    pts = &exec->pts;
    pts->n_points   = n_points;
    pts->n_contours = n_contours;

    if ( (load_flags & TTLOAD_SCALE_GLYPH) == 0 )
    {
        /* no scaling, just copy the orig arrays into the cur ones */
        org_to_cur( n_points, pts );
    }
    else
    {
        /* first scale the glyph points */

        for ( j = 0; j < n_points; j++ )
        {
            pts->org[j].x = Scale_X( &exec->metrics, pts->org[j].x );
            pts->org[j].y = Scale_Y( &exec->metrics, pts->org[j].y );
        }

        /* if hinting, round pp1, and shift the glyph accordingly */
        if ( subg->is_hinted )
        {
            x = pts->org[n_points - 2].x;
            x = ((x+32) & -64) - x;
            translate_array( n_points, pts->org, x, 0 );

            org_to_cur( n_points, pts );

            pts->cur[n_points - 1].x = (pts->cur[n_points - 1].x + 32) & -64;

            /* now consider hinting */
            if ( n_ins > 0 )
            {
                exec->is_composite     = FALSE;
                exec->pedantic_hinting = load_flags & TTLOAD_PEDANTIC;

                error = Context_Run( exec, FALSE );
                if (error && exec->pedantic_hinting)
                    return error;
            }
        }
        else
            org_to_cur( n_points, pts );
    }

    /* save glyph phantom points */
    if (!subg->preserve_pps)
    {
        subg->pp1 = pts->cur[n_points - 2];
        subg->pp2 = pts->cur[n_points - 1];
    }

    return TT_Err_Ok;
}