windows-nt/Source/XPSP1/NT/windows/richedit/lssrc/lstfset.c
2020-09-26 16:20:57 +08:00

155 lines
3.8 KiB
C

#include "lsidefs.h"
#include "lstfset.h"
// %%Function: LsPointUV2FromPointUV1
// %%Contact: victork
//
LSERR WINAPI LsPointUV2FromPointUV1(LSTFLOW lstflow1, /* IN: text flow 1 */
PCPOINTUV pptStart, /* IN: start input point (TF1) */
PCPOINTUV pptEnd, /* IN: end input point (TF1) */
LSTFLOW lstflow2, /* IN: text flow 2 */
PPOINTUV pptOut) /* OUT: vector in TF2 */
{
Assert(lstflowES == 0);
Assert(lstflowEN == 1);
Assert(lstflowSE == 2);
Assert(lstflowSW == 3);
Assert(lstflowWS == 4);
Assert(lstflowWN == 5);
Assert(lstflowNE == 6);
Assert(lstflowNW == 7);
// The three bits that constitute lstflow happens to have well defined meanings.
//
// Middle bit: on for vertical writing, off for horizontal.
// First (low value) bit: "on" means v-axis points right or down (positive).
// Third bit: "off" means u-axis points right or down (positive).
//
// So the algorithm of covertion (u1,v1) in lstflow1 to (u2,v2) in lstflow2 is:
//
// fHorizontalOrVertical1 = lstflow1 & fUVertical;
// fUPositive1 = !(lstflow1 & fUDirection);
// fVPositive1 = lstflow1 & fVDirection;
// fHorizontalOrVertical2 = lstflow2 & fUVertical;
// fUPositive2 = !(lstflow2 & fUDirection);
// fVPositive2 = lstflow2 & fVDirection;
//
//
// if (fHorizontalOrVertical1 == fHorizontalOrVertical2)
// {
// if (fUPositive1 == fUPositive2)
// {
// u2 = u1;
// }
// else
// {
// u2 = -u1;
// }
// if (fVPositive1 == fVPositive2)
// {
// v2 = v1;
// }
// else
// {
// v2 = -v1;
// }
// }
// else
// {
// if (fUPositive1 == fVPositive2)
// {
// u2 = v1;
// }
// else
// {
// u2 = -v1;
// }
// if (fVPositive1 == fUPositive2)
// {
// v2 = u1;
// }
// else
// {
// v2 = -u1;
// }
// }
//
// Actual code is a little bit more compact.
//
// A hack (?): (!a == !b) is used instead of (((a==0) && (b==0)) || ((a!=0) && (b!=0)))
if ((lstflow1 ^ lstflow2) & fUVertical) // one is vertical, another is horizontal
{
pptOut->u = (pptEnd->v - pptStart->v) *
((!(lstflow2 & fUDirection) == !(lstflow1 & fVDirection)) ? -1 : 1);
pptOut->v = (pptEnd->u - pptStart->u) *
((!(lstflow2 & fVDirection) == !(lstflow1 & fUDirection)) ? -1 : 1);
}
else
{
pptOut->u = (pptEnd->u - pptStart->u) *
(((lstflow1 ^ lstflow2) & fUDirection) ? -1 : 1);
pptOut->v = (pptEnd->v - pptStart->v) *
(((lstflow1 ^ lstflow2) & fVDirection) ? -1 : 1);
}
return lserrNone;
}
// %%Function: LsPointXYFromPointUV
// %%Contact: victork
//
/* returns (x,y) point given (x,y) point and (u,v) vector */
LSERR WINAPI LsPointXYFromPointUV(const POINT* pptXY, /* IN: input point (x,y) */
LSTFLOW lstflow, /* IN: text flow for */
PCPOINTUV pptUV, /* IN: vector in (u,v) */
POINT* pptXYOut) /* OUT: point (x,y) */
{
switch (lstflow)
{
case lstflowES: /* latin */
pptXYOut->x = pptXY->x + pptUV->u;
pptXYOut->y = pptXY->y - pptUV->v;
return lserrNone;
case lstflowSW: /* vertical FE */
pptXYOut->x = pptXY->x + pptUV->v;
pptXYOut->y = pptXY->y + pptUV->u;
return lserrNone;
case lstflowWS: /* BiDi */
pptXYOut->x = pptXY->x - pptUV->u;
pptXYOut->y = pptXY->y - pptUV->v;
return lserrNone;
case lstflowEN:
pptXYOut->x = pptXY->x + pptUV->u;
pptXYOut->y = pptXY->y + pptUV->v;
return lserrNone;
case lstflowSE:
pptXYOut->x = pptXY->x - pptUV->v;
pptXYOut->y = pptXY->y + pptUV->u;
return lserrNone;
case lstflowWN:
pptXYOut->x = pptXY->x - pptUV->u;
pptXYOut->y = pptXY->y + pptUV->v;
return lserrNone;
case lstflowNE:
pptXYOut->x = pptXY->x - pptUV->v;
pptXYOut->y = pptXY->y - pptUV->u;
return lserrNone;
case lstflowNW:
pptXYOut->x = pptXY->x + pptUV->v;
pptXYOut->y = pptXY->y - pptUV->u;
return lserrNone;
default:
NotReached();
return lserrInvalidParameter;
}
}