Ejemplo n.º 1
0
static void CVMergeSPLS(CharView *cv,SplineSet *ss, SplinePoint *base,SplinePoint *sp) {
    int order2 = cv->b.layerheads[cv->b.drawmode]->order2;

    cv->joinvalid = true;
    cv->joinpos = *sp; cv->joinpos.selected = false;
    if ( sp->prev!=NULL )
	SplineSetReverse(cv->p.spl);
    if ( sp->prev!=NULL )
	IError("Base point not at start of splineset in CVMouseDownPoint");
    /* remove the old spl entry from the chain */
    if ( cv->p.spl==cv->b.layerheads[cv->b.drawmode]->splines )
	cv->b.layerheads[cv->b.drawmode]->splines = cv->p.spl->next;
    else { SplineSet *temp;
	for ( temp = cv->b.layerheads[cv->b.drawmode]->splines; temp->next!=cv->p.spl; temp = temp->next );
	temp->next = cv->p.spl->next;
    }
    if ( order2 && (!RealNear(base->nextcp.x,sp->prevcp.x) ||
	    !RealNear(base->nextcp.y,sp->prevcp.y)) ) {
	base->nonextcp = sp->noprevcp = true;
	base->nextcp = base->me;
	sp->prevcp = sp->me;
    }
    SplineMake(base,sp,order2);
    SplineCharDefaultNextCP(base);
    SplineCharDefaultPrevCP(sp);
    if ( sp->pointtype==pt_tangent ) {
	SplineCharTangentNextCP(sp);
	if ( sp->next ) SplineRefigure(sp->next );
    }
    ss->last = cv->p.spl->last;
    if ( ss->spiros && cv->p.spl->spiros ) {
	if ( ss->spiro_cnt+cv->p.spl->spiro_cnt > ss->spiro_max )
	    ss->spiros = realloc(ss->spiros,
		    (ss->spiro_max = ss->spiro_cnt+cv->p.spl->spiro_cnt)*sizeof(spiro_cp));
	memcpy(ss->spiros+ss->spiro_cnt-1,
		cv->p.spl->spiros+1, (cv->p.spl->spiro_cnt-1)*sizeof(spiro_cp));
	ss->spiro_cnt += cv->p.spl->spiro_cnt-2;
    } else
	SplineSetSpirosClear(ss);
    cv->p.spl->last = cv->p.spl->first = NULL;
    cv->p.spl->spiros = 0;
    SplinePointListFree(cv->p.spl);
    cv->p.spl = NULL;
}
Ejemplo n.º 2
0
/* Finishes an old FontAnvil bezier context, and returns the contour which was created */
struct splinepointlist *bezctx_ff_close(bezctx * z) {
   bezctx_ff *bc=(bezctx_ff *) z;
   SplineSet *ss=bc->ss;

