/* Setting default boundary values for checking first and second forward * difference for the necessity of the restepping. See comments to the * boundary values in ProcessQuad for more info. */ int incStepBnd = DF_CUB_INC_BND; int decStepBnd = DF_CUB_DEC_BND; /* Setting default amount of steps */ int count = DF_CUB_COUNT; /* Setting default shift for preparing to the midpoint rounding */ int shift = DF_CUB_SHIFT; int ax = (int)((-coords[0] + 3*coords[2] - 3*coords[4] + coords[6])*CUB_A_MDP_MULT); int ay = (int)((-coords[1] + 3*coords[3] - 3*coords[5] + coords[7])*CUB_A_MDP_MULT); int bx = (int)((3*coords[0] - 6*coords[2] + 3*coords[4])*CUB_B_MDP_MULT); int by = (int)((3*coords[1] - 6*coords[3] + 3*coords[5])*CUB_B_MDP_MULT); int cx = (int)((-3*coords[0] + 3*coords[2])*(CUB_C_MDP_MULT)); int cy = (int)((-3*coords[1] + 3*coords[3])*(CUB_C_MDP_MULT)); int dddpx = 6*ax; int dddpy = 6*ay; int ddpx = dddpx + bx; int ddpy = dddpy + by; int dpx = ax + (bx>>1) + cx; int dpy = ay + (by>>1) + cy; int x1, y1; int x2 = x0; int y2 = y0; /* Calculating whole part of the first point of the curve */ int x0w = x0 & MDP_W_MASK; int y0w = y0 & MDP_W_MASK; int dx = xe - x0; int dy = ye - y0; while (count > 0) { /* Perform decreasing step in 2 times if necessary */ while (Math.abs(ddpx) > decStepBnd || Math.abs(ddpy) > decStepBnd) { ddpx = (ddpx<<1) - dddpx; ddpy = (ddpy<<1) - dddpy; dpx = (dpx<<2) - (ddpx>>1); dpy = (dpy<<2) - (ddpy>>1); count <<=1; decStepBnd <<=3; incStepBnd <<=3; px <<=3; py <<=3; shift += 3; } /* Perform increasing step in 2 times if necessary. * Note: we could do it only in even steps */ while ((count & 1) == 0 && shift > DF_CUB_SHIFT && Math.abs(dpx) <= incStepBnd && Math.abs(dpy) <= incStepBnd) { dpx = (dpx>>2) + (ddpx>>3); dpy = (dpy>>2) + (ddpy>>3); ddpx = (ddpx + dddpx)>>1; ddpy = (ddpy + dddpy)>>1; count >>=1; decStepBnd >>=3; incStepBnd >>=3; px >>=3; py >>=3; shift -= 3; } count--; /* Performing one step less than necessary and use actual (xe,ye) * curve's endpoint instead of calculated. This prevent us from * running above the curve endpoint due to the accumulated errors * during the iterations. */ if (count > 0) { px += dpx; py += dpy; dpx += ddpx; dpy += ddpy; ddpx += dddpx; ddpy += dddpy; x1 = x2; y1 = y2; x2 = x0w + (px >> shift); y2 = y0w + (py >> shift); /* Checking that we are not running out of the endpoint and * bounding violating coordinate. The check is pretty simple * because the curve passed to the DrawCubic already splitted * into the monotonic in X and Y pieces */ /* Bounding x2 by xe */ if (((xe-x2)^dx) < 0) { x2 = xe; } /* Bounding y2 by ye */ if (((ye-y2)^dy) < 0) { y2 = ye; } hnd.processFixedLine(x1, y1, x2, y2, pixelInfo, checkBounds, false); } else { hnd.processFixedLine(x2, y2, xe, ye, pixelInfo, checkBounds, false); } } } /* * Checking size of the cubic curves and split them if necessary. * Calling DrawMonotonicCubic for the curves of the appropriate size. * Note: coords array could be changed */ private static void ProcessMonotonicCubic(ProcessHandler hnd, float[] coords, int[] pixelInfo) { float[] coords1 = new float[8]; float tx, ty; float xMin, xMax; float yMin, yMax; xMin = xMax = coords[0]; yMin = yMax = coords[1]; for (int i = 2; i < 8; i += 2) { xMin = (xMin > coords[i])? coords[i] : xMin; xMax = (xMax < coords[i])? coords[i] : xMax; yMin = (yMin > coords[i + 1])? coords[i + 1] : yMin; yMax = (yMax < coords[i + 1])? coords[i + 1] : yMax; } if (hnd.clipMode == PH_MODE_DRAW_CLIP) { /* In case of drawing we could just skip curves which are * completely out of bounds */ if (hnd.dhnd.xMaxf < xMin || hnd.dhnd.xMinf > xMax || hnd.dhnd.yMaxf < yMin || hnd.dhnd.yMinf > yMax) { return; } } else { /* In case of filling we could skip curves which are above, * below and behind the right boundary of the visible area */ if (hnd.dhnd.yMaxf < yMin || hnd.dhnd.yMinf > yMax || hnd.dhnd.xMaxf < xMin) { return; } /* We could clamp x coordinates to the corresponding boundary * if the curve is completely behind the left one */ if (hnd.dhnd.xMinf > xMax) { coords[0] = coords[2] = coords[4] = coords[6] = hnd.dhnd.xMinf; } } if (xMax - xMin > MAX_CUB_SIZE || yMax - yMin > MAX_CUB_SIZE) { coords1[6] = coords[6]; coords1[7] = coords[7]; coords1[4] = (coords[4] + coords[6])/2.0f; coords1[5] = (coords[5] + coords[7])/2.0f; tx = (coords[2] + coords[4])/2.0f; ty = (coords[3] + coords[5])/2.0f; coords1[2] = (tx + coords1[4])/2.0f; coords1[3] = (ty + coords1[5])/2.0f; coords[2] = (coords[0] + coords[2])/2.0f; coords[3] = (coords[1] + coords[3])/2.0f; coords[4] = (coords[2] + tx)/2.0f; coords[5] = (coords[3] + ty)/2.0f; coords[6]=coords1[0]=(coords[4] + coords1[2])/2.0f; coords[7]=coords1[1]=(coords[5] + coords1[3])/2.0f; ProcessMonotonicCubic(hnd, coords, pixelInfo); ProcessMonotonicCubic(hnd, coords1, pixelInfo); } else { DrawMonotonicCubic(hnd, coords, /* Set checkBounds parameter if curve intersects * boundary of the visible area. We know that * the curve is visible, so the check is pretty * simple */ hnd.dhnd.xMinf > xMin || hnd.dhnd.xMaxf < xMax || hnd.dhnd.yMinf > yMin || hnd.dhnd.yMaxf < yMax, pixelInfo); } } /* * Split cubic curve into monotonic in X and Y parts. Calling * ProcessMonotonicCubic for each monotonic piece of the curve. * * Note: coords array could be changed */ private static void ProcessCubic(ProcessHandler hnd, float[] coords, int[] pixelInfo) { /* Temporary array for holding parameters corresponding to the extreme * in X and Y points */ double params[] = new double[4]; double eqn[] = new double[3]; double res[] = new double[2]; int cnt = 0; /* Simple check for monotonicity in X before searching for the extreme * points of the X(t) function. We first check if the curve is * monotonic in X by seeing if all of the X coordinates are strongly * ordered. */ if ((coords[0] > coords[2] || coords[2] > coords[4] || coords[4] > coords[6]) && (coords[0] < coords[2] || coords[2] < coords[4] || coords[4] < coords[6])) { /* Searching for extreme points of the X(t) function by solving * dX(t) * ---- = 0 equation * dt */ eqn[2] = -coords[0] + 3*coords[2] - 3*coords[4] + coords[6]; eqn[1] = 2*(coords[0] - 2*coords[2] + coords[4]); eqn[0] = -coords[0] + coords[2]; int nr = QuadCurve2D.solveQuadratic(eqn, res); /* Following code also correctly works in degenerate case of * the quadratic equation (nr = -1) because we do not need * splitting in this case. */ for (int i = 0; i < nr; i++) { if (res[i] > 0 && res[i] < 1) { params[cnt++] = res[i]; } } } /* Simple check for monotonicity in Y before searching for the extreme * points of the Y(t) function. We first check if the curve is * monotonic in Y by seeing if all of the Y coordinates are strongly * ordered. */ if ((coords[1] > coords[3] || coords[3] > coords[5] || coords[5] > coords[7]) && (coords[1] < coords[3] || coords[3] < coords[5] || coords[5] < coords[7])) { /* Searching for extreme points of the Y(t) function by solving * dY(t) * ----- = 0 equation * dt */ eqn[2] = -coords[1] + 3*coords[3] - 3*coords[5] + coords[7]; eqn[1] = 2*(coords[1] - 2*coords[3] + coords[5]); eqn[0] = -coords[1] + coords[3]; int nr = QuadCurve2D.solveQuadratic(eqn, res); /* Following code also correctly works in degenerate case of * the quadratic equation (nr = -1) because we do not need * splitting in this case. */ for (int i = 0; i < nr; i++) { if (res[i] > 0 && res[i] < 1) { params[cnt++] = res[i]; } } } if (cnt > 0) { /* Sorting parameter values corresponding to the extreme points * of the curve */ Arrays.sort(params, 0, cnt); /* Processing obtained monotonic parts */ ProcessFirstMonotonicPartOfCubic(hnd, coords, pixelInfo, (float)params[0]); for (int i = 1; i < cnt; i++) { double param = params[i] - params[i-1]; if (param > 0) { ProcessFirstMonotonicPartOfCubic(hnd, coords, pixelInfo, /* Scale parameter to match with rest of the curve */ (float)(param/(1.0 - params[i - 1]))); } } } ProcessMonotonicCubic(hnd,coords,pixelInfo); } /* * Bite the piece of the cubic curve from start point till the point * corresponding to the specified parameter then call ProcessCubic for the * bitten part. * Note: coords array will be changed */ private static void ProcessFirstMonotonicPartOfCubic(ProcessHandler hnd, float[] coords, int[] pixelInfo, float t) { float[] coords1 = new float[8]; float tx, ty; coords1[0] = coords[0]; coords1[1] = coords[1]; tx = coords[2] + t*(coords[4] - coords[2]); ty = coords[3] + t*(coords[5] - coords[3]); coords1[2] = coords[0] + t*(coords[2] - coords[0]); coords1[3] = coords[1] + t*(coords[3] - coords[1]); coords1[4] = coords1[2] + t*(tx - coords1[2]); coords1[5] = coords1[3] + t*(ty - coords1[3]); coords[4] = coords[4] + t*(coords[6] - coords[4]); coords[5] = coords[5] + t*(coords[7] - coords[5]); coords[2] = tx + t*(coords[4] - tx); coords[3] = ty + t*(coords[5] - ty); coords[0]=coords1[6]=coords1[4] + t*(coords[2] - coords1[4]); coords[1]=coords1[7]=coords1[5] + t*(coords[3] - coords1[5]); ProcessMonotonicCubic(hnd, coords1, pixelInfo); } /* Note: * For more easy reading of the code below each java version of the macros * from the ProcessPath.c preceded by the commented origin call * containing verbose names of the parameters */ private static void ProcessLine(ProcessHandler hnd, float x1, float y1, float x2, float y2, int[] pixelInfo) { float xMin, yMin, xMax, yMax; int X1, Y1, X2, Y2, X3, Y3, res; boolean clipped = false; float x3,y3; float c[] = new float[]{x1, y1, x2, y2, 0, 0}; boolean lastClipped; xMin = hnd.dhnd.xMinf; yMin = hnd.dhnd.yMinf; xMax = hnd.dhnd.xMaxf; yMax = hnd.dhnd.yMaxf; // // TESTANDCLIP(yMin, yMax, y1, x1, y2, x2, res); // res = TESTANDCLIP(yMin, yMax, c, 1, 0, 3, 2); if (res == CRES_INVISIBLE) return; clipped = IS_CLIPPED(res); // // TESTANDCLIP(yMin, yMax, y2, x2, y1, x1, res); // res = TESTANDCLIP(yMin, yMax, c, 3, 2, 1, 0); if (res == CRES_INVISIBLE) return; lastClipped = IS_CLIPPED(res); clipped = clipped || lastClipped; if (hnd.clipMode == PH_MODE_DRAW_CLIP) { // // TESTANDCLIP(xMin, xMax, x1, y1, x2, y2, res); // res = TESTANDCLIP(xMin, xMax, c, 0, 1, 2, 3); if (res == CRES_INVISIBLE) return; clipped = clipped || IS_CLIPPED(res); // // TESTANDCLIP(xMin, xMax, x2, y2, x1, y1, res); // res = TESTANDCLIP(xMin, xMax, c, 2, 3, 0, 1); if (res == CRES_INVISIBLE) return; lastClipped = lastClipped || IS_CLIPPED(res); clipped = clipped || lastClipped; X1 = (int)(c[0]*MDP_MULT); Y1 = (int)(c[1]*MDP_MULT); X2 = (int)(c[2]*MDP_MULT); Y2 = (int)(c[3]*MDP_MULT); hnd.processFixedLine(X1, Y1, X2, Y2, pixelInfo, clipped, /* enable boundary checking in case of clipping to avoid entering out of bounds which could happens during rounding */ lastClipped /* Notify pProcessFixedLine that this is the end of the subpath (because of exiting out of boundaries) */ ); } else { /* Clamping starting from first vertex of the the processed * segment * * CLIPCLAMP(xMin, xMax, x1, y1, x2, y2, x3, y3, res); */ res = CLIPCLAMP(xMin, xMax, c, 0, 1, 2, 3, 4, 5); X1 = (int)(c[0]*MDP_MULT); Y1 = (int)(c[1]*MDP_MULT); /* Clamping only by left boundary */ if (res == CRES_MIN_CLIPPED) { X3 = (int)(c[4]*MDP_MULT); Y3 = (int)(c[5]*MDP_MULT); hnd.processFixedLine(X3, Y3, X1, Y1, pixelInfo, false, lastClipped); } else if (res == CRES_INVISIBLE) { return; } /* Clamping starting from last vertex of the the processed * segment * * CLIPCLAMP(xMin, xMax, x2, y2, x1, y1, x3, y3, res); */ res = CLIPCLAMP(xMin, xMax, c, 2, 3, 0, 1, 4, 5); /* Checking if there was a clip by right boundary */ lastClipped = lastClipped || (res == CRES_MAX_CLIPPED); X2 = (int)(c[2]*MDP_MULT); Y2 = (int)(c[3]*MDP_MULT); hnd.processFixedLine(X1, Y1, X2, Y2, pixelInfo, false, lastClipped); /* Clamping only by left boundary */ if (res == CRES_MIN_CLIPPED) { X3 = (int)(c[4]*MDP_MULT); Y3 = (int)(c[5]*MDP_MULT); hnd.processFixedLine(X2, Y2, X3, Y3, pixelInfo, false, lastClipped); } } } private static boolean doProcessPath(ProcessHandler hnd, Path2D.Float p2df, float transXf, float transYf) { float coords[] = new float[8]; float tCoords[] = new float[8]; float closeCoord[] = new float[] {0.0f, 0.0f}; float firstCoord[] = new float[2]; int pixelInfo[] = new int[5]; boolean subpathStarted = false; boolean skip = false; float lastX, lastY; pixelInfo[0] = 0; /* Adjusting boundaries to the capabilities of the * ProcessPath code */ hnd.dhnd.adjustBounds(LOWER_OUT_BND, LOWER_OUT_BND, UPPER_OUT_BND, UPPER_OUT_BND); /* Adding support of the KEY_STROKE_CONTROL rendering hint. * Now we are supporting two modes: "pixels at centers" and * "pixels at corners". * First one is disabled by default but could be enabled by setting * VALUE_STROKE_PURE to the rendering hint. It means that pixel at the * screen (x,y) has (x + 0.5, y + 0.5) float coordinates. * * Second one is enabled by default and means straightforward mapping * (x,y) --> (x,y) */ if (hnd.dhnd.strokeControl == SunHints.INTVAL_STROKE_PURE) { closeCoord[0] = -0.5f; closeCoord[1] = -0.5f; transXf -= 0.5; transYf -= 0.5; }Lines 1001–1500 of 2128. Previous lines Load more
/* Setting default boundary values for checking first and second forward * difference for the necessity of the restepping. See comments to the * boundary values in ProcessQuad for more info. */ int incStepBnd = DF_CUB_INC_BND; int decStepBnd = DF_CUB_DEC_BND; /* Setting default amount of steps */ int count = DF_CUB_COUNT; /* Setting default shift for preparing to the midpoint rounding */ int shift = DF_CUB_SHIFT; int ax = (int)((-coords[0] + 3*coords[2] - 3*coords[4] + coords[6])*CUB_A_MDP_MULT); int ay = (int)((-coords[1] + 3*coords[3] - 3*coords[5] + coords[7])*CUB_A_MDP_MULT); int bx = (int)((3*coords[0] - 6*coords[2] + 3*coords[4])*CUB_B_MDP_MULT); int by = (int)((3*coords[1] - 6*coords[3] + 3*coords[5])*CUB_B_MDP_MULT); int cx = (int)((-3*coords[0] + 3*coords[2])*(CUB_C_MDP_MULT)); int cy = (int)((-3*coords[1] + 3*coords[3])*(CUB_C_MDP_MULT)); int dddpx = 6*ax; int dddpy = 6*ay; int ddpx = dddpx + bx; int ddpy = dddpy + by; int dpx = ax + (bx>>1) + cx; int dpy = ay + (by>>1) + cy; int x1, y1; int x2 = x0; int y2 = y0; /* Calculating whole part of the first point of the curve */ int x0w = x0 & MDP_W_MASK; int y0w = y0 & MDP_W_MASK; int dx = xe - x0; int dy = ye - y0; while (count > 0) { /* Perform decreasing step in 2 times if necessary */ while (Math.abs(ddpx) > decStepBnd || Math.abs(ddpy) > decStepBnd) { ddpx = (ddpx<<1) - dddpx; ddpy = (ddpy<<1) - dddpy; dpx = (dpx<<2) - (ddpx>>1); dpy = (dpy<<2) - (ddpy>>1); count <<=1; decStepBnd <<=3; incStepBnd <<=3; px <<=3; py <<=3; shift += 3; } /* Perform increasing step in 2 times if necessary. * Note: we could do it only in even steps */ while ((count & 1) == 0 && shift > DF_CUB_SHIFT && Math.abs(dpx) <= incStepBnd && Math.abs(dpy) <= incStepBnd) { dpx = (dpx>>2) + (ddpx>>3); dpy = (dpy>>2) + (ddpy>>3); ddpx = (ddpx + dddpx)>>1; ddpy = (ddpy + dddpy)>>1; count >>=1; decStepBnd >>=3; incStepBnd >>=3; px >>=3; py >>=3; shift -= 3; } count--; /* Performing one step less than necessary and use actual (xe,ye) * curve's endpoint instead of calculated. This prevent us from * running above the curve endpoint due to the accumulated errors * during the iterations. */ if (count > 0) { px += dpx; py += dpy; dpx += ddpx; dpy += ddpy; ddpx += dddpx; ddpy += dddpy; x1 = x2; y1 = y2; x2 = x0w + (px >> shift); y2 = y0w + (py >> shift); /* Checking that we are not running out of the endpoint and * bounding violating coordinate. The check is pretty simple * because the curve passed to the DrawCubic already splitted * into the monotonic in X and Y pieces */ /* Bounding x2 by xe */ if (((xe-x2)^dx) < 0) { x2 = xe; } /* Bounding y2 by ye */ if (((ye-y2)^dy) < 0) { y2 = ye; } hnd.processFixedLine(x1, y1, x2, y2, pixelInfo, checkBounds, false); } else { hnd.processFixedLine(x2, y2, xe, ye, pixelInfo, checkBounds, false); } } } /* * Checking size of the cubic curves and split them if necessary. * Calling DrawMonotonicCubic for the curves of the appropriate size. * Note: coords array could be changed */ private static void ProcessMonotonicCubic(ProcessHandler hnd, float[] coords, int[] pixelInfo) { float[] coords1 = new float[8]; float tx, ty; float xMin, xMax; float yMin, yMax; xMin = xMax = coords[0]; yMin = yMax = coords[1]; for (int i = 2; i < 8; i += 2) { xMin = (xMin > coords[i])? coords[i] : xMin; xMax = (xMax < coords[i])? coords[i] : xMax; yMin = (yMin > coords[i + 1])? coords[i + 1] : yMin; yMax = (yMax < coords[i + 1])? coords[i + 1] : yMax; } if (hnd.clipMode == PH_MODE_DRAW_CLIP) { /* In case of drawing we could just skip curves which are * completely out of bounds */ if (hnd.dhnd.xMaxf < xMin || hnd.dhnd.xMinf > xMax || hnd.dhnd.yMaxf < yMin || hnd.dhnd.yMinf > yMax) { return; } } else { /* In case of filling we could skip curves which are above, * below and behind the right boundary of the visible area */ if (hnd.dhnd.yMaxf < yMin || hnd.dhnd.yMinf > yMax || hnd.dhnd.xMaxf < xMin) { return; } /* We could clamp x coordinates to the corresponding boundary * if the curve is completely behind the left one */ if (hnd.dhnd.xMinf > xMax) { coords[0] = coords[2] = coords[4] = coords[6] = hnd.dhnd.xMinf; } } if (xMax - xMin > MAX_CUB_SIZE || yMax - yMin > MAX_CUB_SIZE) { coords1[6] = coords[6]; coords1[7] = coords[7]; coords1[4] = (coords[4] + coords[6])/2.0f; coords1[5] = (coords[5] + coords[7])/2.0f; tx = (coords[2] + coords[4])/2.0f; ty = (coords[3] + coords[5])/2.0f; coords1[2] = (tx + coords1[4])/2.0f; coords1[3] = (ty + coords1[5])/2.0f; coords[2] = (coords[0] + coords[2])/2.0f; coords[3] = (coords[1] + coords[3])/2.0f; coords[4] = (coords[2] + tx)/2.0f; coords[5] = (coords[3] + ty)/2.0f; coords[6]=coords1[0]=(coords[4] + coords1[2])/2.0f; coords[7]=coords1[1]=(coords[5] + coords1[3])/2.0f; ProcessMonotonicCubic(hnd, coords, pixelInfo); ProcessMonotonicCubic(hnd, coords1, pixelInfo); } else { DrawMonotonicCubic(hnd, coords, /* Set checkBounds parameter if curve intersects * boundary of the visible area. We know that * the curve is visible, so the check is pretty * simple */ hnd.dhnd.xMinf > xMin || hnd.dhnd.xMaxf < xMax || hnd.dhnd.yMinf > yMin || hnd.dhnd.yMaxf < yMax, pixelInfo); } } /* * Split cubic curve into monotonic in X and Y parts. Calling * ProcessMonotonicCubic for each monotonic piece of the curve. * * Note: coords array could be changed */ private static void ProcessCubic(ProcessHandler hnd, float[] coords, int[] pixelInfo) { /* Temporary array for holding parameters corresponding to the extreme * in X and Y points */ double params[] = new double[4]; double eqn[] = new double[3]; double res[] = new double[2]; int cnt = 0; /* Simple check for monotonicity in X before searching for the extreme * points of the X(t) function. We first check if the curve is * monotonic in X by seeing if all of the X coordinates are strongly * ordered. */ if ((coords[0] > coords[2] || coords[2] > coords[4] || coords[4] > coords[6]) && (coords[0] < coords[2] || coords[2] < coords[4] || coords[4] < coords[6])) { /* Searching for extreme points of the X(t) function by solving * dX(t) * ---- = 0 equation * dt */ eqn[2] = -coords[0] + 3*coords[2] - 3*coords[4] + coords[6]; eqn[1] = 2*(coords[0] - 2*coords[2] + coords[4]); eqn[0] = -coords[0] + coords[2]; int nr = QuadCurve2D.solveQuadratic(eqn, res); /* Following code also correctly works in degenerate case of * the quadratic equation (nr = -1) because we do not need * splitting in this case. */ for (int i = 0; i < nr; i++) { if (res[i] > 0 && res[i] < 1) { params[cnt++] = res[i]; } } } /* Simple check for monotonicity in Y before searching for the extreme * points of the Y(t) function. We first check if the curve is * monotonic in Y by seeing if all of the Y coordinates are strongly * ordered. */ if ((coords[1] > coords[3] || coords[3] > coords[5] || coords[5] > coords[7]) && (coords[1] < coords[3] || coords[3] < coords[5] || coords[5] < coords[7])) { /* Searching for extreme points of the Y(t) function by solving * dY(t) * ----- = 0 equation * dt */ eqn[2] = -coords[1] + 3*coords[3] - 3*coords[5] + coords[7]; eqn[1] = 2*(coords[1] - 2*coords[3] + coords[5]); eqn[0] = -coords[1] + coords[3]; int nr = QuadCurve2D.solveQuadratic(eqn, res); /* Following code also correctly works in degenerate case of * the quadratic equation (nr = -1) because we do not need * splitting in this case. */ for (int i = 0; i < nr; i++) { if (res[i] > 0 && res[i] < 1) { params[cnt++] = res[i]; } } } if (cnt > 0) { /* Sorting parameter values corresponding to the extreme points * of the curve */ Arrays.sort(params, 0, cnt); /* Processing obtained monotonic parts */ ProcessFirstMonotonicPartOfCubic(hnd, coords, pixelInfo, (float)params[0]); for (int i = 1; i < cnt; i++) { double param = params[i] - params[i-1]; if (param > 0) { ProcessFirstMonotonicPartOfCubic(hnd, coords, pixelInfo, /* Scale parameter to match with rest of the curve */ (float)(param/(1.0 - params[i - 1]))); } } } ProcessMonotonicCubic(hnd,coords,pixelInfo); } /* * Bite the piece of the cubic curve from start point till the point * corresponding to the specified parameter then call ProcessCubic for the * bitten part. * Note: coords array will be changed */ private static void ProcessFirstMonotonicPartOfCubic(ProcessHandler hnd, float[] coords, int[] pixelInfo, float t) { float[] coords1 = new float[8]; float tx, ty; coords1[0] = coords[0]; coords1[1] = coords[1]; tx = coords[2] + t*(coords[4] - coords[2]); ty = coords[3] + t*(coords[5] - coords[3]); coords1[2] = coords[0] + t*(coords[2] - coords[0]); coords1[3] = coords[1] + t*(coords[3] - coords[1]); coords1[4] = coords1[2] + t*(tx - coords1[2]); coords1[5] = coords1[3] + t*(ty - coords1[3]); coords[4] = coords[4] + t*(coords[6] - coords[4]); coords[5] = coords[5] + t*(coords[7] - coords[5]); coords[2] = tx + t*(coords[4] - tx); coords[3] = ty + t*(coords[5] - ty); coords[0]=coords1[6]=coords1[4] + t*(coords[2] - coords1[4]); coords[1]=coords1[7]=coords1[5] + t*(coords[3] - coords1[5]); ProcessMonotonicCubic(hnd, coords1, pixelInfo); } /* Note: * For more easy reading of the code below each java version of the macros * from the ProcessPath.c preceded by the commented origin call * containing verbose names of the parameters */ private static void ProcessLine(ProcessHandler hnd, float x1, float y1, float x2, float y2, int[] pixelInfo) { float xMin, yMin, xMax, yMax; int X1, Y1, X2, Y2, X3, Y3, res; boolean clipped = false; float x3,y3; float c[] = new float[]{x1, y1, x2, y2, 0, 0}; boolean lastClipped; xMin = hnd.dhnd.xMinf; yMin = hnd.dhnd.yMinf; xMax = hnd.dhnd.xMaxf; yMax = hnd.dhnd.yMaxf; // // TESTANDCLIP(yMin, yMax, y1, x1, y2, x2, res); // res = TESTANDCLIP(yMin, yMax, c, 1, 0, 3, 2); if (res == CRES_INVISIBLE) return; clipped = IS_CLIPPED(res); // // TESTANDCLIP(yMin, yMax, y2, x2, y1, x1, res); // res = TESTANDCLIP(yMin, yMax, c, 3, 2, 1, 0); if (res == CRES_INVISIBLE) return; lastClipped = IS_CLIPPED(res); clipped = clipped || lastClipped; if (hnd.clipMode == PH_MODE_DRAW_CLIP) { // // TESTANDCLIP(xMin, xMax, x1, y1, x2, y2, res); // res = TESTANDCLIP(xMin, xMax, c, 0, 1, 2, 3); if (res == CRES_INVISIBLE) return; clipped = clipped || IS_CLIPPED(res); // // TESTANDCLIP(xMin, xMax, x2, y2, x1, y1, res); // res = TESTANDCLIP(xMin, xMax, c, 2, 3, 0, 1); if (res == CRES_INVISIBLE) return; lastClipped = lastClipped || IS_CLIPPED(res); clipped = clipped || lastClipped; X1 = (int)(c[0]*MDP_MULT); Y1 = (int)(c[1]*MDP_MULT); X2 = (int)(c[2]*MDP_MULT); Y2 = (int)(c[3]*MDP_MULT); hnd.processFixedLine(X1, Y1, X2, Y2, pixelInfo, clipped, /* enable boundary checking in case of clipping to avoid entering out of bounds which could happens during rounding */ lastClipped /* Notify pProcessFixedLine that this is the end of the subpath (because of exiting out of boundaries) */ ); } else { /* Clamping starting from first vertex of the the processed * segment * * CLIPCLAMP(xMin, xMax, x1, y1, x2, y2, x3, y3, res); */ res = CLIPCLAMP(xMin, xMax, c, 0, 1, 2, 3, 4, 5); X1 = (int)(c[0]*MDP_MULT); Y1 = (int)(c[1]*MDP_MULT); /* Clamping only by left boundary */ if (res == CRES_MIN_CLIPPED) { X3 = (int)(c[4]*MDP_MULT); Y3 = (int)(c[5]*MDP_MULT); hnd.processFixedLine(X3, Y3, X1, Y1, pixelInfo, false, lastClipped); } else if (res == CRES_INVISIBLE) { return; } /* Clamping starting from last vertex of the the processed * segment * * CLIPCLAMP(xMin, xMax, x2, y2, x1, y1, x3, y3, res); */ res = CLIPCLAMP(xMin, xMax, c, 2, 3, 0, 1, 4, 5); /* Checking if there was a clip by right boundary */ lastClipped = lastClipped || (res == CRES_MAX_CLIPPED); X2 = (int)(c[2]*MDP_MULT); Y2 = (int)(c[3]*MDP_MULT); hnd.processFixedLine(X1, Y1, X2, Y2, pixelInfo, false, lastClipped); /* Clamping only by left boundary */ if (res == CRES_MIN_CLIPPED) { X3 = (int)(c[4]*MDP_MULT); Y3 = (int)(c[5]*MDP_MULT); hnd.processFixedLine(X2, Y2, X3, Y3, pixelInfo, false, lastClipped); } } } private static boolean doProcessPath(ProcessHandler hnd, Path2D.Float p2df, float transXf, float transYf) { float coords[] = new float[8]; float tCoords[] = new float[8]; float closeCoord[] = new float[] {0.0f, 0.0f}; float firstCoord[] = new float[2]; int pixelInfo[] = new int[5]; boolean subpathStarted = false; boolean skip = false; float lastX, lastY; pixelInfo[0] = 0; /* Adjusting boundaries to the capabilities of the * ProcessPath code */ hnd.dhnd.adjustBounds(LOWER_OUT_BND, LOWER_OUT_BND, UPPER_OUT_BND, UPPER_OUT_BND); /* Adding support of the KEY_STROKE_CONTROL rendering hint. * Now we are supporting two modes: "pixels at centers" and * "pixels at corners". * First one is disabled by default but could be enabled by setting * VALUE_STROKE_PURE to the rendering hint. It means that pixel at the * screen (x,y) has (x + 0.5, y + 0.5) float coordinates. * * Second one is enabled by default and means straightforward mapping * (x,y) --> (x,y) */ if (hnd.dhnd.strokeControl == SunHints.INTVAL_STROKE_PURE) { closeCoord[0] = -0.5f; closeCoord[1] = -0.5f; transXf -= 0.5; transYf -= 0.5; }