Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1327 lines
32 KiB

//
// Copyright (c) 1997-1999 Microsoft Corporation.
//
#include "stdafx.h"
#include "vdata.h"
#include "extfunc.h"
#include "ttfstruc.h"
/* Smooth sort */
#define SMOOTH 0x8000
#define NOSMOOTH 0x4000
#define BACKWARD 0x2000 /* NOSMOOTH is forward vector */
#define FOREWARD 0x1000 /* NOSMOOTH is backward vector*/
/* Curve Type */
#define SPLINE_ATR 0x0001
/* Smoothing anchor Point */
#define SMOOTHANCHOR 0x0080
/* Smoothing anchor point is based 90degree Rule */
/* for turning */
#define TURN_OU 1 /* 凹 */
#define TURN_TOTSU 2 /* 凸 */
#define sign(n) (n < 0 ? 1 : 0)
#define LONGMIN 5
int SmoothVector(int lstHdl,int tmpLst,int xinMesh,int yinMesh, int outMesh,struct SMOOTHPRM *prm,int fp);
static int BindVector(int inLst,int outLst);
static int BindPoint(int inLst,int outLst);
static int DetectNoSmooth(int lsthdl);
static void turnsort(struct VDATA *vp);
static void generalsmooth(struct VDATA *vp);
static int isturn(struct VDATA *vp);
static int islong(struct VDATA *vp);
static void longline(struct VDATA *vp);
static int ZoomPoint(int lstHdl,int xinMesh,int yinMesh, int outMesh,int uFp);
static int preproc1(int inLst,int outLst);
static int diveachside(struct VDATA *vp,int outLst);
static int divoneside(struct VDATA *vp,int outLst);
static int divVec( int ilst, int olst, int divN);
static int Smooth1(int inLst,int outLst,int weight1,int weight2,int weight3);
static int Smooth2(int inLst,int outLst);
int searchanchor(int sn,struct VDATA *sp,struct VDATA * *ep,int lim);
static int smooth1sub(struct VDATA *vp,int np,int outLst,int w1,int w2,int w3);
static int smooth2sub(struct VDATA *vp,int np,int outLst);
int RemoveFp(int lstHdl,int outMesh,int uFp);
static int BindLinears(int inLst,int outLst);
static int DelZeroVec(int inLst,int outLst);
int toTTFFrame(int lstH,struct BBX *bbx);
static int lightSub(int inLst,int outLst);
int SmoothLight(int ioLst,int tmpLst,int width,int height, int oWidth,int ufpVal);
int ConvMesh(int lstH,int inMesh,int outMesh);
static int
straightCurve( int iLst, int oLst)
{
struct VHEAD *vhd;
struct VDATA *vp;
struct vecdata rel, nxtrel;
int np;
int sts;
struct vecdata svd;
if ( (sts = VDGetHead( iLst, &vhd))!=0)
goto RET;
VDNew(oLst);
while ( vhd->next!=NIL) {
/* No point data is not Allowed */
/* Set Origin */
vp = vhd->headp;
if ((sts = VDSetData(oLst, &vp->vd))!=0)
goto RET;
vp=vp->next;
for ( np = 1; np < vhd->nPoints; np++,vp = vp->next) {
if ( vp->vd.atr & SPLINE_ATR) {
rel.x = vp->vd.x - vp->prev->vd.x;
rel.y = vp->vd.y - vp->prev->vd.y;
nxtrel.x= vp->next->vd.x - vp->vd.x;
nxtrel.y= vp->next->vd.y - vp->vd.y;
if ((long)rel.x*nxtrel.y==(long)rel.y*nxtrel.x){
vp = vp->next;
np++;
svd = vp->vd;
svd.atr &= ~SPLINE_ATR;
if ((sts = VDSetData(oLst, &svd))!=0)
goto RET;
}
else {
if ((sts = VDSetData(oLst, &vp->vd))!=0)
goto RET;
vp = vp->next;
np++;
if ( np >= vhd->nPoints)
break;
if ((sts = VDSetData(oLst, &vp->vd))!=0)
goto RET;
}
}
else {
if ((sts = VDSetData(oLst, &vp->vd))!=0)
goto RET;
}
}
if(VDClose( oLst))
goto RET;
vhd = vhd->next;
}
return 0;
RET:
return -1;
}
/***********************************************************************
* Smoothing Main
*/
/* */ int
/* */ SmoothVector(
/* */ int lstHdl,
/* */ int tmpLst,
/* */ int xinMesh, /* Input Mesh Size*/
/* */ int yinMesh,
/* */ int outMesh, /* Output Mesh size */
/* */ struct SMOOTHPRM *prm,
/* */ int fp) /* Fixed Point sft-val */
/*
* reuturns : 0, -1
* Remarks : このモジュールの入力は、輪郭抽出の結果のベクタ列で
*  原点を左上とする。
*  出力は、出力メッシュに合わせるが、原点は左上で、
*  ベースライン、左側ベアリングは調整されない
***********************************************************************/
{
int sts;
if ( (sts = BindPoint( lstHdl, tmpLst))<0)
goto RET;
if ( (sts = DetectNoSmooth( tmpLst))<0)
goto RET;
if ( (sts = ZoomPoint( tmpLst, xinMesh, yinMesh, outMesh, fp))<0)
goto RET;
if ( (sts = preproc1( tmpLst, lstHdl))<0)
goto RET;
/* */
if ( prm->UseConic) {
if ( sts = divVec( lstHdl, tmpLst, 2))
goto RET;
if ( (sts = Smooth1( tmpLst, lstHdl, 1, 2, 1))<0)
goto RET;
if ( (sts = Smooth2( lstHdl, tmpLst))<0)
goto RET;
if ( sts = FitConic(tmpLst,lstHdl, prm->SmoothLevel, fp))
goto RET;
}
else {
if ( (sts = Smooth1( lstHdl, tmpLst, 1, 2, 1))<0)
goto RET;
if ( (sts = Smooth2( tmpLst, lstHdl))<0)
goto RET;
}
if ( (sts = DelZeroVec( lstHdl, tmpLst))<0)
goto RET;
if ( (sts = straightCurve( tmpLst, lstHdl))<0)
goto RET;
if ( (sts = DelZeroVec( lstHdl, tmpLst))<0)
goto RET;
sts = BindLinears( tmpLst, lstHdl);
RET:
return sts;
}
/***********************************************************************
* Bind Same Direction Unit Vector
*/
/* */ static int
/* */ BindVector(
/* */ int inLst, /* Absolute Coordinate */
/* */ int outLst) /* Relative one */
/*
* reuturns : 0, -1
***********************************************************************/
{
struct VHEAD *vhd;
struct VDATA *vp;
struct vecdata rel, nxtrel;
int np;
int sts;
if ( (sts = VDGetHead( inLst, &vhd))!=0)
goto RET;
VDNew(outLst);
nxtrel.atr = 1;
while ( vhd->next!=NIL) {
/* No point data is not Allowed */
/* Set Origin */
vp = vhd->headp;
if ((sts = VDSetData(outLst, &vp->vd))!=0)
goto RET;
rel.x = rel.y = 0;
for ( np = 0; np < vhd->nPoints; np++,vp = vp->next) {
nxtrel.x = vp->next->vd.x - vp->vd.x;
nxtrel.y = vp->next->vd.y - vp->vd.y;
if ( rel.x==0 && rel.y ==0)
rel = nxtrel;
else {
if ( rel.y==0 && nxtrel.y==0)
rel.x += nxtrel.x;
else if ( rel.x == 0 && nxtrel.x==0)
rel.y += nxtrel.y;
else {
if ((sts=VDSetData(outLst, &rel))!=0)
goto RET;
rel = nxtrel;
}
}
}
if ( rel.x!=0 || rel.y!=0) {
if ((sts=VDSetData(outLst, &rel))!=0)
goto RET;
}
vhd = vhd->next;
if ((sts = VDClose(outLst))!=0)
goto RET;
}
RET:
return( sts);
}
/***********************************************************************
* Bind Same Direction Unit Vector(Absolute Coodinate Version)
* Only for short vector ( dont care SPLINE )
*/
/* */ static int
/* */ BindPoint(
/* */ int inLst, /* Absolute Coordinate */
/* */ int outLst) /* .. */
/*
* reuturns : 0, -1
***********************************************************************/
{
struct VHEAD *vhd;
struct VDATA *vp;
struct vecdata lastvd;
int np;
int sts;
if ( (sts = VDGetHead( inLst, &vhd))!=0)
goto RET;
VDNew(outLst);
while ( vhd->next!=NIL) {
/* No point data is not Allowed */
/* Set Origin */
vp = vhd->headp;
if ((sts = VDSetData(outLst, &vp->vd))!=0)
goto RET;
lastvd = vp->vd;
for ( np = 0; np < vhd->nPoints; np++,vp = vp->next) {
if (vp->next->vd.x != lastvd.x && vp->next->vd.y != lastvd.y) {
if ((sts=VDSetData(outLst, &vp->vd))!=0)
goto RET;
lastvd = vp->vd;
}
}
vhd = vhd->next;
if ((sts = VDClose(outLst))!=0)
goto RET;
}
RET:
return( sts);
}
/***********************************************************************
* Detect Corner and edge
*/
/* */ static int
/* */ DetectNoSmooth(
/* */ int lsthdl) /* Absolute Coordinate */
/*
* returns : 0, -1
***********************************************************************/
{
struct VHEAD *vhd;
int sts;
struct VDATA *vp;
int np;
if ( (sts = VDGetHead( lsthdl, &vhd))!=0)
goto RET;
while ( vhd->next != NIL) {
vp = vhd->headp;
for ( np = 0; np < vhd->nPoints; np++, vp = vp->next) {
if ( isturn( vp) )
turnsort(vp);
else if (islong (vp))
longline( vp);
else /* based on general rule */
generalsmooth(vp);
}
vhd = vhd->next;
}
RET:
return sts;
}
/***********************************************************************
* Judge smooth or not at Turning Part
*/
/* */ static void
/* */ turnsort(
/* */ struct VDATA *vp)
/*
* returns : none
***********************************************************************/
{
struct vecdata cur, prev1, prev2, next1, next2;
cur.x = vp->vd.x-vp->prev->vd.x;
cur.y = vp->vd.y-vp->prev->vd.y;
prev1.x = vp->prev->vd.x-vp->prev->prev->vd.x;
prev1.y = vp->prev->vd.y-vp->prev->prev->vd.y;
prev2.x = vp->prev->prev->vd.x-vp->prev->prev->prev->vd.x;
prev2.y = vp->prev->prev->vd.y-vp->prev->prev->prev->vd.y;
next1.x = vp->next->vd.x - vp->vd.x;
next1.y = vp->next->vd.y - vp->vd.y;
next2.x = vp->next->next->vd.x - vp->next->vd.x;
next2.y = vp->next->next->vd.y - vp->next->vd.y;
if ( cur.x) {
if ( abs(next1.y) > 1)
vp->vd.atr |= NOSMOOTH ;
else if ( sign( cur.x) == sign( next2.x))
vp->vd.atr |= SMOOTH | BACKWARD;
else
vp->vd.atr |= NOSMOOTH;
if ( abs(prev1.y) > 1)
vp->prev->vd.atr |= NOSMOOTH ;
else if (sign(cur.x)==sign(prev2.x))
vp->prev->vd.atr |= SMOOTH | FOREWARD;
else
vp->prev->vd.atr |= NOSMOOTH ;
}
else {
if ( abs(next1.x) > 1)
vp->vd.atr |= NOSMOOTH ;
else if ( sign( cur.y) == sign( next2.y))
vp->vd.atr |= SMOOTH | BACKWARD;
else
vp->vd.atr |= NOSMOOTH;
if ( abs(prev1.x) > 1)
vp->prev->vd.atr |= NOSMOOTH ;
else if (sign(cur.y)==sign(prev2.y))
vp->prev->vd.atr |= SMOOTH | FOREWARD;
else
vp->prev->vd.atr |= NOSMOOTH;
}
return;
}
/***********************************************************************
* Judge Smooth or not with general rule
*/
/* */ static void
/* */ generalsmooth( struct VDATA *vp)
/*
* returns : none
***********************************************************************/
{
struct vecdata prev2, prev1, cur, next1, next2, next3;
cur.x = vp->vd.x- vp->prev->vd.x;
cur.y = vp->vd.y- vp->prev->vd.y;
prev1.x = vp->prev->vd.x - vp->prev->prev->vd.x;
prev1.y = vp->prev->vd.y - vp->prev->prev->vd.y;
prev2.x = vp->prev->prev->vd.x - vp->prev->prev->prev->vd.x;
prev2.y = vp->prev->prev->vd.y - vp->prev->prev->prev->vd.y;
next1.x = vp->next->vd.x - vp->vd.x;
next1.y = vp->next->vd.y - vp->vd.y;
next2.x = vp->next->next->vd.x - vp->next->vd.x;
next2.y = vp->next->next->vd.y - vp->next->vd.y;
next3.x = vp->next->next->next->vd.x - vp->next->next->vd.x;
next3.y = vp->next->next->next->vd.y - vp->next->next->vd.y;
if ( cur.y) {
if ( abs(next1.x)>1 && abs(cur.y)>1) {
if ( sign(cur.y) == sign(next1.x)
&& abs(next2.y)==1
&& abs(prev1.x)==1
&& sign(cur.y)==sign(prev2.y)
&& sign(next1.x)==sign( next3.x))
;
else
vp->vd.atr |= NOSMOOTH;
}
}
else {
if ( abs(next1.y)>1 && abs(cur.x)>1) {
if ( sign(cur.x) != sign(next1.y)
&& abs(next2.x)==1
&& abs(prev1.y)==1
&& sign(cur.x)==sign(prev2.x)
&& sign(next1.y)==sign( next3.y))
;
else
vp->vd.atr |= NOSMOOTH;
}
}
return;
}
/***********************************************************************
* Judge turning
*/
/* */ static int
/* */ isturn( struct VDATA *vp) /* Absolute */
/*
* retuns
***********************************************************************/
{
int turnSort;
struct vecdata prev, cur, next;
prev.x = vp->prev->vd.x - vp->prev->prev->vd.x;
prev.y = vp->prev->vd.y - vp->prev->prev->vd.y;
cur.x = vp->vd.x - vp->prev->vd.x;
cur.y = vp->vd.y - vp->prev->vd.y;
next.x = vp->next->vd.x - vp->vd.x;
next.y = vp->next->vd.y - vp->vd.y;
if ( prev.x !=0) {
if ( sign(prev.x )!=sign(next.x )) {
if (sign(next.x ) ==sign(cur.y))
turnSort = TURN_TOTSU;
else
turnSort = TURN_OU;
}
else turnSort = 0;
}
else {
if ( sign(prev.y )!=sign(next.y )) {
if (sign(next.y ) ==sign(cur.x))
turnSort = TURN_OU;
else
turnSort = TURN_TOTSU;
}
else turnSort = 0;
}
return turnSort;
}
/***********************************************************************
* judge Long Line or Not
*/
/* */ static int
/* */ islong( struct VDATA *vp)
/*
* returns : 0, 1
***********************************************************************/
{
struct vecdata cur, prev1, prev2, next1, next2;
int sts;
cur.x = vp->vd.x - vp->prev->vd.x;
cur.y = vp->vd.y - vp->prev->vd.y;
if ( abs(cur.x)<= LONGMIN && abs(cur.y) <= LONGMIN)
return( 0);
prev2.x = vp->prev->prev->vd.x - vp->prev->prev->prev->vd.x;
prev2.y = vp->prev->prev->vd.y - vp->prev->prev->prev->vd.y;
prev1.x = vp->prev->vd.x - vp->prev->prev->vd.x;
prev1.y = vp->prev->vd.y - vp->prev->prev->vd.y;
next1.x = vp->next->vd.x - vp->vd.x;
next1.y = vp->next->vd.y - vp->vd.y;
next2.x = vp->next->next->vd.x - vp->next->vd.x;
next2.y = vp->next->next->vd.y - vp->next->vd.y;
if ( cur.x) {
if ( (sign(cur.x) != sign(next2.x)
|| abs(next1.y)>1
|| ( abs(next1.y)==1 && abs(cur.x)/2 > abs(next2.x)))
&& (sign(cur.x) != sign(prev2.x)
|| abs(prev1.y)>1
|| ( abs(prev1.y)==1 && abs(cur.x)/2 > abs(prev2.x))))
sts = 1;
/* 94.11.09 */
else if ( abs(cur.x) > 2 && (abs(next1.y)>2 || abs(prev1.y)>2))
sts = 1;
/* */
else sts = 0;
}
else {
if ( (sign(cur.y) != sign(next2.y)
|| abs(next1.x)>1
|| ( abs(next1.x)==1 && abs(cur.y)/2 > abs(next2.y)))
&& (sign(cur.y) != sign(prev2.y)
|| abs(prev1.x)>1
|| ( abs(prev1.x)==1 && abs(cur.y)/2 > abs(prev2.y))))
sts = 1;
/* 94.11.09 */
else if ( abs(cur.y) > 2 && (abs(next1.x)>2 || abs(prev1.x)>2))
sts = 1;
/* */
else sts = 0;
}
return sts;
}
/***********************************************************************
* judge Long Line or Not
*/
/* */ static void
/* */ longline( struct VDATA *vp)
/*
* returns : 0, 1
***********************************************************************/
{
struct vecdata cur, prev1, prev2, next1, next2;
prev2.x = vp->prev->prev->vd.x - vp->prev->prev->prev->vd.x;
prev2.y = vp->prev->prev->vd.y - vp->prev->prev->prev->vd.y;
prev1.x = vp->prev->vd.x - vp->prev->prev->vd.x;
prev1.y = vp->prev->vd.y - vp->prev->prev->vd.y;
cur.x = vp->vd.x - vp->prev->vd.x;
cur.y = vp->vd.y - vp->prev->vd.y;
next1.x = vp->next->vd.x - vp->vd.x;
next1.y = vp->next->vd.y - vp->vd.y;
next2.x = vp->next->next->vd.x - vp->next->vd.x;
next2.y = vp->next->next->vd.y - vp->next->vd.y;
if ( cur.x) {
/* 前方 */
if ( abs(next1.y)!=1 || sign(cur.x)!=sign(next2.x))
vp->vd.atr |= NOSMOOTH;
else if ( abs( next2.x) ==1 && sign(cur.x)==sign(next1.y))
vp->vd.atr |= NOSMOOTH;
else
vp->vd.atr |= NOSMOOTH | BACKWARD;
/* 後方 */
if ( abs(prev1.y)!=1 || sign(cur.x)!=sign(prev2.x))
vp->prev->vd.atr |= NOSMOOTH;
else if ( abs( prev2.x) ==1&& sign(cur.x)!=sign(prev1.y))
vp->prev->vd.atr |= NOSMOOTH;
else
vp->prev->vd.atr |= NOSMOOTH | FOREWARD;
}
else {
/* 前方 */
if ( abs(next1.x)!=1 || sign(cur.y)!=sign(next2.y))
vp->vd.atr |= NOSMOOTH;
else if ( abs( next2.y) ==1 && sign(cur.y)!=sign(next1.x))
vp->vd.atr |= NOSMOOTH;
else
vp->vd.atr |= NOSMOOTH | BACKWARD;
/* 後方 */
if ( abs(prev1.x)!=1 || sign(cur.y)!=sign(prev2.y))
vp->prev->vd.atr |= NOSMOOTH;
else if ( abs( prev2.y) ==1&& sign(cur.y)==sign(prev1.x))
vp->prev->vd.atr |= NOSMOOTH;
else
vp->prev->vd.atr |= NOSMOOTH | FOREWARD;
}
}
/***********************************************************************
* Zoom for fixed point
*/
/* */ static int
/* */ ZoomPoint(
/* */ int lstHdl, /* List Handle to proccess */
/* */ int xinMesh, /* INPut Dot Mesh */
/* */ int yinMesh,
/* */ int outMesh, /* output mesh (256) */
/* */ int uFp) /* Under Fixed Point Value */
/*
* returns : none
* remarks : 処理結果の座標系は、(128,128)[=outMesh/2]を原点に移動し、
*  UFpを掛けた値である
***********************************************************************/
{
struct VHEAD *vhd;
int sts;
struct VDATA *vp;
int np;
int center;
center = outMesh/2*uFp;
if ( (sts = VDGetHead( lstHdl, &vhd))!=0)
goto RET;
while ( vhd->next != NIL) {
vp = vhd->headp;
for ( np = 0; np < vhd->nPoints; np++, vp = vp->next) {
vp->vd.x =(short)((long)vp->vd.x*outMesh*uFp/xinMesh)-center;
vp->vd.y =(short)((long)vp->vd.y*outMesh*uFp/yinMesh)-center;
}
vhd = vhd->next;
}
RET:
return sts;
}
/***********************************************************************
* Pre-Proc1 of smoothing( divide long vector )
*/
/* */ static int
/* */ preproc1( int inLst, int outLst)
/*
* returns : 0. -1
***********************************************************************/
{
struct VHEAD *vhd;
int sts;
struct VDATA *vp;
int np;
struct vecdata vd;
if ( (sts = VDGetHead( inLst, &vhd))!=0)
goto RET;
VDNew( outLst);
while ( vhd->next != NIL) {
vp = vhd->headp;
for ( np = 0; np < vhd->nPoints; ) {
if ( vp->vd.atr & FOREWARD) {
if ( vp->next->vd.atr& BACKWARD) {
if ((sts = diveachside( vp, outLst))<0)
goto RET;
np++;
vp = vp->next;
}
else {
if ((sts=divoneside(vp, outLst))<0)
goto RET;
}
}
else if ((vp->vd.atr & BACKWARD)
&& (vp->prev->vd.atr & FOREWARD)==0){
if ( (sts = divoneside( vp, outLst))<0)
goto RET;
}
else { /* only copy */
vd = vp->vd;
if ( vp->vd.atr & NOSMOOTH)
vd.atr = SMOOTHANCHOR;
if ((sts=VDSetData( outLst, &vd))<0)
goto RET;
}
np++;
vp = vp->next;
}
if ( (sts = VDClose( outLst))<0)
break;
vhd = vhd->next;
}
RET:
return sts;
}
/***********************************************************************
* Divide Vector from each side( for PreProc)
*/
/* */ static int
/* */ diveachside( struct VDATA *vp, int outLst)
/*
* returns : 0, -1
***********************************************************************/
{
struct vecdata prev, cur, next1, next2, next3;
struct vecdata div1, div2;
int sts;
prev.x = vp->prev->vd.x - vp->prev->prev->vd.x;
prev.y = vp->prev->vd.y - vp->prev->prev->vd.y;
cur.x = vp->vd.x - vp->prev->vd.x;
cur.y = vp->vd.y - vp->prev->vd.y;
next1.x = vp->next->vd.x - vp->vd.x;
next1.y = vp->next->vd.y - vp->vd.y;
next2.x = vp->next->next->vd.x - vp->next->vd.x;
next2.y = vp->next->next->vd.y - vp->next->vd.y;
next3.x = vp->next->next->next->vd.x - vp->next->next->vd.x;
next3.y = vp->next->next->next->vd.y - vp->next->next->vd.y;
sts = 0;
if ( next1.x) {
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
div1.y = vp->vd.y;
div2.y = vp->vd.y;
div1.atr = SMOOTHANCHOR;
div2.atr = SMOOTHANCHOR;
if ( abs(prev.x) + abs( next3.x) <= abs(next1.x)) {
div1.x = vp->vd.x + prev.x;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
div2.x = vp->next->vd.x - next3.x;
if ( (sts = VDSetData( outLst, &div2))<0)
goto RET;
if ( (sts = VDSetData( outLst, &vp->next->vd))<0)
goto RET;
}
else {
div1.x = (short)((long)next1.x*abs(prev.x)/abs(prev.x + next3.x));
if ( div1.x != 0) {
div1.x += vp->vd.x;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
if ( (sts = VDSetData( outLst, &vp->next->vd))<0)
goto RET;
}
else {
div1.x = vp->next->vd.x;
div1.y = vp->next->vd.y;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
}
}
}
else {
div1.x = vp->vd.x;
div2.x = vp->vd.x;
div1.atr = SMOOTHANCHOR;
div2.atr = SMOOTHANCHOR;
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
if ( abs(prev.y) + abs( next3.y) <= abs(next1.y)) {
// div1.y = vp->vd.y + prev.y;
div1.y = vp->vd.y + prev.y/2;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
// div2.y = vp->next->vd.y - next3.y;
div2.y = vp->next->vd.y - next3.y/2;
if ( (sts = VDSetData( outLst, &div2))<0)
goto RET;
if ( (sts = VDSetData( outLst, &vp->next->vd))<0)
goto RET;
}
else {
div1.y = (short)((long)next1.y*abs(prev.y)/abs(prev.y + next3.y));
if ( div1.y!=0) {
div1.y += vp->vd.y;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
if ( (sts = VDSetData( outLst, &vp->next->vd))<0)
goto RET;
}
else {
div1.x = vp->next->vd.x;
div1.y = vp->next->vd.y;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
}
}
}
RET:
return( sts);
}
/***********************************************************************
*
*/
/* */ static int
/* */ divoneside(
/* */ struct VDATA *vp,
/* */ int outLst)
/*
*
***********************************************************************/
{
struct vecdata prev, cur, next1, next2;
struct vecdata div1;
int sts;
sts = 0;
div1.atr = SMOOTHANCHOR;
if ( vp->vd.atr & FOREWARD) {
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
prev.x = vp->prev->vd.x - vp->prev->prev->vd.x;
prev.y = vp->prev->vd.y - vp->prev->prev->vd.y;
cur.x = vp->vd.x - vp->prev->vd.x;
cur.y = vp->vd.y - vp->prev->vd.y;
next1.x = vp->next->vd.x - vp->vd.x;
next1.y = vp->next->vd.y - vp->vd.y;
if ( vp->vd.x == vp->prev->vd.x) {
if ( abs(prev.x) < abs(next1.x)) {
div1.y = vp->vd.y;
// div1.x = vp->vd.x + prev.x;
div1.x = vp->vd.x + prev.x/2;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
}
}
else {
if ( abs(prev.y) < abs(next1.y)) {
div1.x = vp->vd.x;
// div1.y = vp->vd.y + prev.y;
div1.y = vp->vd.y + prev.y/2;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
}
}
}
else {
cur.x = vp->vd.x - vp->prev->vd.x;
cur.y = vp->vd.y - vp->prev->vd.y;
next2.x = vp->next->next->vd.x - vp->next->vd.x;
next2.y = vp->next->next->vd.y - vp->next->vd.y;
if ( vp->vd.x == vp->next->vd.x) {
if ( abs(cur.x) > abs(next2.x)) {
// div1.x = vp->vd.x - next2.x;
div1.x = vp->vd.x - next2.x/2;
div1.y = vp->vd.y;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
}
}
else {
if ( abs(cur.y) > abs(next2.y)) {
div1.x = vp->vd.x;
// div1.y = vp->vd.y - next2.y;
div1.y = vp->vd.y - next2.y/2;
if ( (sts = VDSetData( outLst, &div1))<0)
goto RET;
}
}
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
}
RET:
return( sts);
}
/***********************************************************************
* Smoothing 1
*/
/* */ static int
/* */ Smooth1( int inLst,
/* */ int outLst,
/* */ int weight1, /* Waight of Smoothing Form.*/
/* */ int weight2,
/* */ int weight3 )
/*
* returns : 0, -1
***********************************************************************/
{
struct VHEAD *vhd;
int sts;
struct VDATA *svp, *evp;
int sp, ep;
if ( (sts = VDGetHead( inLst, &vhd))!=0)
goto RET;
VDNew( outLst);
while ( vhd->next != NIL) {
svp = vhd->headp;
if ((sp=searchanchor(0,svp,&svp,vhd->nPoints))<vhd->nPoints){
while(sp <vhd->nPoints) {
ep = searchanchor(sp+1, svp->next,&evp, vhd->nPoints);
if ((sts=smooth1sub( svp, ep-sp,outLst,weight1, weight2, weight3))<0)
goto RET;
if ( ep >= vhd->nPoints)
break;
sp = ep;
svp = evp;
}
}
vhd = vhd->next;
if ( (sts = VDClose( outLst)) < 0)
break;
}
RET:
return sts;
}
/***********************************************************************
* Smoothing 2 ( mabiki)
*/
/* */ static int
/* */ Smooth2( int inLst, int outLst )
/*
* returns : 0, -1
***********************************************************************/
{
struct VHEAD *vhd;
int sts;
struct VDATA *svp, *evp;
int sp, ep;
if ( (sts = VDGetHead( inLst, &vhd))!=0)
goto RET;
VDNew( outLst);
while ( vhd->next != NIL) {
svp = vhd->headp;
if ((sp=searchanchor(0,svp,&svp,vhd->nPoints))<vhd->nPoints){
while(sp <vhd->nPoints) {
ep = searchanchor(sp+1, svp->next,&evp, vhd->nPoints);
if ((sts=smooth2sub( svp, ep-sp,outLst))<0)
goto RET;
if ( ep >= vhd->nPoints)
break;
sp = ep;
svp = evp;
}
}
vhd = vhd->next;
if ( (sts = VDClose( outLst)) < 0)
break;
}
RET:
return sts;
}
/***********************************************************************
* Search Smoothing Anchor Point
*/
/* */ int
/* */ searchanchor(
/* */ int sn,
/* */ struct VDATA *sp,
/* */ struct VDATA **ep,
/* */ int lim)
/*
*
***********************************************************************/
{
while ( lim-- > 0) {
if (sp->vd.atr & SMOOTHANCHOR) {
*ep = sp;
return sn;
}
sp = sp->next;
sn++;
}
return( sn);
}
/***********************************************************************
* Smooth1 body
*/
/* */ static int
/* */ smooth1sub(
/* */ struct VDATA *vp,
/* */ int np,
/* */ int outLst,
/* */ int w1, /* Waight of Smoothing Form.*/
/* */ int w2,
/* */ int w3)
/*
* returns : 0, -1
***********************************************************************/
{
int pcnt,
sts;
struct vecdata vd;
int base;
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
np--;
vp = vp->next;
base = w1 + w2 + w3;
for ( pcnt = 0; pcnt < np; pcnt++, vp= vp->next) {
vd.x = (vp->prev->vd.x*w1 + vp->vd.x*w2 + vp->next->vd.x*w3)/base;
vd.y = (vp->prev->vd.y*w1 + vp->vd.y*w2 + vp->next->vd.y*w3)/base;
vd.atr = vp->vd.atr;
if ( (sts = VDSetData( outLst, &vd))<0)
break;
}
RET:
return( sts);
}
/***********************************************************************
* Smooth2 body ( mabiki body)
*/
/* */ static int
/* */ smooth2sub(
/* */ struct VDATA *vp,
/* */ int np,
/* */ int outLst)
/*
* returns : 0, -1
***********************************************************************/
{
int pcnt,
sts;
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
np--;
vp = vp->next;
for ( pcnt = 0; pcnt < np; pcnt++, vp= vp->next) {
if ( np < 3 || pcnt % 2 == 0) {
if ( (sts = VDSetData( outLst, &vp->vd))<0)
break;
}
}
RET:
return( sts);
}
/***********************************************************************
* Remove Fixed Point
*/
/* */ int
/* */ RemoveFp(
/* */ int lstHdl, /* List Handle to proccess */
/* */ int outMesh, /* output mesh */
/* */ int uFp) /* Under Fixed Point Value */
/*
* returns : none
* remarks : スムーズィングの処理結果の座標系は、UFpで割って原点を
* (128,128) [=outMesh/2]に移動した値である
***********************************************************************/
{
struct VHEAD *vhd;
int sts;
struct VDATA *vp;
int center;
int np;
center = outMesh/2;
if ( (sts = VDGetHead( lstHdl, &vhd))!=0)
goto RET;
while ( vhd->next != NIL) {
vp = vhd->headp;
for ( np = 0; np < vhd->nPoints; np++, vp = vp->next) {
vp->vd.x = vp->vd.x / uFp+center;
if ( vp->vd.x < 0) vp->vd.x = 0;
else if ( vp->vd.x >= outMesh) vp->vd.x = outMesh-1;
vp->vd.y = vp->vd.y / uFp+center;
if ( vp->vd.y < 0) vp->vd.y = 0;
else if ( vp->vd.y >= outMesh) vp->vd.y = outMesh-1;
}
vhd = vhd->next;
}
RET:
return sts;
}
/***********************************************************************
* Bind same direction vector
*/
/* */ static int
/* */ BindLinears( int inLst, int outLst)
/*
***********************************************************************/
{
struct VHEAD *vhd;
int sts;
struct VDATA *vp;
int np;
struct vecdata rel1, rel2;
VDNew( outLst);
if ( (sts = VDGetHead( inLst, &vhd))!=0)
goto RET;
while ( vhd->next != NIL) {
vp = vhd->headp;
/* Origin */
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
vp = vp->next;
for ( np = 1; np < vhd->nPoints; np++, vp = vp->next) {
if ( np+1 >= vhd->nPoints) {
if ((sts=VDSetData( outLst, &vp->vd))<0)
goto RET;
break;
}
else if ( vp->vd.atr&SPLINE_ATR) {
if ((sts=VDSetData( outLst, &vp->vd))<0)
goto RET;
/* End Point */
vp = vp->next;
np++;
if ( np >= vhd->nPoints)
break;
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
}
else {
rel1.x = vp->next->vd.x - vp->vd.x;
rel1.y = vp->next->vd.y - vp->vd.y;
rel2.x = vp->vd.x - vp->prev->vd.x;
rel2.y = vp->vd.y - vp->prev->vd.y;
if ( (vp->next->vd.atr & SPLINE_ATR )
|| (long)rel1.x*rel2.y != (long)rel1.y*rel2.x) {
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
}
}
}
if ( (sts = VDClose( outLst))<0)
goto RET;
vhd = vhd->next;
}
RET:
return( sts);
}
/***********************************************************************
* Deleate Zero Vector ( about Non Curve Part)
*/
/* */ static int
/* */ DelZeroVec( int inLst, int outLst)
/*
***********************************************************************/
{
struct VHEAD *vhd;
int sts;
struct VDATA *vp;
int np;
VDNew( outLst);
if ( (sts = VDGetHead( inLst, &vhd))!=0)
goto RET;
while ( vhd->next != NIL) {
vp = vhd->headp;
/* Origin */
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
vp = vp->next;
for ( np = 1; np < vhd->nPoints; np++, vp = vp->next) {
if ( vp->vd.atr&SPLINE_ATR) {
/* Control Point */
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
/* End Point */
vp = vp->next;
np++;
if ( np >= vhd->nPoints)
break;
if ( (sts = VDSetData( outLst, &vp->vd))<0)
goto RET;
}
else {
if ( vp->vd.x != vp->prev->vd.x
|| vp->vd.y != vp->prev->vd.y) {
if ((sts=VDSetData( outLst, &vp->vd))<0)
goto RET;
}
}
}
if ( (sts = VDClose( outLst))<0)
goto RET;
vhd = vhd->next;
}
RET:
return( sts);
}
/* X |Y
* O------------ +-|------+
* | | | | |
* | | ---> | | |
* | | -----+-------------X
* |-------+ O-|------+
* |Y |
*/
int
toTTFFrame( int lstH, struct BBX *bbx)
{
struct VHEAD *vhd;
struct VDATA *vp;
int np;
int sts;
short mesh;
if ( (sts = VDGetHead( lstH, &vhd))!=0)
goto RET;
if ( (sts = VDGetNCont( lstH))<=0)
goto RET;
mesh = bbx->xMax - bbx->xMin+1;
if ( mesh > bbx->yMax - bbx->yMin)
mesh = bbx->yMax - bbx->yMin+1;
while ( vhd->next != NIL) {
vp = vhd->headp;
np = vhd->nPoints;
while ( np-->0) {
vp->vd.x += (short)bbx->xMin;
vp->vd.y = (mesh - 1) - vp->vd.y + bbx->yMin;
/* Limit in BBX */
if ( vp->vd.x > bbx->xMax)
vp->vd.x = (short)bbx->xMax;
else if (vp->vd.x < bbx->xMin)
vp->vd.x = (short)bbx->xMin;
if ( vp->vd.y > bbx->yMax)
vp->vd.y = (short)bbx->yMax;
else if (vp->vd.y < bbx->yMin)
vp->vd.y = (short)bbx->yMin;
vp = vp->next;
}
vhd = vhd->next;
}
sts = 0;
RET:
return sts;
}
static int
lightSub( int inLst, int outLst)
{
struct VHEAD *vhd;
int sts;
struct VDATA *svp, *evp;
int sp, ep;
if ( (sts = VDGetHead( inLst, &vhd))!=0)
goto RET;
VDNew( outLst);
while ( vhd->next != NIL) {
svp = vhd->headp;
if ((sp=searchanchor(0,svp,&svp,vhd->nPoints))<vhd->nPoints){
while(sp <vhd->nPoints) {
ep = searchanchor(sp+1, svp->next,&evp, vhd->nPoints);
if ((sts=smooth1sub( svp, ep-sp,outLst,1, 2, 1))<0)
goto RET;
if ( ep >= vhd->nPoints)
break;
sp = ep;
svp = evp;
}
}
vhd = vhd->next;
if ( (sts = VDClose( outLst)) < 0)
break;
}
RET:
return sts;
}
static int
divVec( int ilst, int olst, int divN)
{
struct VHEAD *vhd;
struct VDATA *vp;
struct vecdata rel, vd;
int np;
int n;
if ( VDGetHead( ilst, &vhd)!=0)
goto RET;
VDNew( olst);
while ( vhd->next != NIL) {
vp = vhd->headp;
np = vhd->nPoints;
while ( np-->0) {
if (VDSetData(olst, &vp->vd))
goto RET;
rel.x = vp->next->vd.x - vp->vd.x;
rel.y = vp->next->vd.y - vp->vd.y;
vd.atr = 0;
for ( n=1; n<divN; n++) {
vd.x = vp->vd.x+rel.x*n/divN;
vd.y = vp->vd.y+rel.y*n/divN;
if (VDSetData(olst, &vd))
goto RET;
}
vp = vp->next;
}
vhd = vhd->next;
VDClose( olst);
}
return 0;
RET:
return -1;
}
int
SmoothLight( int ioLst, int tmpLst, int width, int height, int oWidth, int ufpVal)
{
int sts;
if ( (sts = BindPoint( ioLst, tmpLst))<0)
goto RET;
if ( (sts = DetectNoSmooth( tmpLst))<0)
goto RET;
if ( (sts = ZoomPoint( tmpLst, width, height, oWidth, ufpVal))<0)
goto RET;
if ( (sts = preproc1( tmpLst, ioLst))<0)
goto RET;
if ( sts = divVec( ioLst, tmpLst, 2))
goto RET;
if ( lightSub( tmpLst, ioLst))
goto RET;
if ( lightSub( ioLst, tmpLst))
goto RET;
if ( RemoveFp( tmpLst, oWidth, ufpVal))
goto RET;
if ( (sts = DelZeroVec( tmpLst, ioLst))<0)
goto RET;
return 0;
RET:
return -1;
}
int
ConvMesh( int lstH, int inMesh, int outMesh)
{
struct VHEAD *vhd;
struct VDATA *vp;
int np;
int sts;
if ( inMesh==outMesh)
return 0;
if ( (sts = VDGetHead( lstH, &vhd))!=0)
goto RET;
if ( (sts = VDGetNCont( lstH))<=0)
goto RET;
while ( vhd->next != NIL) {
vp = vhd->headp;
np = vhd->nPoints;
while ( np-->0) {
vp->vd.x = (int)((long)vp->vd.x*outMesh/inMesh);
vp->vd.y = (int)((long)vp->vd.y*outMesh/inMesh);
vp = vp->next;
}
vhd = vhd->next;
}
sts = 0;
RET:
return sts;
}
/* EOF */