   if (!bc->is_open && ss != NULL) {
      if (ss->first != ss->last &&
	  RealNear(ss->first->me.x, ss->last->me.x) &&
	  RealNear(ss->first->me.y, ss->last->me.y)) {
	 ss->first->prevcp=ss->last->prevcp;
	 ss->first->noprevcp=ss->last->noprevcp;
	 ss->first->prev=ss->last->prev;
	 ss->first->prev->to=ss->first;
	 SplinePointFree(ss->last);
	 ss->last=ss->first;
      } else {
	 if (SplineMake3(ss->last, ss->first) != NULL)
	    ss->last=ss->first;
      }
   }
   free(bc);
   return (ss);
}
Ejemplo n.º 3
0
static int AssignPtNumbers(MMSet *mm,int gid) {
    /* None of the instances has fixed point numbers. Make them match */
    int cnt=0;
    SplineSet **ss;
    SplinePoint **sp;
    int i;
    int allavg, alllines, stillmore, ret=true;

    ss = malloc((mm->instance_count+1)*sizeof(SplineSet *));
    sp = malloc((mm->instance_count+1)*sizeof(SplinePoint *));
    for ( i=0; i<mm->instance_count; ++i )
	ss[i] = mm->instances[i]->glyphs[gid]->layers[ly_fore].splines;
    ss[i] = mm->normal->glyphs[gid]->layers[ly_fore].splines;

    if ( ss[0]==NULL ) {
	stillmore = false;
	for ( i=0; i<=mm->instance_count; ++i )
	    if ( ss[i]!=NULL ) stillmore = true;
	if ( stillmore )
return( false );
return( true );
    } else {
	stillmore = true;
	for ( i=0; i<=mm->instance_count; ++i )
	    if ( ss[i]==NULL ) stillmore = false;
	if ( !stillmore )
return( false );
    }
	    
    for (;;) {
	for ( i=0; i<=mm->instance_count; ++i )
	    sp[i] = ss[i]->first;
	for (;;) {
	    allavg = alllines = true;
	    for ( i=0; i<=mm->instance_count; ++i ) {
		if ( !RealNear(sp[i]->me.x,(sp[i]->nextcp.x+sp[i]->prevcp.x)/2) ||
			!RealNear(sp[i]->me.y,(sp[i]->nextcp.y+sp[i]->prevcp.y)/2) )
		    allavg = false;
		if ( !sp[i]->nonextcp )
		    alllines = false;
	    }
	    if ( sp[0] == ss[0]->first )
		allavg = false;
	    for ( i=0; i<=mm->instance_count; ++i ) {
		if ( allavg )
		    sp[i]->ttfindex = 0xffff;
		else
		    sp[i]->ttfindex = cnt;
	    }
	    if ( !allavg )
		++cnt;
	    for ( i=0; i<=mm->instance_count; ++i ) {
		if ( alllines )
		    sp[i]->nextcpindex = 0xffff;
		else
		    sp[i]->nextcpindex = cnt;
	    }
	    if ( !alllines )
		++cnt;

	    if ( sp[0]->next==NULL ) {
		stillmore = false;
		for ( i=1; i<=mm->instance_count; ++i )
		    if ( sp[i]->next!=NULL )
			stillmore = true;
		if ( stillmore )
		    ret = false;
	break;
	    }
	    for ( i=1; i<=mm->instance_count; ++i )
		if ( sp[i]->next==NULL )
		    stillmore = false;
	    if ( !stillmore ) {
		ret = false;
	break;
	    }
	    sp[0] = sp[0]->next->to;
	    for ( i=1; i<=mm->instance_count; ++i )
		sp[i] = sp[i]->next->to;
	    if ( sp[0]==ss[0]->first ) {
		stillmore = false;
		for ( i=1; i<=mm->instance_count; ++i )
		    if ( sp[i]!=ss[i]->first )
			stillmore = true;
		if ( stillmore )
		    ret = false;
	break;
	    }
	    for ( i=1; i<=mm->instance_count; ++i ) {
		if ( sp[i]==ss[i]->first )
		    stillmore = false;
	    }
	    if ( !stillmore ) {
		ret = false;
	break;
	    }
	}
	if ( !ret )
    break;
	stillmore = true;
	for ( i=0; i<=mm->instance_count; ++i )
	    ss[i] = ss[i]->next;
	if ( ss[0]==NULL ) {
	    stillmore=false;
	    for ( i=1; i<=mm->instance_count; ++i )
		if ( ss[i]!=NULL )
		    stillmore = true;
	    if ( stillmore )
		ret = true;
    break;
	}
	for ( i=1; i<=mm->instance_count; ++i )
	    if ( ss[i]==NULL )
		stillmore = false;
	if ( !stillmore ) {
	    ret = true;
    break;
	}
    }
return( ret );
}
Ejemplo n.º 4
0
static int MatchPoints(SplineFont *sffixed, SplineFont *sfother, int gid) {
    SplineChar *fixed, *other;
    SplineSet *ss1, *ss2;
    SplinePoint *sp1, *sp2;

    fixed = sffixed->glyphs[gid]; other = sfother->glyphs[gid];

    if ( PtNumbersAreSet(other)) {
	/* Point numbers must match exactly, both are fixed */
	for ( ss1=fixed->layers[ly_fore].splines,
		  ss2=other->layers[ly_fore].splines;
		ss1!=NULL && ss2!=NULL ;
		ss1 = ss1->next, ss2=ss2->next ) {
	    for ( sp1=ss1->first, sp2=ss2->first; ; ) {
		if ( sp1->ttfindex!=sp2->ttfindex ||
			sp1->nextcpindex!=sp2->nextcpindex )
return( false );
		if ( sp1->next==NULL || sp2->next==NULL ) {
		    if ( sp1->next!=NULL || sp2->next!=NULL )
return( false );
	    break;
		}
		sp1 = sp1->next->to; sp2=sp2->next->to;
		if ( sp1==ss1->first || sp2==ss2->first ) {
		    if ( sp1!=ss1->first || sp2!=ss2->first )
return( false );
	    break;
		}
	    }
	}
return( ss1==NULL && ss2==NULL );
    } else {
	for ( ss1=fixed->layers[ly_fore].splines,
		  ss2=other->layers[ly_fore].splines;
		ss1!=NULL && ss2!=NULL ;
		ss1 = ss1->next, ss2=ss2->next ) {
	    for ( sp1=ss1->first, sp2=ss2->first; ; ) {
		if ( sp1->ttfindex!=0xffff )
		    sp2->ttfindex = sp1->ttfindex;
		else if ( !RealNear(sp2->me.x,(sp2->nextcp.x+sp2->prevcp.x)/2) ||
			!RealNear(sp2->me.y,(sp2->nextcp.y+sp2->prevcp.y)/2) )
return( false );
		else
		    sp2->ttfindex = 0xffff;
		if ( sp1->nextcpindex!=0xffff )
		    sp2->nextcpindex = sp1->nextcpindex;
		else if ( !sp2->nonextcp )
return( false );
		else
		    sp2->nextcpindex = 0xffff;
		if ( sp1->next==NULL || sp2->next==NULL ) {
		    if ( sp1->next!=NULL || sp2->next!=NULL )
return( false );
	    break;
		}
		sp1 = sp1->next->to; sp2=sp2->next->to;
		if ( sp1==ss1->first || sp2==ss2->first ) {
		    if ( sp1!=ss1->first || sp2!=ss2->first )
return( false );
	    break;
		}
	    }
	}
return( ss1==NULL && ss2==NULL );
    }
}
Ejemplo n.º 5
0
static void AddSpline(EdgeList *es, Spline *sp ) {
    real t1=2, t2=2, t;
    real b2_fourac;
    real fm, tm;
    Spline1D *msp = &sp->splines[es->major], *osp = &sp->splines[es->other];

    /* Find the points of extrema on the curve discribing y behavior */
    if ( !RealNear(msp->a,0) ) {
	/* cubic, possibly 2 extrema (possibly none) */
	b2_fourac = 4*msp->b*msp->b - 12*msp->a*msp->c;
	if ( b2_fourac>=0 ) {
	    b2_fourac = sqrt(b2_fourac);
	    t1 = CheckExtremaForSingleBitErrors(msp,(-2*msp->b - b2_fourac) / (6*msp->a));
	    t2 = CheckExtremaForSingleBitErrors(msp,(-2*msp->b + b2_fourac) / (6*msp->a));
	    if ( t1>t2 ) { real temp = t1; t1 = t2; t2 = temp; }
	    else if ( t1==t2 ) t2 = 2.0;

	    /* check for curves which have such a small slope they might */
	    /*  as well be horizontal */
	    fm = es->major==1?sp->from->me.y:sp->from->me.x;
	    tm = es->major==1?sp->to->me.y:sp->to->me.x;
	    if ( fm==tm ) {
		real m1, m2, d1, d2;
		m1 = m2 = fm;
		if ( t1>0 && t1<1 )
		    m1 = ((msp->a*t1+msp->b)*t1+msp->c)*t1 + msp->d;
		if ( t2>0 && t2<1 )
		    m2 = ((msp->a*t2+msp->b)*t2+msp->c)*t2 + msp->d;
		d1 = (m1-fm)*es->scale;
		d2 = (m2-fm)*es->scale;
		if ( d1>-.5 && d1<.5 && d2>-.5 && d2<.5 ) {
		    sp->ishorvert = true;
		    if ( es->genmajoredges )
			AddMajorEdge(es,sp);
return;		/* Pretend it's horizontal, ignore it */
		}
	    }
	}
    } else if ( !RealNear(msp->b,0) ) {
	/* Quadratic, at most one extremum */
	t1 = -msp->c/(2.0*msp->b);
    } else if ( !RealNear(msp->c,0) ) {
	/* linear, no points of extrema */
    } else {
	sp->ishorvert = true;
	if ( es->genmajoredges )
	    AddMajorEdge(es,sp);
return;		/* Horizontal line, ignore it */
    }

    if ( RealNear(t1,0)) t1=0;
    if ( RealNear(t1,1)) t1=1;
    if ( RealNear(t2,0)) t2=0;
    if ( RealNear(t2,1)) t2=1;
    if ( RealNear(t1,t2)) t2=2;
    t=0;
    if ( t1>0 && t1<1 ) {
	AddEdge(es,sp,0,t1);
	t = t1;
    }
    if ( t2>0 && t2<1 ) {
	AddEdge(es,sp,t,t2);
	t = t2;
    }
    AddEdge(es,sp,t,1.0);
    if ( es->interesting ) {
	/* Also store up points of extrema in X as interesting (we got the endpoints, just internals now)*/
	extended ot1, ot2;
	int mpos;
	SplineFindExtrema(osp,&ot1,&ot2);
	if ( ot1>0 && ot1<1 ) {
	    mpos = (int) ceil( ( ((msp->a*ot1+msp->b)*ot1+msp->c)*ot1+msp->d )*es->scale-es->mmin );
	    es->interesting[mpos] = 1;
	}
	if ( ot2>0 && ot2<1 ) {
	    mpos = (int) ceil( ( ((msp->a*ot2+msp->b)*ot2+msp->c)*ot2+msp->d )*es->scale-es->mmin );
	    es->interesting[mpos] = 1;
	}
    }
}
Ejemplo n.º 6
0
static void AddEdge(EdgeList *es, Spline *sp, real tmin, real tmax ) {
    Edge *e, *pr;
    real m1, m2;
    int mpos;
    Hints *hint;
    Spline1D *msp = &sp->splines[es->major], *osp = &sp->splines[es->other];

    e = gcalloc(1,sizeof(Edge));
    e->spline = sp;

    m1 = ( ((msp->a*tmin+msp->b)*tmin+msp->c)*tmin + msp->d ) * es->scale;
    m2 = ( ((msp->a*tmax+msp->b)*tmax+msp->c)*tmax + msp->d ) * es->scale;
    if ( m1>m2 ) {
	e->mmin = m2;
	e->t_mmin = tmax;
	e->mmax = m1;
	e->t_mmax = tmin;
	e->up = false;
    } else {
	e->mmax = m2;
	e->t_mmax = tmax;
	e->mmin = m1;
	e->t_mmin = tmin;
	e->up = true;
    }
    if ( RealNear(e->mmin,es->mmin)) e->mmin = es->mmin;
    e->o_mmin = ( ((osp->a*e->t_mmin+osp->b)*e->t_mmin+osp->c)*e->t_mmin + osp->d ) * es->scale;
    e->o_mmax = ( ((osp->a*e->t_mmax+osp->b)*e->t_mmax+osp->c)*e->t_mmax + osp->d ) * es->scale;
    e->mmin -= es->mmin; e->mmax -= es->mmin;
    e->t_cur = e->t_mmin;
    e->o_cur = e->o_mmin;
    e->m_cur = e->mmin;
    e->last_opos = e->last_mpos = -2;
    e->tmin = tmin; e->tmax = tmax;

    if ( e->mmin<0 || e->mmin>=e->mmax ) {
	/*IError("Probably not serious, but we've got a zero length spline in AddEdge in %s",es->sc==NULL?<nameless>:es->sc->name);*/
	free(e);
return;
    }

    if ( es->sc!=NULL ) for ( hint=es->hhints; hint!=NULL; hint=hint->next ) {
	if ( hint->adjustb ) {
	    if ( e->m_cur>hint->b1 && e->m_cur<hint->b2 ) {
		e->m_cur = e->mmin = hint->ab;
		e->min_adjusted = true;
	    } else if ( e->mmax>hint->b1 && e->mmax<hint->b2 ) {
		e->mmax = hint->ab;
		e->max_adjusted = true;
	    }
	} else if ( hint->adjuste ) {
	    if ( e->m_cur>hint->e1 && e->m_cur<hint->e2 ) {
		e->m_cur = e->mmin = hint->ae;
		e->min_adjusted = true;
	    } else if ( e->mmax>hint->e1 && e->mmax<hint->e2 ) {
		e->mmax = hint->ae;
		e->max_adjusted = true;
	    }
	}
    }

    mpos = (int) ceil(e->m_cur);
    if ( mpos>e->mmax || mpos>=es->cnt ) {
	free(e);
return;
    }

    if ( e->m_cur!=ceil(e->m_cur) ) {
	/* bring the new edge up to its first scan line */
	e->t_cur = TOfNextMajor(e,es,ceil(e->m_cur));
	e->o_cur = ( ((osp->a*e->t_cur+osp->b)*e->t_cur+osp->c)*e->t_cur + osp->d ) * es->scale;
    }

    e->before = es->last;
    if ( es->last!=NULL )
	es->last->after = e;
    if ( es->last==NULL )
	es->splinesetfirst = e;
    es->last = e;

    if ( es->edges[mpos]==NULL || e->o_cur<es->edges[mpos]->o_cur ||
	    (e->o_cur==es->edges[mpos]->o_cur && SlopeLess(e,es->edges[mpos],es->other))) {
	e->esnext = es->edges[mpos];
	es->edges[mpos] = e;
    } else {
	for ( pr=es->edges[mpos]; pr->esnext!=NULL && pr->esnext->o_cur<e->o_cur ;
		pr = pr->esnext );
	/* When two splines share a vertex which is a local minimum, then */
	/*  o_cur will be equal for both (to the vertex's o value) and so */
	/*  the above code randomly picked one to go first. That screws up */
	/*  the overlap code, which wants them properly ordered from the */
	/*  start. so look at the end point, nope the end point isn't always */
	/*  meaningful, look at the slope... */
	if ( pr->esnext!=NULL && pr->esnext->o_cur==e->o_cur &&
		SlopeLess(e,pr->esnext,es->other)) {
	    pr = pr->esnext;
	}
	e->esnext = pr->esnext;
	pr->esnext = e;
    }
    if ( es->interesting ) {
	/* Mark the other end of the spline as interesting */
	es->interesting[(int) ceil(e->mmax)]=1;
    }
}
Ejemplo n.º 7
0
static int Trans_OK(GGadget *g, GEvent *e) {
    real transform[6], trans[6], t[6];
    bigreal angle, angle2;
    int i, index, err;
    int alllayers = false, round_2_int = false, dokerns = false, dokp=false;
    int dogrid = false, dowidth = false;
    BasePoint base;
    int origin, bvpos=0;
    BVTFunc bvts[TCnt+1];
    static int warned = false;
    int isapply = GGadgetGetCid(g) == CID_Apply;

    if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) {
	TransData *td = GDrawGetUserData(GGadgetGetWindow(g));

	transform[0] = transform[3] = 1.0;
	transform[1] = transform[2] = transform[4] = transform[5] = 0;
	base.x = base.y = 0;

	origin = GGadgetGetFirstListSelectedItem( GWidgetGetControl(td->gw,CID_Origin));
	if ( GWidgetGetControl(td->gw,CID_AllLayers)!=NULL )
	    alllayers = GGadgetIsChecked(GWidgetGetControl(td->gw,CID_AllLayers));
	if ( GWidgetGetControl(td->gw,CID_DoGrid)!=NULL )
	    dogrid = GGadgetIsChecked(GWidgetGetControl(td->gw,CID_DoGrid));
	if ( GWidgetGetControl(td->gw,CID_DoWidth)!=NULL )
	    dowidth = GGadgetIsChecked(GWidgetGetControl(td->gw,CID_DoWidth));
	else
	    dowidth = true;
	if ( GWidgetGetControl(td->gw,CID_DoSimplePos)!=NULL )
	    dokp = GGadgetIsChecked(GWidgetGetControl(td->gw,CID_DoSimplePos));
	if ( GWidgetGetControl(td->gw,CID_DoKerns)!=NULL )
	    dokerns = GGadgetIsChecked(GWidgetGetControl(td->gw,CID_DoKerns));
	round_2_int = GGadgetIsChecked(GWidgetGetControl(td->gw,CID_Round2Int));
	if ( isapply )
	    alllayers = dogrid = dokp = dokerns = false;
	if ( td->getorigin!=NULL ) {
	    (td->getorigin)(td->userdata,&base,origin );
	    transform[4] = -base.x;
	    transform[5] = -base.y;
	}
	for ( i=0; i<TCnt; ++i ) {
	    index =  GGadgetGetFirstListSelectedItem(
		    GWidgetGetControl(td->gw,CID_Type+i*TBlock_CIDOffset));
	    trans[0] = trans[3] = 1.0;
	    trans[1] = trans[2] = trans[4] = trans[5] = 0;
	    err = 0;
	    switch ( index ) {
	      case 0:		/* Do Nothing */
	      break;
	      case 1:		/* Move */
		trans[4] = GetReal8(td->gw,CID_XMove+i*TBlock_CIDOffset,_("X Movement"),&err);
		trans[5] = GetReal8(td->gw,CID_YMove+i*TBlock_CIDOffset,_("Y Movement"),&err);
		bvts[bvpos].x = trans[4]; bvts[bvpos].y = trans[5]; bvts[bvpos++].func = bvt_transmove;
	      break;
	      case 2:		/* Rotate */
		angle = GetReal8(td->gw,CID_Angle+i*TBlock_CIDOffset,_("Rotation Angle"),&err);
		if ( GGadgetIsChecked( GWidgetGetControl(td->gw,CID_Clockwise+i*TBlock_CIDOffset)) )
		    angle = -angle;
		if ( fmod(angle,90)!=0 )
		    bvts[0].func = bvt_none;		/* Bad trans=> No trans */
		else {
		    angle = fmod(angle,360);
		    if ( angle<0 ) angle+=360;
		    if ( angle==90 ) bvts[bvpos++].func = bvt_rotate90ccw;
		    else if ( angle==180 ) bvts[bvpos++].func = bvt_rotate180;
		    else if ( angle==270 ) bvts[bvpos++].func = bvt_rotate90cw;
		}
		angle *= 3.1415926535897932/180;
		trans[0] = trans[3] = cos(angle);
		trans[2] = -(trans[1] = sin(angle));
	      break;
	      case 3:		/* Scale Uniformly */
		trans[0] = trans[3] = GetReal8(td->gw,CID_Scale+i*TBlock_CIDOffset,_("Scale Factor"),&err)/100.0;
		bvts[0].func = bvt_none;		/* Bad trans=> No trans */
	      break;
	      case 4:		/* Scale */
		trans[0] = GetReal8(td->gw,CID_XScale+i*TBlock_CIDOffset,_("X Scale Factor"),&err)/100.0;
		trans[3] = GetReal8(td->gw,CID_YScale+i*TBlock_CIDOffset,_("Y Scale Factor"),&err)/100.0;
		bvts[0].func = bvt_none;		/* Bad trans=> No trans */
	      break;
	      case 5:		/* Flip */
		if ( GGadgetIsChecked( GWidgetGetControl(td->gw,CID_Horizontal+i*TBlock_CIDOffset)) ) {
		    trans[0] = -1;
		    bvts[bvpos++].func = bvt_fliph;
		} else {
		    trans[3] = -1;
		    bvts[bvpos++].func = bvt_flipv;
		}
	      break;
	      case 6:		/* Skew */
		angle = GetReal8(td->gw,CID_SkewAng+i*TBlock_CIDOffset,_("Skew Angle"),&err);
		if ( GGadgetIsChecked( GWidgetGetControl(td->gw,CID_CounterClockwise+i*TBlock_CIDOffset)) )
		    angle = -angle;
		angle *= 3.1415926535897932/180;
		trans[2] = tan(angle);
		skewselect(&bvts[bvpos],trans[2]); ++bvpos;
	      break;
	      case 7:		/* 3D rotate */
		angle =  GetReal8(td->gw,CID_XAxis+i*TBlock_CIDOffset,_("Rotation about X Axis"),&err) * 3.1415926535897932/180;
		angle2 = GetReal8(td->gw,CID_YAxis+i*TBlock_CIDOffset,_("Rotation about Y Axis"),&err) * 3.1415926535897932/180;
		trans[0] = cos(angle2);
		trans[3] = cos(angle );
		bvts[0].func = bvt_none;		/* Bad trans=> No trans */
	      break;
	      default:
		IError("Unexpected selection in Transform");
		err = 1;
	      break;
	    }
	    if ( err )
return(true);
#if 0
 printf( "(%g,%g,%g,%g,%g,%g)*(%g,%g,%g,%g,%g,%g) = ",
     trans[0], trans[1], trans[2], trans[3], trans[4], trans[5],
     transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]);
#endif
	    t[0] = transform[0]*trans[0] +
			transform[1]*trans[2];
	    t[1] = transform[0]*trans[1] +
			transform[1]*trans[3];
	    t[2] = transform[2]*trans[0] +
			transform[3]*trans[2];
	    t[3] = transform[2]*trans[1] +
			transform[3]*trans[3];
	    t[4] = transform[4]*trans[0] +
			transform[5]*trans[2] +
			trans[4];
	    t[5] = transform[4]*trans[1] +
			transform[5]*trans[3] +
			trans[5];
	    memcpy(transform,t,sizeof(t));
#if 0
 printf( "(%g,%g,%g,%g,%g,%g)\n",
     transform[0], transform[1], transform[2], transform[3], transform[4], transform[5]);
#endif
	}
	bvts[bvpos++].func = bvt_none;		/* Done */
	for ( i=0; i<6; ++i )
	    if ( RealNear(transform[i],0)) transform[i] = 0;
	transform[4] += base.x;
	transform[5] += base.y;

	if (( transform[1]!=0 || transform[2]!=0 ) && !warned ) {
	    ff_post_notice(_("Warning"),_("After rotating or skewing a glyph you should probably apply Element->Add Extrema"));
	    warned = true;
	}
	(td->transfunc)(td->userdata,transform,origin,bvts,
		(alllayers?fvt_alllayers:0)|
		(dogrid?fvt_dogrid:0)|
		 (dowidth?0:fvt_dontmovewidth)|
		 (round_2_int?fvt_round_to_int:0)|
		 (dokp?fvt_scalepstpos:0)|
		 (dokerns?fvt_scalekernclasses:0)|
		 (isapply?fvt_justapply:0));
	td->done = !isapply;
	td->applied = isapply;
    }
