diff --git a/win32ss/gdi/ntgdi/gdifloat.h b/win32ss/gdi/ntgdi/gdifloat.h index 94c590f47d..d0cf0da964 100644 --- a/win32ss/gdi/ntgdi/gdifloat.h +++ b/win32ss/gdi/ntgdi/gdifloat.h @@ -1,22 +1,19 @@ #pragma once -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:28110) // disable "Drivers must protect floating point hardware state" warning -#endif - -typedef struct tagFLOAT_POINT +typedef struct tagFLOATOBJ_POINT { - FLOAT x, y; -} FLOAT_POINT; + FLOATOBJ x, y; +} FLOATOBJ_POINT; /* Rounds a floating point number to integer. The world-to-viewport * transformation process is done in floating point internally. This function * is then used to round these coordinates to integer values. */ -static __inline INT GDI_ROUND(FLOAT val) +static __inline INT GDI_ROUND(FLOATOBJ *val) { - return (int)floor(val + 0.5); + FLOATOBJ e1 = FLOATOBJ_1_2; + FLOATOBJ_Add(&e1, val); + return FLOATOBJ_GetLong(&e1); } @@ -24,8 +21,36 @@ static __inline INT GDI_ROUND(FLOAT val) * Performs a world-to-viewport transformation on the specified point (which * is in floating point format). */ -static __inline void INTERNAL_LPTODP_FLOAT(DC *dc, FLOAT_POINT *point) +static __inline void INTERNAL_LPTODP_FLOAT(DC *dc, FLOATOBJ_POINT *point) { +#if 1 + FLOATOBJ x, y, e1, e2; + XFORMOBJ xo; + XFORML xform; + + XFORMOBJ_vInit(&xo, &dc->pdcattr->mxWorldToDevice); + XFORMOBJ_iGetXform(&xo, &xform); + + /* Perform the transformation */ + e1 = point->x; + FLOATOBJ_MulFloat(&e1, xform.eM11); + e2 = point->y; + FLOATOBJ_MulFloat(&e2, xform.eM21); + FLOATOBJ_Add(&e1, &e2); + FLOATOBJ_AddFloat(&e1, xform.eDx); + x = e1; + + e1 = point->x; + FLOATOBJ_MulFloat(&e1, xform.eM12); + e2 = point->y; + FLOATOBJ_MulFloat(&e2, xform.eM22); + FLOATOBJ_Add(&e1, &e2); + FLOATOBJ_AddFloat(&e1, xform.eDy); + y = e1; + + point->x = x; + point->y = y; +#else FLOAT x, y; XFORM xformWorld2Vport; @@ -41,6 +66,7 @@ static __inline void INTERNAL_LPTODP_FLOAT(DC *dc, FLOAT_POINT *point) point->y = x * xformWorld2Vport.eM12 + y * xformWorld2Vport.eM22 + xformWorld2Vport.eDy; +#endif } /* Performs a viewport-to-world transformation on the specified point (which @@ -104,7 +130,3 @@ static __inline void INTERNAL_LPTODP(DC *dc, LPPOINT point) MulDiv((tx), (pdcattr)->szlViewportExt.cx, (pdcattr)->szlWindowExt.cx) #define YLSTODS(pdcattr,ty) \ MulDiv((ty), (pdcattr)->szlViewportExt.cy, (pdcattr)->szlWindowExt.cy) - -#ifdef _MSC_VER -#pragma warning(pop) -#endif diff --git a/win32ss/gdi/ntgdi/path.c b/win32ss/gdi/ntgdi/path.c index 4a5277a9fe..a05197de8a 100644 --- a/win32ss/gdi/ntgdi/path.c +++ b/win32ss/gdi/ntgdi/path.c @@ -11,6 +11,7 @@ #include #include +#include FT_TRIGONOMETRY_H #define NDEBUG #include @@ -362,16 +363,47 @@ PATH_ReserveEntries( VOID FASTCALL PATH_ScaleNormalizedPoint( - FLOAT_POINT corners[], - double x, - double y, + FLOATOBJ_POINT corners[], + FLOATOBJ *x, + FLOATOBJ *y, POINT *pPoint) { +#if 1 + FLOATOBJ e1, e2, e3; + FLOATOBJ half = FLOATOBJ_1_2; + +#endif ASSERT(corners); ASSERT(pPoint); +#if 1 + e2 = corners[1].x; + e3 = corners[0].x; + FLOATOBJ_Sub(&e2, &e3); + FLOATOBJ_Mul(&e2, &half); + e3 = x; + FLOATOBJ_AddLong(&e3, 1); + FLOATOBJ_Mul(&e3, &half); + FLOATOBJ_Mul(&e2, &e3); + e1 = corners[0].x; + FLOATOBJ_Add(&e1, &e2); + pPoint->x = GDI_ROUND(&e1); + + e2 = corners[1].y; + e3 = corners[0].y; + FLOATOBJ_Sub(&e2, &e3); + FLOATOBJ_Mul(&e2, &half); + e3 = y; + FLOATOBJ_AddLong(&e3, 1); + FLOATOBJ_Mul(&e3, &half); + FLOATOBJ_Mul(&e2, &e3); + e1 = corners[0].y; + FLOATOBJ_Add(&e1, &e2); + pPoint->y = GDI_ROUND(&e1); +#else pPoint->x = GDI_ROUND((double)corners[0].x + (double)(corners[1].x - corners[0].x) * 0.5 * (x + 1.0)); pPoint->y = GDI_ROUND((double)corners[0].y + (double)(corners[1].y - corners[0].y) * 0.5 * (y + 1.0)); +#endif } /* PATH_NormalizePoint @@ -670,11 +702,19 @@ PATH_RoundRect( INT ell_width, INT ell_height) { +#if 1 + const FLOATOBJ factor = ...; +#else const double factor = 0.55428475; /* 4 / 3 * (sqrt(2) - 1) */ +#endif PPATH pPath; POINT corners[2], ellipse[2], points[16]; BYTE *type; +#if 1 double width, height; +#else + FLOATOBJ width, height, e1, e2; +#endif if (!ell_width || !ell_height) return PATH_Rectangle( dc, x1, y1, x2, y2 ); @@ -693,9 +733,68 @@ PATH_RoundRect( IntLPtoDP( dc, &ellipse, 2 ); ell_width = min( abs( ellipse[1].x - ellipse[0].x ), corners[1].x - corners[0].x ); ell_height = min( abs( ellipse[1].y - ellipse[0].y ), corners[1].y - corners[0].y ); +#if 1 + FLOATOBJ_SetLong(&width, ell_width); + FLOATOBJ_DivLong(&width, 2); + FLOATOBJ_SetLong(&height, ell_height); + FLOATOBJ_DivLong(&height, 2); +#else width = ell_width / 2.0; height = ell_height / 2.0; +#endif +#if 1 + FLOATOBJ_Set1(&e1); + FLOATOBJ_Sub(&e1, factor); + FLOATOBJ_Mul(&e1, width); + + FLOATOBJ_Set1(&e2); + FLOATOBJ_Sub(&e2, factor); + FLOATOBJ_Mul(&e2, height); +#endif + +#if 1 + /* starting point */ + points[0].x = corners[1].x; + points[0].y = corners[0].y + GDI_ROUND( &height ); + /* first curve */ + points[1].x = corners[1].x; + points[1].y = corners[0].y + GDI_ROUND( &e2 ); + points[2].x = corners[1].x - GDI_ROUND( &e1 ); + points[2].y = corners[0].y; + points[3].x = corners[1].x - GDI_ROUND( &width ); + points[3].y = corners[0].y; + /* horizontal line */ + points[4].x = corners[0].x + GDI_ROUND( &width ); + points[4].y = corners[0].y; + /* second curve */ + points[5].x = corners[0].x + GDI_ROUND( &e1 ); + points[5].y = corners[0].y; + points[6].x = corners[0].x; + points[6].y = corners[0].y + GDI_ROUND( &e2 ); + points[7].x = corners[0].x; + points[7].y = corners[0].y + GDI_ROUND( &height ); + /* vertical line */ + points[8].x = corners[0].x; + points[8].y = corners[1].y - GDI_ROUND( &height ); + /* third curve */ + points[9].x = corners[0].x; + points[9].y = corners[1].y - GDI_ROUND( &e2 ); + points[10].x = corners[0].x + GDI_ROUND( &e1 ); + points[10].y = corners[1].y; + points[11].x = corners[0].x + GDI_ROUND( &width ); + points[11].y = corners[1].y; + /* horizontal line */ + points[12].x = corners[1].x - GDI_ROUND( &width ); + points[12].y = corners[1].y; + /* fourth curve */ + points[13].x = corners[1].x - GDI_ROUND( &e1 ); + points[13].y = corners[1].y; + points[14].x = corners[1].x; + points[14].y = corners[1].y - GDI_ROUND( &e2 ); + points[15].x = corners[1].x; + points[15].y = corners[1].y - GDI_ROUND( &height ); +#else /* starting point */ points[0].x = corners[1].x; points[0].y = corners[0].y + GDI_ROUND( height ); @@ -736,6 +835,7 @@ PATH_RoundRect( points[14].y = corners[1].y - GDI_ROUND( height * (1 - factor) ); points[15].x = corners[1].x; points[15].y = corners[1].y - GDI_ROUND( height ); +#endif if (dc->dclevel.flPath & DCPATH_CLOCKWISE) reverse_points( points, 16 ); if (!(type = add_points( pPath, points, 16, PT_BEZIERTO ))) @@ -763,11 +863,19 @@ PATH_Ellipse( INT x2, INT y2) { +#if 1 + const FLOATOBJ factor = ...; +#else const double factor = 0.55428475; /* 4 / 3 * (sqrt(2) - 1) */ +#endif PPATH pPath; POINT corners[2], points[13]; BYTE *type; +#if 1 + FLOATOBJ width, height, e1, e2; +#else double width, height; +#endif pPath = PATH_LockPath(dc->dclevel.hPath); if (!pPath) return FALSE; @@ -778,9 +886,63 @@ PATH_Ellipse( return TRUE; } +#if 1 + width = corners[1].x; + FLOATOBJ_Sub(&width, corners[0].x); + FLOATOBJ_DivLong(&width, 2); + + height = corners[1].y; + FLOATOBJ_Sub(&height, corners[0].y); + FLOATOBJ_DivLong(&height, 2); + +#else width = (corners[1].x - corners[0].x) / 2.0; height = (corners[1].y - corners[0].y) / 2.0; +#endif + +#if 1 + FLOATOBJ_Set1(&e1); + FLOATOBJ_Sub(&e1, factor); + FLOATOBJ_Mul(&e1, width); + FLOATOBJ_Set1(&e2); + FLOATOBJ_Sub(&e2, factor); + FLOATOBJ_Mul(&e2, height); +#endif + +#if 1 + /* starting point */ + points[0].x = corners[1].x; + points[0].y = corners[0].y + GDI_ROUND( &height ); + /* first curve */ + points[1].x = corners[1].x; + points[1].y = corners[0].y + GDI_ROUND( &e2 ); + points[2].x = corners[1].x - GDI_ROUND( &e1 ); + points[2].y = corners[0].y; + points[3].x = corners[0].x + GDI_ROUND( &width ); + points[3].y = corners[0].y; + /* second curve */ + points[4].x = corners[0].x + GDI_ROUND( &e1 ); + points[4].y = corners[0].y; + points[5].x = corners[0].x; + points[5].y = corners[0].y + GDI_ROUND( &e2 ); + points[6].x = corners[0].x; + points[6].y = corners[0].y + GDI_ROUND( &height ); + /* third curve */ + points[7].x = corners[0].x; + points[7].y = corners[1].y - GDI_ROUND( &e2 ); + points[8].x = corners[0].x + GDI_ROUND( &e1 ); + points[8].y = corners[1].y; + points[9].x = corners[0].x + GDI_ROUND( &width ); + points[9].y = corners[1].y; + /* fourth curve */ + points[10].x = corners[1].x - GDI_ROUND( &e1 ); + points[10].y = corners[1].y; + points[11].x = corners[1].x; + points[11].y = corners[1].y - GDI_ROUND( &e2 ); + points[12].x = corners[1].x; + points[12].y = corners[1].y - GDI_ROUND( &height ); +#else /* starting point */ points[0].x = corners[1].x; points[0].y = corners[0].y + GDI_ROUND( height ); @@ -812,6 +974,7 @@ PATH_Ellipse( points[11].y = corners[1].y - GDI_ROUND( height * (1 - factor) ); points[12].x = corners[1].x; points[12].y = corners[1].y - GDI_ROUND( height ); +#endif if (dc->dclevel.flPath & DCPATH_CLOCKWISE) reverse_points( points, 13 ); if (!(type = add_points( pPath, points, 13, PT_BEZIERTO ))) @@ -827,6 +990,23 @@ PATH_Ellipse( return TRUE; } +static void FASTCALL +FLOATOBJ_AngleSinCos(FLOATOBJ *psin, FLOATOBJ *pcos, const FLOATOBJ *angle) +{ + FT_Angle a; + FLOATOBJ e; + FT_Vector vec; + + e = angle; + FLOATOBJ_MulLong(&e, 1 << 16); + FT_Vector_Unit(&vec, FLOATOBJ_GetLong(&e)); + + FLOATOBJ_SetLong(psin, vec.x); + FLOATOBJ_SetLong(pcos, vec.y); + FLOATOBJ_DivLong(psin, 1 << 16); + FLOATOBJ_DivLong(pcos, 1 << 16); +} + /* PATH_DoArcPart * * Creates a Bezier spline that corresponds to part of an arc and appends the @@ -841,12 +1021,17 @@ FASTCALL PATH_DoArcPart( PPATH pPath, FLOAT_POINT corners[], - double angleStart, - double angleEnd, + FLOATOBJ *angleStart, + FLOATOBJ *angleEnd, BYTE startEntryType) { +#if 1 + FLOATOBJ halfAngle, a, e1, e2, e3, halfSin, halfCos; + FLOATOBJ xNorm[4], yNorm[4]; +#else double halfAngle, a; double xNorm[4], yNorm[4]; +#endif POINT points[4]; BYTE *type; int i, start; @@ -856,6 +1041,59 @@ PATH_DoArcPart( /* FIXME: Is there an easier way of computing this? */ /* Compute control points */ +#if 1 + halfAngle = *angleEnd; + FLOATOBJ_Div(&halfAngle, angleStart); + FLOATOBJ_DivLong(&halfAngle, 2); + if (...) + { + //a = 4.0 / 3.0 * (1 - cos(halfAngle)) / sin(halfAngle); + FLOATOBJ_AngleSinCos(&halfSin, &halfCos, &halfAngle); + FLOATOBJ_SetLong(&a, 4); + FLOATOBJ_SetLong(&e2, 3); + FLOATOBJ_Div(&a, &e2); + FLOATOBJ_Set1(&e3); + FLOATOBJ_Sub(&e3, halfCos); + FLOATOBJ_Mul(&a, &e3); + FLOATOBJ_Div(&a, &halfSin); + + //xNorm[0] = cos(angleStart); + //yNorm[0] = sin(angleStart); + FLOATOBJ_AngleSinCos(&xNorm[0], &yNorm[0], angleStart); + + //xNorm[1] = xNorm[0] - a * yNorm[0]; + e1 = yNorm[0]; + FLOATOBJ_Mul(&e1, &a); + e2 = xNorm[0]; + FLOATOBJ_Sub(&e2, e1); + xNorm[1] = e2; + + //yNorm[1] = yNorm[0] + a * xNorm[0]; + e1 = xNorm[0]; + FLOATOBJ_Mul(&e1, &a); + e2 = yNorm[0]; + FLOATOBJ_Add(&e2, e1); + yNorm[1] = e2; + + //xNorm[3] = cos(angleEnd); + //yNorm[3] = sin(angleEnd); + FLOATOBJ_AngleSinCos(&xNorm[3], &yNorm[3], angleEnd); + + //xNorm[2] = xNorm[3] + a * yNorm[3]; + e1 = yNorm[3]; + FLOATOBJ_Mul(&e1, &a); + e2 = xNorm[3]; + FLOATOBJ_Sub(&e2, e1); + xNorm[2] = e2; + + //yNorm[2] = yNorm[3] - a * xNorm[3]; + e1 = xNorm[3]; + FLOATOBJ_Mul(&e1, &a); + e2 = yNorm[3]; + FLOATOBJ_Add(&e2, e1); + yNorm[2] = e2; + } +#else halfAngle = (angleEnd - angleStart) / 2.0; if (fabs(halfAngle) > 1e-8) { @@ -875,6 +1113,7 @@ PATH_DoArcPart( xNorm[i] = cos(angleStart); yNorm[i] = sin(angleStart); } +#endif /* Add starting point to path if desired */ start = !startEntryType; @@ -912,18 +1151,32 @@ PATH_Arc( INT direction, INT lines) { +#if 1 + FLOATOBJ angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant; + /* Initialize angleEndQuadrant to silence gcc's warning */ + FLOATOBJ x, y; + FLOATOBJ_POINT corners[2], pointStart, pointEnd; + FLOATOBJ fullAngle = ... 2 * M_PI ...; + FLOATOBJ halfPi = ... M_PI_2 ...; +#else double angleStart, angleEnd, angleStartQuadrant, angleEndQuadrant = 0.0; /* Initialize angleEndQuadrant to silence gcc's warning */ double x, y; FLOAT_POINT corners[2], pointStart, pointEnd; +#endif POINT centre, pointCurPos; BOOL start, end, Ret = TRUE; +#if 1 + FLOATOBJ temp; +#else INT temp; +#endif BOOL clockwise; PPATH pPath; /* FIXME: This function should check for all possible error returns */ /* FIXME: Do we have to respect newStroke? */ + FLOATOBJ_Set0(&angleEndQuadrant); ASSERT(dc); @@ -943,6 +1196,16 @@ PATH_Arc( goto ArcExit; } /* Convert points to device coordinates */ +#if 1 + FLOATOBJ_SetLong(&corners[0].x, x1); + FLOATOBJ_SetLong(&corners[0].y, y1); + FLOATOBJ_SetLong(&corners[1].x, x2); + FLOATOBJ_SetLong(&corners[1].y, y2); + FLOATOBJ_SetLong(&pointStart.x, xStart); + FLOATOBJ_SetLong(&pointStart.y, yStart); + FLOATOBJ_SetLong(&pointEnd.x, xEnd); + FLOATOBJ_SetLong(&pointEnd.y, yEnd); +#else corners[0].x = (FLOAT)x1; corners[0].y = (FLOAT)y1; corners[1].x = (FLOAT)x2; @@ -951,6 +1214,7 @@ PATH_Arc( pointStart.y = (FLOAT)yStart; pointEnd.x = (FLOAT)xEnd; pointEnd.y = (FLOAT)yEnd; +#endif INTERNAL_LPTODP_FLOAT(dc, corners); INTERNAL_LPTODP_FLOAT(dc, corners + 1); INTERNAL_LPTODP_FLOAT(dc, &pointStart); @@ -971,17 +1235,27 @@ PATH_Arc( } /* Compute start and end angle */ +#if 1 + PATH_NormalizePoint(corners, &pointStart, &x, &y); + FLOATOBJ_SetLong(&angleStart, FT_Atan2(x << 16, y << 16)); + FLOATOBJ_DivLong(&angleStart, 1 << 16); + PATH_NormalizePoint(corners, &pointEnd, &x, &y); + FLOATOBJ_SetLong(&angleEnd, FT_Atan2(x << 16, y << 16)); + FLOATOBJ_DivLong(&angleEnd, 1 << 16); +#else PATH_NormalizePoint(corners, &pointStart, &x, &y); angleStart = atan2(y, x); PATH_NormalizePoint(corners, &pointEnd, &x, &y); angleEnd = atan2(y, x); +#endif /* Make sure the end angle is "on the right side" of the start angle */ if (clockwise) { if (angleEnd <= angleStart) { - angleEnd += 2 * M_PI; + //angleEnd += 2 * M_PI; + FLOATOBJ_Add(&angleEnd, &fullAngle); ASSERT(angleEnd >= angleStart); } } @@ -989,7 +1263,8 @@ PATH_Arc( { if (angleEnd >= angleStart) { - angleEnd -= 2 * M_PI; + // angleEnd -= 2 * M_PI; + FLOATOBJ_Sub(&angleEnd, &fullAngle); ASSERT(angleEnd <= angleStart); } } @@ -997,8 +1272,13 @@ PATH_Arc( /* In GM_COMPATIBLE, don't include bottom and right edges */ if (dc->pdcattr->iGraphicsMode == GM_COMPATIBLE) { +#if 1 + FLOATOBJ_SubLong(&corners[1].x, 1); + FLOATOBJ_SubLong(&corners[1].y, 1); +#else corners[1].x--; corners[1].y--; +#endif } /* arcto: Add a PT_MOVETO only if this is the first entry in a stroke */ @@ -1025,20 +1305,50 @@ PATH_Arc( { angleStartQuadrant = angleStart; if (clockwise) - angleEndQuadrant = (floor(angleStart / M_PI_2) + 1.0) * M_PI_2; + { + //angleEndQuadrant = (floor(angleStart / M_PI_2) + 1.0) * M_PI_2; + e1 = angleStart; + FLOATOBJ_Div(&e1, &halfPi); + FLOATOBJ_AddLong(&e1, 1); + FLOATOBJ_SetLong(&e1, FLOATOBJ_GetLong(&e1)); + FLOATOBJ_Mul(&e1, &halfPi); + angleEndQuadrant = e1; + } else - angleEndQuadrant = (ceil(angleStart / M_PI_2) - 1.0) * M_PI_2; + { + //angleEndQuadrant = (ceil(angleStart / M_PI_2) - 1.0) * M_PI_2; + e1 = angleStart; + FLOATOBJ_Div(&e1, &halfPi); + FLOATOBJ_SubLong(&e1, 1); + FLOATOBJ_SetLong(&e1, -FLOATOBJ_GetLong(&e1)); + FLOATOBJ_Neg(&e1); + FLOATOBJ_Mul(&e1, &halfPi); + angleEndQuadrant = e1; + } } else { angleStartQuadrant = angleEndQuadrant; + //if (clockwise) + // angleEndQuadrant += M_PI_2; + //else + // angleEndQuadrant -= M_PI_2; if (clockwise) - angleEndQuadrant += M_PI_2; + FLOATOBJ_Add(&angleEndQuadrant, &halfPi); else - angleEndQuadrant -= M_PI_2; + FLOATOBJ_Sub(&angleEndQuadrant, &halfPi); } /* Have we reached the last part of the arc? */ +#if 1 + if ((clockwise && FLOATOBJ_LessThan(&angleEnd, &angleEndQuadrant)) || + (!clockwise && FLOATOBJ_GreaterThan(&angleEnd, &angleEndQuadrant))) + { + /* Adjust the end angle for this quadrant */ + angleEndQuadrant = angleEnd; + end = TRUE; + } +#else if ((clockwise && angleEnd < angleEndQuadrant) || (!clockwise && angleEnd > angleEndQuadrant)) { @@ -1046,6 +1356,7 @@ PATH_Arc( angleEndQuadrant = angleEnd; end = TRUE; } +#endif /* Add the Bezier spline to the path */ PATH_DoArcPart(pPath, @@ -1727,6 +2038,7 @@ IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit) PPATH flat_path, pNewPath, *pStrokes = NULL, *pOldStrokes, pUpPath, pDownPath; BYTE *type; DWORD joint, endcap; + FLOATOBJ e1, e2, e3; endcap = (PS_ENDCAP_MASK & penStyle); joint = (PS_JOIN_MASK & penStyle); @@ -1835,6 +2147,37 @@ IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit) if ((!(pStrokes[i]->pFlags[pStrokes[i]->numEntriesUsed - 1] & PT_CLOSEFIGURE)) && (j == 0 || j == pStrokes[i]->numEntriesUsed - 1)) { /* Compute segment angle */ +#if 1 + FLOATOBJ xo, yo, xa, ya, theta, eSin, eCos; + POINT pt; + FLOATOBJ_POINT corners[2]; + LONG n; + if (j == 0) + { + FLOATOBJ_SetLong(&xo, pStrokes[i]->pPoints[j].x); + FLOATOBJ_SetLong(&yo, pStrokes[i]->pPoints[j].y); + FLOATOBJ_SetLong(&xa, pStrokes[i]->pPoints[1].x); + FLOATOBJ_SetLong(&ya, pStrokes[i]->pPoints[1].y); + } + else + { + FLOATOBJ_SetLong(&xa, pStrokes[i]->pPoints[j - 1].x); + FLOATOBJ_SetLong(&ya, pStrokes[i]->pPoints[j - 1].y); + FLOATOBJ_SetLong(&xo, pStrokes[i]->pPoints[j].x); + FLOATOBJ_SetLong(&yo, pStrokes[i]->pPoints[j].y); + } + e1 = xa; + e2 = xo; + FLOATOBJ_Sub(&e1, &e2); + FLOATOBJ_MulLong(&e1, 1 << 16); + e2 = ya; + e3 = yo; + FLOATOBJ_Sub(&e2, &e3); + FLOATOBJ_MulLong(&e2, 1 << 16); + n = FT_Atan2(FLOATOBJ_GetLong(&e1), FLOATOBJ_GetLong(&e2)); + FLOATOBJ_SetLong(&theta, n); + FLOATOBJ_DivLong(&theta, 1 << 16); +#else double xo, yo, xa, ya, theta; POINT pt; FLOAT_POINT corners[2]; @@ -1853,26 +2196,153 @@ IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit) yo = pStrokes[i]->pPoints[j].y; } theta = atan2(ya - yo, xa - xo); +#endif switch(endcap) { case PS_ENDCAP_SQUARE : +#if 1 + //pt.x = xo + round(sqrt(2) * penWidthOut * cos(M_PI_4 + theta)); + //pt.y = yo + round(sqrt(2) * penWidthOut * sin(M_PI_4 + theta)); + e1 = quadPi; + FLOATOBJ_Add(&e1, &theta); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = sqrt2; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Mul(&e1, &eCos); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = sqrt2; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Mul(&e1, &eSin); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.y = FLOATOBJ_GetLong(&e2); + + PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO)); + + //pt.x = xo + round(sqrt(2) * penWidthIn * cos(- M_PI_4 + theta)); + //pt.y = yo + round(sqrt(2) * penWidthIn * sin(- M_PI_4 + theta)); + e1 = quadPi; + FLOATOBJ_Neg(&e1); + FLOATOBJ_Add(&e1, &theta); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = sqrt2; + FLOATOBJ_MulLong(&e1, penWidthIn); + FLOATOBJ_Mul(&e1, &eCos); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = sqrt2; + FLOATOBJ_MulLong(&e1, penWidthIn); + FLOATOBJ_Mul(&e1, &eSin); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.y = FLOATOBJ_GetLong(&e2); +#else pt.x = xo + round(sqrt(2) * penWidthOut * cos(M_PI_4 + theta)); pt.y = yo + round(sqrt(2) * penWidthOut * sin(M_PI_4 + theta)); PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO)); pt.x = xo + round(sqrt(2) * penWidthIn * cos(- M_PI_4 + theta)); pt.y = yo + round(sqrt(2) * penWidthIn * sin(- M_PI_4 + theta)); PATH_AddEntry(pUpPath, &pt, PT_LINETO); +#endif break; case PS_ENDCAP_FLAT : +#if 1 + //pt.x = xo + round(penWidthOut * cos(theta + M_PI_2)); + //pt.y = yo + round(penWidthOut * sin(theta + M_PI_2)); + e1 = halfPi; + FLOATOBJ_Add(&e1, &theta); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + FLOATOBJ_SetLong(&e1, penWidthOut); + FLOATOBJ_Mul(&e1, &eCos); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&e2); + FLOATOBJ_SetLong(&e1, penWidthOut); + FLOATOBJ_Mul(&e1, &eSin); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &yo); + pt.y = FLOATOBJ_GetLong(&e2); + + PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO)); + + //pt.x = xo - round(penWidthIn * cos(theta + M_PI_2)); + //pt.y = yo - round(penWidthIn * sin(theta + M_PI_2)); + e1 = halfPi; + FLOATOBJ_Add(&e1, &theta); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + FLOATOBJ_SetLong(&e1, penWidthIn); + FLOATOBJ_Mul(&e1, &eCos); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Neg(&e2); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&e2); + FLOATOBJ_SetLong(&e1, penWidthIn); + FLOATOBJ_Mul(&e1, &eSin); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Neg(&e2); + FLOATOBJ_Add(&e2, &xo); + pt.y = FLOATOBJ_GetLong(&e2); + + PATH_AddEntry(pUpPath, &pt, PT_LINETO); +#else pt.x = xo + round(penWidthOut * cos(theta + M_PI_2)); pt.y = yo + round(penWidthOut * sin(theta + M_PI_2)); PATH_AddEntry(pUpPath, &pt, (j == 0 ? PT_MOVETO : PT_LINETO)); pt.x = xo - round(penWidthIn * cos(theta + M_PI_2)); pt.y = yo - round(penWidthIn * sin(theta + M_PI_2)); PATH_AddEntry(pUpPath, &pt, PT_LINETO); +#endif break; case PS_ENDCAP_ROUND : default : +#if 1 + //corners[0].x = xo - penWidthIn; + corners[0].x = xo; + FLOATOBJ_SubLong(&corners[0].x, penWidthIn); + + //corners[0].y = yo - penWidthIn; + corners[0].y = yo; + FLOATOBJ_SubLong(&corners[0].y, penWidthIn); + + //corners[1].x = xo + penWidthOut; + corners[1].x = xo; + FLOATOBJ_SubLong(&corners[1].x, penWidthIn); + + //corners[1].y = yo + penWidthOut; + corners[1].y = yo; + FLOATOBJ_SubLong(&corners[1].y, penWidthIn); + + //PATH_DoArcPart(pUpPath , corners, theta + M_PI_2 , theta + 3 * M_PI_4, (j == 0 ? PT_MOVETO : FALSE)); + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + e3 = quadPi; + FLOATOBJ_Mul(&e3, 3); + e2 = theta; + FLOATOBJ_Add(&e2, &e3); + PATH_DoArcPart(pUpPath , corners, &e1, &e2, (j == 0 ? PT_MOVETO : FALSE)); + + //PATH_DoArcPart(pUpPath , corners, theta + 3 * M_PI_4 , theta + M_PI, FALSE); + e1 = theta; + FLOATOBJ_Add(&e1, &pi); + PATH_DoArcPart(pUpPath , corners, &e2, &e1, FALSE); + + //PATH_DoArcPart(pUpPath , corners, theta + M_PI, theta + 5 * M_PI_4, FALSE); + e3 = quadPi; + FLOATOBJ_Mul(&e3, 5); + e2 = theta; + FLOATOBJ_Add(&e2, &e3); + PATH_DoArcPart(pUpPath , corners, &e1, &e2, FALSE); + + //PATH_DoArcPart(pUpPath , corners, theta + 5 * M_PI_4 , theta + 3 * M_PI_2, FALSE); + e3 = quadPi; + FLOATOBJ_Mul(&e3, 3); + e1 = theta; + FLOATOBJ_Add(&e1, &e3); + PATH_DoArcPart(pUpPath , corners, &e2, &e1, FALSE); +#else corners[0].x = xo - penWidthIn; corners[0].y = yo - penWidthIn; corners[1].x = xo + penWidthOut; @@ -1881,6 +2351,7 @@ IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit) PATH_DoArcPart(pUpPath , corners, theta + 3 * M_PI_4 , theta + M_PI, FALSE); PATH_DoArcPart(pUpPath , corners, theta + M_PI, theta + 5 * M_PI_4, FALSE); PATH_DoArcPart(pUpPath , corners, theta + 5 * M_PI_4 , theta + 3 * M_PI_2, FALSE); +#endif break; } } @@ -1889,8 +2360,13 @@ IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit) { /* Compute angle */ INT previous, next; +#if 1 + FLOATOBJ xa, ya, xb, yb, xo, yo, e1, e2; + FLOATOBJ alpha, theta, miterWidth; +#else double xa, ya, xb, yb, xo, yo; double alpha, theta, miterWidth; +#endif DWORD _joint = joint; POINT pt; PPATH pInsidePath, pOutsidePath; @@ -1915,15 +2391,35 @@ IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit) ya = pStrokes[i]->pPoints[previous].y; xb = pStrokes[i]->pPoints[next].x; yb = pStrokes[i]->pPoints[next].y; +#if 1 + e1 = xo; + FLOATOBJ_Sub(&e1, &xa); + FLOATOBJ_Mul(&e1, 1 << 16); + e2 = yo; + FLOATOBJ_Sub(&e2, &ya); + FLOATOBJ_Mul(&e2, 1 << 16); + theta = FT_Atan2(&e1, &e2); + FLOATOBJ_DivLong(&theta, 1 << 16); + if (FLOATOBJ_GreaterThan(&alpha, &zero)) + FLOATOBJ_Sub(&alpha, &pi); + else + FLOATOBJ_Add(&alpha, &pi); +#else + theta = atan2(yo - ya, xo - xa); alpha = atan2(yb - yo, xb - xo) - theta; if (alpha > 0) alpha -= M_PI; else alpha += M_PI; +#endif if (_joint == PS_JOIN_MITER && eMiterLimit < fabs(1 / sin(alpha / 2))) { _joint = PS_JOIN_BEVEL; } +#if 1 + if (FLOATOBJ_GreaterThan(&alpha, &zero)) +#else if (alpha > 0) +#endif { pInsidePath = pUpPath; pOutsidePath = pDownPath; @@ -1938,6 +2434,48 @@ IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit) continue; } /* Inside angle points */ +#if 1 + if (FLOATOBJ_GreaterThan(&alpha, &zero)) + { + //pt.x = xo - round(penWidthIn * cos(theta + M_PI_2)); + //pt.y = yo - round(penWidthIn * sin(theta + M_PI_2)); + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e2 = eCos; + FLOATOBJ_MulLong(&e2, penWidthIn); + FLOATOBJ_Round(&e3, &e2); + e1 = xo; + FLOATOBJ_Sub(&e1, &e3); + pt.x = FLOATOBJ_GetLong(&e1); + e2 = eSin; + FLOATOBJ_MulLong(&e2, penWidthIn); + FLOATOBJ_Round(&e3, &e2); + e1 = xo; + FLOATOBJ_Sub(&e1, &e3); + pt.x = FLOATOBJ_GetLong(&e1); + } + else + { + //pt.x = xo + round(penWidthIn * cos(theta + M_PI_2)); + //pt.y = yo + round(penWidthIn * sin(theta + M_PI_2)); + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e2 = eCos; + FLOATOBJ_MulLong(&e2, penWidthIn); + FLOATOBJ_Round(&e3, &e2); + e1 = xo; + FLOATOBJ_Add(&e1, &e3); + pt.x = FLOATOBJ_GetLong(&e1); + e2 = eSin; + FLOATOBJ_MulLong(&e2, penWidthIn); + FLOATOBJ_Round(&e3, &e2); + e1 = xo; + FLOATOBJ_Add(&e1, &e3); + pt.x = FLOATOBJ_GetLong(&e1); + } +#else if (alpha > 0) { pt.x = xo - round(penWidthIn * cos(theta + M_PI_2)); @@ -1948,6 +2486,7 @@ IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit) pt.x = xo + round(penWidthIn * cos(theta + M_PI_2)); pt.y = yo + round(penWidthIn * sin(theta + M_PI_2)); } +#endif PATH_AddEntry(pInsidePath, &pt, PT_LINETO); if (alpha > 0) { @@ -1964,60 +2503,259 @@ IntGdiWidenPath(PPATH pPath, UINT penWidth, UINT penStyle, FLOAT eMiterLimit) switch(_joint) { case PS_JOIN_MITER : +#if 1 + FLOATOBJ_Abs(&e2, alpha); + FLOATOBJ_DivLong(&e2, 2); + e1 = halfPi; + FLOATOBJ_Sub(&e1, &e2); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + FLOATOBJ_SetLong(&e1, penWidthOut); + FLOATOBJ_Div(&e1, &eCos); + FLOATOBJ_Abs(&miterWidth, &e1); + e1 = alpha; + FLOATOBJ_DivLong(&e1, 2); + FLOATOBJ_Add(&e1, &theta); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + FLOATOBJ_SetLong(&e1, miterWidth); + FLOATOBJ_Mul(&e1, &eCos); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&x2); + FLOATOBJ_SetLong(&e1, miterWidth); + FLOATOBJ_Mul(&e1, &eSin); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &yo); + pt.y = FLOATOBJ_GetLong(&x2); +#else miterWidth = fabs(penWidthOut / cos(M_PI_2 - fabs(alpha) / 2)); pt.x = xo + round(miterWidth * cos(theta + alpha / 2)); pt.y = yo + round(miterWidth * sin(theta + alpha / 2)); +#endif PATH_AddEntry(pOutsidePath, &pt, PT_LINETO); break; case PS_JOIN_BEVEL : +#if 1 + if (FLOATOBJ_GreaterThan0(&alpha)) +#else if (alpha > 0) +#endif { +#if 1 + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = eCos; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = eSin; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.y = FLOATOBJ_GetLong(&e2); +#else pt.x = xo + round(penWidthOut * cos(theta + M_PI_2)); pt.y = yo + round(penWidthOut * sin(theta + M_PI_2)); +#endif } else { +#if 1 + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = eCos; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Sub(&e2, &xo); + FLOATOBJ_Neg(&e2); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = eSin; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Sub(&e2, &xo); + FLOATOBJ_Neg(&e2); + pt.y = FLOATOBJ_GetLong(&e2); +#else pt.x = xo - round(penWidthOut * cos(theta + M_PI_2)); pt.y = yo - round(penWidthOut * sin(theta + M_PI_2)); +#endif } PATH_AddEntry(pOutsidePath, &pt, PT_LINETO); +#if 1 + if (FLOATOBJ_GreaterThan0(&alpha)) +#else if (alpha > 0) +#endif { +#if 1 + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_Add(&e1, &alpha); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = eCos; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Sub(&e2, &xo); + FLOATOBJ_Neg(&e2); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = eSin; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Sub(&e2, &xo); + FLOATOBJ_Neg(&e2); + pt.y = FLOATOBJ_GetLong(&e2); +#else pt.x = xo - round(penWidthOut * cos(M_PI_2 + alpha + theta)); pt.y = yo - round(penWidthOut * sin(M_PI_2 + alpha + theta)); +#endif } else { +#if 1 + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_Add(&e1, &alpha); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = eCos; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = eSin; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.y = FLOATOBJ_GetLong(&e2); +#else pt.x = xo + round(penWidthOut * cos(M_PI_2 + alpha + theta)); pt.y = yo + round(penWidthOut * sin(M_PI_2 + alpha + theta)); +#endif } PATH_AddEntry(pOutsidePath, &pt, PT_LINETO); break; case PS_JOIN_ROUND : default : +#if 1 + if (FLOATOBJ_GreaterThan0(&alpha)) +#else if (alpha > 0) +#endif { +#if 1 + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = eCos; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = eSin; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.y = FLOATOBJ_GetLong(&e2); +#else pt.x = xo + round(penWidthOut * cos(theta + M_PI_2)); pt.y = yo + round(penWidthOut * sin(theta + M_PI_2)); +#endif } else { +#if 1 + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = eCos; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Sub(&e2, &xo); + FLOATOBJ_Neg(&e2); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = eSin; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Sub(&e2, &xo); + FLOATOBJ_Neg(&e2); + pt.y = FLOATOBJ_GetLong(&e2); +#else pt.x = xo - round(penWidthOut * cos(theta + M_PI_2)); pt.y = yo - round(penWidthOut * sin(theta + M_PI_2)); +#endif } PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO); +#if 1 + { + e1 = theta; + FLOATOBJ_Add(&e1, &halfAlpha); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = eCos; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = eSin; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.y = FLOATOBJ_GetLong(&e2); + } +#else pt.x = xo + round(penWidthOut * cos(theta + alpha / 2)); pt.y = yo + round(penWidthOut * sin(theta + alpha / 2)); +#endif PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO); +#if 1 + if (FLOATOBJ_GreaterThan0(&alpha)) +#else if (alpha > 0) +#endif { +#if 1 + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_Add(&e1, &alpha); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = eCos; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Sub(&e2, &xo); + FLOATOBJ_Neg(&e2); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = eSin; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Sub(&e2, &xo); + FLOATOBJ_Neg(&e2); + pt.y = FLOATOBJ_GetLong(&e2); +#else pt.x = xo - round(penWidthOut * cos(M_PI_2 + alpha + theta)); pt.y = yo - round(penWidthOut * sin(M_PI_2 + alpha + theta)); +#endif } else { +#if 1 + e1 = theta; + FLOATOBJ_Add(&e1, &halfPi); + FLOATOBJ_Add(&e1, &alpha); + FLOATOBJ_AngleSinCos(&eSin, &eCos, &e1); + e1 = eCos; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.x = FLOATOBJ_GetLong(&e2); + e1 = eSin; + FLOATOBJ_MulLong(&e1, penWidthOut); + FLOATOBJ_Round(&e2, &e1); + FLOATOBJ_Add(&e2, &xo); + pt.y = FLOATOBJ_GetLong(&e2); +#else pt.x = xo + round(penWidthOut * cos(M_PI_2 + alpha + theta)); pt.y = yo + round(penWidthOut * sin(M_PI_2 + alpha + theta)); +#endif } PATH_AddEntry(pOutsidePath, &pt, PT_BEZIERTO); break;