#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; } }