return( true );
}
Ejemplo n.º 8
0
static int SPMatchesF(SplinePoint *sp, SearchData *s, SplineSet *path,
	SplinePoint *sc_path_first, int substring ) {
    SplinePoint *sc_sp, *nsc_sp, *p_sp, *np_sp;
    int flip, flipmax;
    bigreal rot, scale;
    int saw_sc_first = false, first_of_path;
    BasePoint p_unit, pend_unit, sc_unit;
    bigreal len, temp;

    s->matched_sp = sp;
    s->matched_rot = 0;
    s->matched_scale = 1.0;
    s->matched_flip = flip_none;
    s->matched_co = 1; s->matched_si=0;

    first_of_path = true;
    p_sp = path->first;
    if ( s->endpoints ) {
	SplinePoint *p_prevsp = p_sp;
	SplinePoint *psc_sp;
	p_sp = p_sp->next->to;
	p_unit.x = p_sp->me.x - p_prevsp->me.x; p_unit.y = p_sp->me.y - p_prevsp->me.y;
	len = sqrt(p_unit.x*p_unit.x + p_unit.y*p_unit.y);
	if ( len==0 )
return( false );
	p_unit.x /= len; p_unit.y /= len;
	if ( sp->prev==NULL )
return( false );
	psc_sp = sp->prev->from;
	if ( (sp->me.x-psc_sp->me.x)*(sp->me.x-psc_sp->me.x) +
		(sp->me.y-psc_sp->me.y)*(sp->me.y-psc_sp->me.y) < len*len )
return( false );
    }
    if ( s->endpoints ) {
	SplinePoint *p_nextsp = path->last;
	SplinePoint *p_end = p_nextsp->prev->from;
	if ( sp->next==NULL )
return( false );
	for ( p_end = p_sp, p_nextsp = p_end->next->to, sc_sp = sp, nsc_sp=sp->next->to ;; ) {
	    if ( p_nextsp->next==NULL )
	break;
	    if ( nsc_sp->next==NULL )
return( false );
	    p_end = p_nextsp;
	    sc_sp = nsc_sp;
	    p_nextsp = p_nextsp->next->to;
	    nsc_sp = nsc_sp->next->to;
	}
	pend_unit.x = p_nextsp->me.x - p_end->me.x; pend_unit.y = p_nextsp->me.y - p_end->me.y;
	len = sqrt(pend_unit.x*pend_unit.x + pend_unit.y*pend_unit.y);
	if ( len==0 )
return( false );
	pend_unit.x /= len; pend_unit.y /= len;
	if ( (sp->me.x-nsc_sp->me.x)*(sp->me.x-nsc_sp->me.x) +
		(sp->me.y-nsc_sp->me.y)*(sp->me.y-nsc_sp->me.y) < len*len )
return( false );
    }

/* ******************* Match with no transformations applied **************** */
    first_of_path = true;
    for (sc_sp=sp; ; ) {
	if ( sc_sp->ticked )		/* Don't search within stuff we have just replaced */
return( false );

	if ( p_sp->next==NULL ) {
	    if ( substring || sc_sp->next==NULL ) {
		s->last_sp = saw_sc_first ? NULL : sp;
return( true );
	    }
    break;
	}
	np_sp = p_sp->next->to;
	if ( sc_sp->next==NULL )
    break;
	nsc_sp = sc_sp->next->to;

	if ( first_of_path && s->endpoints ) {
	    SplinePoint *sc_prevsp;
	    if ( sc_sp->prev==NULL )
return( false );
	    sc_prevsp = sc_sp->prev->from;
	    if ( !p_sp->noprevcp ) {
		if ( sc_sp->noprevcp )
return( false );
		if ( !CoordMatches(sc_sp->prevcp.x-sc_sp->me.x,p_sp->prevcp.x-p_sp->me.x,s) ||
		     !CoordMatches(sc_sp->prevcp.y-sc_sp->me.y,p_sp->prevcp.y-p_sp->me.y,s) )
    break;	/* prev control points do not match, give up */
	    } else {
		if ( !sc_sp->noprevcp )
return( false );
		sc_unit.x = sc_sp->me.x - sc_prevsp->me.x; sc_unit.y = sc_sp->me.y - sc_prevsp->me.y;
		len = sqrt(sc_unit.x*sc_unit.x + sc_unit.y*sc_unit.y );
		if ( len==0 )
return( false );
		sc_unit.x /= len; sc_unit.y /= len;
		if ( !RealNear(sc_unit.x,p_unit.x) || !RealNear(sc_unit.y,p_unit.y))
    break;
	    }
	    first_of_path = false;
	}
	if ( np_sp->next==NULL && s->endpoints ) {
	    SplinePoint *sc_nextsp;
	    if ( sc_sp->next==NULL )
return( false );
	    sc_nextsp = sc_sp->next->to;
	    if ( !p_sp->nonextcp ) {
		if ( !CoordMatches(sc_sp->nextcp.x-sc_sp->me.x,p_sp->nextcp.x-p_sp->me.x,s) ||
		     !CoordMatches(sc_sp->nextcp.y-sc_sp->me.y,p_sp->nextcp.y-p_sp->me.y,s) )
    break;	/* prev control points do not match, give up */
	    } else {
		if ( !sc_sp->nonextcp )
return( false );
		sc_unit.x = sc_nextsp->me.x - sc_sp->me.x; sc_unit.y = sc_nextsp->me.y - sc_sp->me.y;
		len = sqrt(sc_unit.x*sc_unit.x + sc_unit.y*sc_unit.y );
		if ( len==0 )
return( false );
		sc_unit.x /= len; sc_unit.y /= len;
		if ( RealNear(sc_unit.x,pend_unit.x) && RealNear(sc_unit.y,pend_unit.y)) {
		    s->last_sp = saw_sc_first ? NULL : sp;
return( true );
		} else
    break;
	    }
	}

	if ( !CoordMatches(sc_sp->nextcp.x-sc_sp->me.x,p_sp->nextcp.x-p_sp->me.x,s) ||
		!CoordMatches(sc_sp->nextcp.y-sc_sp->me.y,p_sp->nextcp.y-p_sp->me.y,s) ||
		!CoordMatches(nsc_sp->me.x-sc_sp->me.x,np_sp->me.x-p_sp->me.x,s) ||
		!CoordMatches(nsc_sp->me.y-sc_sp->me.y,np_sp->me.y-p_sp->me.y,s) ||
		!CoordMatches(nsc_sp->prevcp.x-nsc_sp->me.x,np_sp->prevcp.x-np_sp->me.x,s) ||
		!CoordMatches(nsc_sp->prevcp.y-nsc_sp->me.y,np_sp->prevcp.y-np_sp->me.y,s) )
    break;
	if ( np_sp==path->first ) {
	    if ( nsc_sp==sp ) {
		s->last_sp = saw_sc_first ? NULL : sp;
return( true );
	    }
    break;
	}
	sc_sp = nsc_sp;
	if ( sc_sp == sc_path_first )
	    saw_sc_first = true;
	p_sp = np_sp;
    }

/* ************** Match with just flip transformations applied ************** */
    if ( s->tryflips ) for ( flip=flip_x ; flip<=flip_xy; ++flip ) {
	int xsign = (flip&1) ? -1 : 1, ysign = (flip&2) ? -1 : 1;
	saw_sc_first = false;
	p_sp = s->endpoints ? path->first->next->to : path->first;
	first_of_path = true;
	for (sc_sp=sp; ; ) {
	    if ( p_sp->next==NULL ) {
		if ( substring || sc_sp->next==NULL ) {
		    s->matched_flip = flip;
		    s->last_sp = saw_sc_first ? NULL : sp;
return( true );
		} else
    break;
	    }
	    np_sp = p_sp->next->to;
	    if ( sc_sp->next==NULL )
    break;
	    nsc_sp = sc_sp->next->to;

	    if ( first_of_path && s->endpoints ) {
		SplinePoint *sc_prevsp;
		/* if ( sc_sp->prev==NULL )*/	/* Already checked this above */
		sc_prevsp = sc_sp->prev->from;
		if ( !p_sp->noprevcp ) {
		    if ( !CoordMatches(sc_sp->prevcp.x-sc_sp->me.x,xsign*(p_sp->prevcp.x-p_sp->me.x),s) ||
			 !CoordMatches(sc_sp->prevcp.y-sc_sp->me.y,ysign*(p_sp->prevcp.y-p_sp->me.y),s) )
	break;	/* prev control points do not match, give up */
		} else {
		    sc_unit.x = sc_sp->me.x - sc_prevsp->me.x; sc_unit.y = sc_sp->me.y - sc_prevsp->me.y;
		    len = sqrt(sc_unit.x*sc_unit.x + sc_unit.y*sc_unit.y );
		    sc_unit.x /= len; sc_unit.y /= len;
		    if ( !RealNear(sc_unit.x,xsign * p_unit.x) || !RealNear(sc_unit.y,ysign*p_unit.y))
	break;
		}
		first_of_path = false;
	    }
	    if ( np_sp->next==NULL && s->endpoints ) {
		SplinePoint *sc_nextsp;
		if ( sc_sp->next==NULL )
return( false );
		sc_nextsp = sc_sp->next->to;
		if ( !p_sp->nonextcp ) {
		    if ( !CoordMatches(sc_sp->nextcp.x-sc_sp->me.x,xsign*(p_sp->nextcp.x-p_sp->me.x),s) ||
			 !CoordMatches(sc_sp->nextcp.y-sc_sp->me.y,ysign*(p_sp->nextcp.y-p_sp->me.y),s) )
	break;	/* prev control points do not match, give up */
		} else {
		    if ( !sc_sp->nonextcp )
return( false );
		    sc_unit.x = sc_nextsp->me.x - sc_sp->me.x; sc_unit.y = sc_nextsp->me.y - sc_sp->me.y;
		    len = sqrt(sc_unit.x*sc_unit.x + sc_unit.y*sc_unit.y );
		    if ( len==0 )
return( false );
		    sc_unit.x /= len; sc_unit.y /= len;
		    if ( RealNear(sc_unit.x,xsign*pend_unit.x) && RealNear(sc_unit.y,ysign*pend_unit.y)) {
			s->matched_flip = flip;
			s->last_sp = saw_sc_first ? NULL : sp;
return( true );
		    } else
	break;
		}
	    }

	    if ( !CoordMatches(sc_sp->nextcp.x-sc_sp->me.x,xsign*(p_sp->nextcp.x-p_sp->me.x),s) ||
		    !CoordMatches(sc_sp->nextcp.y-sc_sp->me.y,ysign*(p_sp->nextcp.y-p_sp->me.y),s) ||
		    !CoordMatches(nsc_sp->me.x-sc_sp->me.x,xsign*(np_sp->me.x-p_sp->me.x),s) ||
		    !CoordMatches(nsc_sp->me.y-sc_sp->me.y,ysign*(np_sp->me.y-p_sp->me.y),s) ||
		    !CoordMatches(nsc_sp->prevcp.x-nsc_sp->me.x,xsign*(np_sp->prevcp.x-np_sp->me.x),s) ||
		    !CoordMatches(nsc_sp->prevcp.y-nsc_sp->me.y,ysign*(np_sp->prevcp.y-np_sp->me.y),s) )
    break;
	    if ( np_sp==path->first ) {
		if ( nsc_sp==sp ) {
		    s->matched_flip = flip;
		    s->last_sp = saw_sc_first ? NULL : sp;
return( true );
		} else
    break;
	    }
	    sc_sp = nsc_sp;
	    if ( sc_sp == sc_path_first )
		saw_sc_first = true;
	    p_sp = np_sp;
	}
    }

/* ******* Match with rotate, scale and flip transformations applied ******** */
    if ( s->tryrotate || s->tryscale ) {
	if ( s->tryflips )
	    flipmax = flip_xy;
	else
	    flipmax = flip_none;
	for ( flip=flip_none ; flip<=flipmax; ++flip ) {
	    p_sp = s->endpoints ? path->first->next->to : path->first;
	    np_sp = p_sp->next->to;	/* if p_sp->next were NULL, we'd have returned by now */
	    sc_sp = sp;
	    if ( sc_sp->next==NULL )
return( false );
	    nsc_sp = sc_sp->next->to;
	    if ( p_sp->me.x==np_sp->me.x && p_sp->me.y==np_sp->me.y )
return( false );
	    if ( sc_sp->me.x==nsc_sp->me.x && sc_sp->me.y==nsc_sp->me.y )
return( false );
	    if ( s->tryrotate && s->endpoints && np_sp->next == NULL ) {
		int xsign = (flip&1)?-1:1, ysign=(flip&2)?-1:1;
		if ( !p_sp->noprevcp ) {
		    rot = atan2(xsign*(sc_sp->me.y-sc_sp->prevcp.y),ysign*(sc_sp->me.x-sc_sp->prevcp.x)) -
			  atan2(        p_sp->me.y- p_sp->prevcp.y,         p_sp->me.x- p_sp->prevcp.x);
		} else {
		    rot = atan2(xsign*(sc_unit.y),ysign*(sc_unit.x)) -
			  atan2(        p_unit.y,         p_unit.x);
		}
		scale = 1;
	    } else if ( s->endpoints && np_sp->next == NULL ) {
return( false );		/* Not enough info to make a guess */
	    } else if ( !s->tryrotate ) {
		if ( p_sp->me.x==np_sp->me.x )
		    scale = (np_sp->me.y-p_sp->me.y) / (nsc_sp->me.y-sc_sp->me.y);
		else if ( p_sp->me.y==np_sp->me.y )
		    scale = (np_sp->me.x-p_sp->me.x) / (nsc_sp->me.x-sc_sp->me.x);
		else {
		    real yscale = (np_sp->me.y-p_sp->me.y) / (nsc_sp->me.y-sc_sp->me.y);
		    scale = (np_sp->me.x-p_sp->me.x) / (nsc_sp->me.x-sc_sp->me.x);
		    if ( scale<.99*yscale || scale>1.01*yscale )
return( false );
		}
		rot = 0;
	    } else {
		int xsign = (flip&1)?-1:1, ysign=(flip&2)?-1:1;
		rot = atan2(xsign*(nsc_sp->me.y-sc_sp->me.y),ysign*(nsc_sp->me.x-sc_sp->me.x)) -
			atan2(np_sp->me.y-p_sp->me.y,np_sp->me.x-p_sp->me.x);
		if ( !s->tryscale )
		    scale = 1;
		else
		    scale = sqrt(  ((np_sp->me.y-p_sp->me.y)*(np_sp->me.y-p_sp->me.y) +
				    (np_sp->me.x-p_sp->me.x)*(np_sp->me.x-p_sp->me.x))/
				   ((nsc_sp->me.y-sc_sp->me.y)*(nsc_sp->me.y-sc_sp->me.y) +
				    (nsc_sp->me.x-sc_sp->me.x)*(nsc_sp->me.x-sc_sp->me.x))  );
	    }
	    if ( scale>-.00001 && scale<.00001 )
return( false );
	    s->matched_rot = rot;
	    if ( rot==0 )
		s->matched_co=1,s->matched_si=0;
	    else if ( rot>3.14159 && rot<3.141595 )
		s->matched_co=-1,s->matched_si=0;
	    else if ( rot>1.570793 && rot<1.570799 )
		s->matched_co=0,s->matched_si=1;
	    else if ( (rot>4.712386 && rot<4.712392 ) ||
		      (rot<-1.570793 && rot>-1.570799 ) )
		s->matched_co=0,s->matched_si=-1;
	    else
		s->matched_co = cos(rot), s->matched_si = sin(rot);
	    saw_sc_first = false;
	    first_of_path = true;
	    for (sc_sp=sp ; ; ) {
		if ( p_sp->next==NULL ) {
		    if ( substring || sc_sp->next==NULL ) {
			s->matched_flip = flip;
			s->matched_rot = rot;
			s->matched_scale = scale;
			s->last_sp = saw_sc_first ? NULL : sp;
return( true );
		    } else
return( false );
		}
		np_sp = p_sp->next->to;
		if ( sc_sp->next==NULL )
return( false );
		nsc_sp = sc_sp->next->to;

		if ( first_of_path && s->endpoints ) {
		    SplinePoint *sc_prevsp;
		    /* if ( sc_sp->prev==NULL )*/	/* Already checked this above */
		    sc_prevsp = sc_sp->prev->from;
		    if ( !p_sp->noprevcp ) {
			if ( !BPMatches(&sc_sp->prevcp,&sc_sp->me,&p_sp->prevcp,&p_sp->me,flip,rot,scale,s) )
	    break;
		    } else {
			sc_unit.x = sc_sp->me.x - sc_prevsp->me.x; sc_unit.y = sc_sp->me.y - sc_prevsp->me.y;
			len = sqrt(sc_unit.x*sc_unit.x + sc_unit.y*sc_unit.y );
			sc_unit.x /= len; sc_unit.y /= len;
			temp      =  sc_unit.x * s->matched_co + sc_unit.y * s->matched_si;
			sc_unit.y = -sc_unit.x * s->matched_si + sc_unit.y * s->matched_co;
			sc_unit.x = temp;
			if ( !RealNear(sc_unit.x,p_unit.x) || !RealNear(sc_unit.y,p_unit.y))
	    break;
		    }
		    first_of_path = false;
		}
		if ( np_sp->next==NULL && s->endpoints ) {
		    SplinePoint *sc_nextsp;
		    if ( sc_sp->next==NULL )
return( false );
		    sc_nextsp = sc_sp->next->to;
		    if ( !p_sp->nonextcp ) {
			if ( !BPMatches(&sc_sp->nextcp,&sc_sp->me,&p_sp->nextcp,&p_sp->me,flip,rot,scale,s) )
	    break;
		    } else {
			if ( !sc_sp->nonextcp )
return( false );
			sc_unit.x = sc_nextsp->me.x - sc_sp->me.x; sc_unit.y = sc_nextsp->me.y - sc_sp->me.y;
			len = sqrt(sc_unit.x*sc_unit.x + sc_unit.y*sc_unit.y );
			if ( len==0 )
return( false );
			sc_unit.x /= len; sc_unit.y /= len;
			temp      =  sc_unit.x * s->matched_co + sc_unit.y * s->matched_si;
			sc_unit.y = -sc_unit.x * s->matched_si + sc_unit.y * s->matched_co;
			sc_unit.x = temp;
			if ( RealNear(sc_unit.x,pend_unit.x) && RealNear(sc_unit.y,pend_unit.y)) {
			    s->matched_flip = flip;
			    s->matched_rot = rot;
			    s->matched_scale = scale;
			    s->last_sp = saw_sc_first ? NULL : sp;
return( true );
			} else
	    break;
		    }
		}
		
		if ( !BPMatches(&sc_sp->nextcp,&sc_sp->me,&p_sp->nextcp,&p_sp->me,flip,rot,scale,s) ||
			!BPMatches(&nsc_sp->me,&sc_sp->me,&np_sp->me,&p_sp->me,flip,rot,scale,s) ||
			!BPMatches(&nsc_sp->prevcp,&nsc_sp->me,&np_sp->prevcp,&np_sp->me,flip,rot,scale,s) )
return( false );
		if ( np_sp==path->first ) {
		    if ( nsc_sp==sp ) {
			s->matched_flip = flip;
			s->matched_rot = rot;
			s->matched_scale = scale;
			s->last_sp = saw_sc_first ? NULL : sp;
return( true );
		    } else
return( false );
		}
		sc_sp = nsc_sp;
		if ( sc_sp == sc_path_first )
		    saw_sc_first = true;
		p_sp = np_sp;
	    }
	}
    }
return( false );
}