Exemplo n.º 1
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;
}
Exemplo n.º 2
0
//translate
intercodes translate_Exp(struct Node *node, operand place) {
	struct Node *child = node->child;
	assert(child != NULL);
	intercodes code1 = NULL;
	intercodes code2 = NULL;
	intercodes code3 = NULL;
	intercodes code4 = NULL;
	intercodes code5 = NULL;
	//INT
	if (strcmp(child->type,"INT") == 0) {
		operand c1 = new_constant(atoi(child->text));
		code1 = gen_assign(ASSIGN_K,place,c1);
		return code1;
	}
	//ID
	if (strcmp(child->type,"ID") == 0 && child->sibling == NULL) {
		int id = getVarID(child);
		operand v1 = new_var(id);
		code1 = gen_assign(ASSIGN_K,place,v1);
		return code1;
	}
	//Exp1 ASSINGOP Exp2
	if (strcmp(child->type,"Exp") == 0 && strcmp(child->sibling->type,"ASSIGNOP") == 0) {
		//Exp1 is ID (ID = Exp2)
//		printf("%s\n",child->child->type);
		if (strcmp(child->child->type,"ID") == 0) {
			operand t1 =  new_tmp();
			int id = getVarID(child->child);
			operand v1 = new_var(id);
			code1 = translate_Exp(child->sibling->sibling,t1);
			code2 = gen_assign(ASSIGN_K,v1,t1);
		//	code1 = link(code1,code2);
			if (place != NULL) {
				code3 = gen_assign(ASSIGN_K,place,v1);
				code1 = link(code1,code3);
			}
			return code1;
		}
		//Exp[Exp] = Exp2
	}
	//Exp1 PLUS/MINUS/STAR/DIV Exp2
	if (strcmp(child->type,"Exp") == 0 &&
		(strcmp(child->sibling->type,"PLUS") == 0 
		|| strcmp(child->sibling->type,"MINUS") == 0
		|| strcmp(child->sibling->type,"STAR") == 0
		|| strcmp(child->sibling->type,"DIV") == 0)) {
		operand t1 = new_tmp();
		operand t2 = new_tmp();
		code1 = translate_Exp(child,t1);
		code2 = translate_Exp(child->sibling->sibling,t2);
		//printf("%d %d\n", t1->u.tmp_no, t2 -> u.tmp_no);
		if (strcmp(child->sibling->type,"PLUS") == 0) {
			code3 = gen_binop(ADD_K,place,t1,t2);
		}
		else if (strcmp(child->sibling->type,"MINUS") == 0)
			code3 = gen_binop(SUB_K,place,t1,t2);
		else if (strcmp(child->sibling->type,"STAR") == 0)
			code3 = gen_binop(MUL_K,place,t1,t2);
		else if (strcmp(child->sibling->type,"DIV") == 0)
			code3 = gen_binop(DIV_K,place,t1,t2);
		//code1 = link(code1,code2);
		//code1 = link(code1,code3);
		return code1;
	}
	//MINUS Exp1
	if (strcmp(child->type,"MINUS") == 0)  {
		operand t1 = new_tmp();
		code1 = translate_Exp(child,t1);
		operand c1 = new_constant(0);
		code2 = gen_binop(SUB_K,place,c1,t1);
		code1 = link(code1,code2);
		return code1;
	}
	//Exp1 RELOP Exp2
	//NOT Exp1
	//Exp1 AND Exp2
	//Exp1 OR Exp2
	if (strcmp(child->type,"NOT") == 0 
	|| strcmp(child->sibling->type,"RELOP") == 0
	|| strcmp(child->sibling->type,"AND") == 0
	|| strcmp(child->sibling->type,"OR") == 0) {
		operand label1 = new_label();
		operand label2 = new_label();
		operand c1 = new_constant(0);
		operand c2 = new_constant(1);
		code1 = gen_assign(ASSIGN_K,place,c1);
		code2 = translate_Cond(node,label1,label2);
		code3 = gen_one(LABEL_K,label1);
		code4 = gen_assign(ASSIGN_K,place,c2);
		code5 = gen_one(LABEL_K,label2);
		code1 = link(code1,code2);
		code1 = link(code1,code3);
		code1 = link(code1,code4);
		code1 = link(code1,code5);
		return code1;
	}
	//ID LP RP
	if (strcmp(child->sibling->sibling->type,"LP") == 0 && strcmp(child->sibling->sibling->type,"RP") == 0) {
		char *func_name = child->text;
		if (strcmp(func_name,"read") == 0) {
			if (place == NULL) {
				operand t1 = new_tmp();
				code1 = gen_one(READ_K,t1);
			}
			else 
				code1 = gen_one(READ_K,place);
			return code1;
		}
		struct funMes *func_node = getFunMes(child);
		assert(func_node != NULL);
		operand f1 = new_function(func_name);
		if (place != NULL && place->kind != ADDRESS) 
			code1 = gen_assign(CALL_K,place,f1);
		else if (place != NULL && place->kind == ADDRESS) {
			operand t2 = new_tmp();
			code1 = gen_assign(CALL_K,t2,f1);
			code2 = gen_assign(ASSIGN_K,place,t2);
			code1 = link(code1,code2);
		}
		else {
			operand t2 = new_tmp();
			code1 = gen_assign(CALL_K,t2,f1);
		}
		return code1;
	}
	//ID LP Args RP
	if (strcmp(child->sibling->type,"LP") == 0 && strcmp(child->sibling->sibling->type,"Args") == 0) {
		char *func_name = child->text;
		operand *arg_list = (operand *)malloc(sizeof(operand) * 10);
		int arg_num = 0;
		code1 = translate_Args(child->sibling->sibling,arg_list,&arg_num);
		if (strcmp(func_name,"write") == 0) {
			assert(arg_num == 1);
			operand t1;
			if (arg_list[0]->kind == ADDRESS) {
				t1 = new_tmp();
				code2 = gen_assign(ASSIGN_K,t1,arg_list[0]);
				code1 = link(code1,code2);
			}
			else 
				t1 = arg_list[0];
			code3 = gen_one(WRITE_K,t1);
			code1 = link(code1,code3);
			return code1;
		}
		int i;
		for (i = 0;i < arg_num;i++) {
			code2 = gen_one(ARG_K,arg_list[i]);
			code1 = link(code1,code2);
		}
		operand f1 = new_function(func_name);
		if (place != NULL && place->kind != ADDRESS) 
			code3 = gen_assign(CALL_K,place,f1);
		else if (place != NULL && place->kind == ADDRESS) {
			operand t2 = new_tmp();
			code1 = gen_assign(CALL_K,t2,f1);
			code2 = gen_assign(ASSIGN_K,place,t2);
			code1 = link(code1,code2);
		}
		else {
			operand t2 = new_tmp();
			code3 = gen_assign(CALL_K,t2,f1);
		}
		code1 = link(code1,code3);
		return code1;
	}
	//LP Exp RP
	if (strcmp(child->type,"LP") == 0) {
		return translate_Exp(child->sibling,place);
	}
	//Exp1 LB Exp2 RB
	if (strcmp(child->type,"LB") == 0) {
		return translate_array(node,place,NULL,NULL);
	}
	//Exp DOT ID
	return NULL;

}
Exemplo n.º 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;
}