/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* This is the java implementation of the native code from
* This code is written to be as much similar to the native
* as it possible. So, it sometimes does not follow java naming conventions.
*
* It's important to keep this code synchronized with native one. See more
* comments, description and high level scheme of the rendering process in the
* ProcessPath.c
*/
public class ProcessPath {
/* Public interfaces and methods for drawing and filling general paths */
public static abstract class DrawHandler {
public int xMin;
public int yMin;
public int xMax;
public int yMax;
public float xMinf;
public float yMinf;
public float xMaxf;
public float yMaxf;
public int strokeControl;
int strokeControl)
{
}
{
/* Setting up fractional clipping box
*
* We are using following float -> int mapping:
*
* xi = floor(xf + 0.5)
*
* So, fractional values that hit the [xmin, xmax) integer interval
* will be situated inside the [xmin-0.5, xmax - 0.5) fractional
* interval. We are using EPSF constant to provide that upper
* boundary is not included.
*/
}
int strokeControl)
{
this.strokeControl = strokeControl;
}
{
}
}
}
public interface EndSubPathHandler {
public void processEndSubPath();
}
int clipMode;
int clipMode) {
}
boolean checkBounds,
boolean endSubPath);
}
new EndSubPathHandler() {
public void processEndSubPath() { }
};
{
return false;
}
return true;
}
{
}
{
}
/* Private implementation of the rendering process */
/* Boundaries used for skipping huge path segments */
/* Precision (in bits) used in forward differencing */
/* Precision (in bits) used for the rounding in the midpoint test */
/* Boundaries used for clipping large path segments (those are inside
*/
/* Calculation boundaries. They are used for switching to the more slow but
* allowing larger input values method of calculation of the initial values
* of the scan converted line segments inside the FillPolygon
*/
/* Following constants are used for providing open boundaries of the
* intervals
*/
/* Bit mask used to separate whole part from the fraction part of the
* number
*/
/* Bit mask used to separate fractional part from the whole part of the
* number
*/
/*
* Constants for the forward differencing
* of the cubic and quad curves
*/
/* Maximum size of the cubic curve (calculated as the size of the bounding
* box of the control points) which could be rendered without splitting
*/
/* Maximum size of the quad curve (calculated as the size of the bounding
* box of the control points) which could be rendered without splitting
*/
/* Default power of 2 steps used in the forward differencing. Here DF prefix
* stands for DeFault. Constants below are used as initial values for the
* adaptive forward differencing algorithm.
*/
/* Shift of the current point of the curve for preparing to the midpoint
* rounding
*/
/* Default amount of steps of the forward differencing */
/* Default boundary constants used to check the necessity of the restepping
*/
FWD_PREC + 2;
FWD_PREC - 1;
/* Multipliers for the coefficients of the polynomial form of the cubic and
* quad curves representation
*/
/* Clipping macros for drawing and filling algorithms */
double t) {
}
}
}
/* This is java implementation of the macro from ProcessGeneralPath.c.
* To keep the logic of the java code similar to the native one
* array and set of indexes are used to point out the data.
*/
double t;
int res = CRES_NOT_CLIPPED;
return CRES_INVISIBLE;
};
t = (LINE_MIN);
} else {
return CRES_INVISIBLE;
};
t = (LINE_MAX);
}
c[a1] = (float)t;
}
return res;
}
/* Integer version of the method above */
double t;
int res = CRES_NOT_CLIPPED;
return CRES_INVISIBLE;
};
t = (LINE_MIN);
} else {
return CRES_INVISIBLE;
};
t = (LINE_MAX);
}
c[a1] = (int)t;
}
return res;
}
/* Following method is used for clipping and clumping filled shapes.
* An example of this process is shown on the picture below:
* ----+ ----+
* |/ | |/ |
* + | + |
* /| | I |
* / | | I |
* | | | ===> I |
* \ | | I |
* \| | I |
* + | + |
* |\ | |\ |
* | ----+ | ----+
* boundary boundary
*
* We can only perform clipping in case of right side of the output area
* because all segments passed out the right boundary don't influence on the
* result of scan conversion algorithm (it correctly handles half open
* contours).
*
* This is java implementation of the macro from ProcessGeneralPath.c.
* To keep the logic of the java code similar to the native one
* array and set of indexes are used to point out the data.
*
*/
if (res == CRES_MIN_CLIPPED) {
} else if (res == CRES_MAX_CLIPPED) {
} else if (res == CRES_INVISIBLE) {
} else {
}
}
return res;
}
/* Integer version of the method above */
if (res == CRES_MIN_CLIPPED) {
} else if (res == CRES_MAX_CLIPPED) {
} else if (res == CRES_INVISIBLE) {
} else {
}
}
return res;
}
super(dhnd, PH_MODE_DRAW_CLIP);
this.processESP = processESP;
}
public void processEndSubPath() {
}
boolean checkBounds, int[] pixelInfo) {
/* Handling lines having just one pixel */
if (checkBounds &&
}
return;
}
if (!checkBounds ||
{
/* Switch off first pixel of the line before drawing */
{
}
}
}
/* Switch on last pixel of the line if it was already
* drawn during rendering of the previous segments
*/
{
if (checkBounds &&
return;
}
}
}
int[] pixelInfo) {
if (checkBounds &&
/*
* (_X,_Y) should be inside boundaries
*
* assert(dhnd.yMin <= _Y &&
* dhnd.yMax > _Y &&
* dhnd.xMin <= _X &&
* dhnd.xMax > _X);
*
*/
}
}
/* Drawing line with subpixel endpoints
*
* (x1, y1), (x2, y2) - fixed point coordinates of the endpoints
* with MDP_PREC bits for the fractional part
*
* pixelInfo - structure which keeps drawing info for avoiding
* multiple drawing at the same position on the
* screen (required for the XOR mode of drawing)
*
* pixelInfo[0] - state of the drawing
* 0 - no pixel drawn between
* 1 - there are drawn pixels
*
* pixelInfo[1,2] - first pixel of the path
* path
*
* pixelInfo[3,4] - last drawn pixel between
*
* checkBounds - flag showing necessity of checking the clip
*
*/
int[] pixelInfo, boolean checkBounds,
boolean endSubPath) {
/* Checking if line is inside a (X,Y),(X+MDP_MULT,Y+MDP_MULT) box */
if ((c & MDP_W_MASK) == 0) {
/* Checking for the segments with integer coordinates having
* the same start and end points
*/
if (c == 0) {
}
return;
}
} else {
/* Neither dx nor dy can be zero because of the check above */
/* Floor of x1, y1, x2, y2 */
/* Processing first endpoint */
/* Adding MDP_HALF_MULT to the [xy]1 if f[xy]1 == [xy]1
* will not affect the result
*/
} else {
/* Boundary at the direction from (x1,y1) to (x2,y2) */
/* intersection with column bx1 */
} else {
/* intersection with row by1 */
}
}
/* Processing second endpoint */
/* Adding MDP_HALF_MULT to the [xy]2 if f[xy]2 == [xy]2
* will not affect the result
*/
} else {
/* Boundary at the direction from (x2,y2) to (x1,y1) */
/* intersection with column bx2 */
} else {
/* intersection with row by2 */
}
}
}
}
}
/* Performing drawing of the monotonic in X and Y quadratic curves with
* sizes less than MAX_QUAD_SIZE by using forward differencing method of
* calculation. See comments to the DrawMonotonicQuad in the
* ProcessGeneralPath.c
*/
float[] coords,
boolean checkBounds,
int[] pixelInfo) {
/* Extracting fractional part of coordinates of first control point */
/* Setting default amount of steps */
int count = DF_QUAD_COUNT;
/* Setting default shift for preparing to the midpoint rounding */
int shift = DF_QUAD_SHIFT;
/* Perform decreasing step in 2 times if slope of the first forward
* difference changes too quickly (more than a pixel per step in X or Y
* direction). We can perform adjusting of the step size before the
* rendering loop because the curvature of the quad curve remains the
* same along all the curve
*/
while (maxDD > DF_QUAD_DEC_BND) {
count <<= 1;
maxDD >>= 2;
px <<=2;
py <<=2;
shift += 2;
}
while(count-- > 1) {
/* 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 */
}
/* Bounding y2 by ye */
}
}
/* We are performing one step less than necessary and use actual
* (xe,ye) endpoint of the curve instead of calculated. This prevent us
* from running above the curve endpoint due to the accumulated errors
* during the iterations.
*/
}
/*
* Checking size of the quad curves and split them if necessary.
* Calling DrawMonotonicQuad for the curves of the appropriate size.
* Note: coords array could be changed
*/
float[] coords,
int[] pixelInfo) {
float[] coords1 = new float[6];
for (int i = 2; i < 6; i += 2) {
}
/* In case of drawing we could just skip curves which are
* completely out of bounds
*/
return;
}
} else {
/* In case of filling we could skip curves which are above,
* below and behind the right boundary of the visible area
*/
{
return;
}
/* We could clamp x coordinates to the corresponding boundary
* if the curve is completely behind the left one
*/
}
}
} else {
/* Set checkBounds parameter if curve intersects
* boundary of the visible area. We know that the
* curve is visible, so the check is pretty
* simple
*/
}
}
/*
* Split quadratic curve into monotonic in X and Y parts. Calling
* ProcessMonotonicQuad for each monotonic piece of the curve.
* Note: coords array could be changed
*/
int[] pixelInfo) {
/* Temporary array for holding parameters corresponding to the extreme
* in X and Y points
*/
double params[] = new double[2];
int cnt = 0;
double param;
/* 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.
*/
{
/* Searching for extreme points of the X(t) function by solving
* dX(t)
* ---- = 0 equation
* dt
*/
if (ax != 0) {
/* Calculating root of the following equation
* ax*t + bx = 0
*/
}
}
}
/* 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.
*/
{
/* Searching for extreme points of the Y(t) function by solving
* dY(t)
* ----- = 0 equation
* dt
*/
if (ay != 0) {
/* Calculating root of the following equation
* ay*t + by = 0
*/
if (cnt > 0) {
/* Inserting parameter only if it differs from
* already stored
*/
}
} else {
}
}
}
}
/* Processing obtained monotonic parts */
switch(cnt) {
case 0:
break;
case 1:
(float)params[0]);
break;
case 2:
(float)params[0]);
if (param > 0) {
/* Scale parameter to match with
* rest of the curve
*/
}
break;
}
}
/*
* Bite the piece of the quadratic curve from start point till the point
* corresponding to the specified parameter then call ProcessQuad for the
* bitten part.
* Note: coords array will be changed
*/
float[] coords,
int[] pixelInfo,
float t) {
float[] coords1 = new float[6];
}
/* Performing drawing of the monotonic in X and Y cubic curves with sizes
* less than MAX_CUB_SIZE by using forward differencing method of
* calculation. See comments to the DrawMonotonicCubic in the
* ProcessGeneralPath.c
*/
float[] coords,
boolean checkBounds,
int[] pixelInfo) {
/* Extracting fractional part of coordinates of first control point */
/* 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;
/* Calculating whole part of the first point of the curve */
while (count > 0) {
/* Perform decreasing step in 2 times if necessary */
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
*/
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) {
/* 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 */
}
/* Bounding y2 by ye */
}
false);
} else {
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
*/
float[] coords,
int[] pixelInfo) {
float[] coords1 = new float[8];
for (int i = 2; i < 8; i += 2) {
}
/* In case of drawing we could just skip curves which are
* completely out of bounds
*/
return;
}
} else {
/* In case of filling we could skip curves which are above,
* below and behind the right boundary of the visible area
*/
{
return;
}
/* We could clamp x coordinates to the corresponding boundary
* if the curve is completely behind the left one
*/
}
}
} else {
/* Set checkBounds parameter if curve intersects
* boundary of the visible area. We know that
* the curve is visible, so the check is pretty
* simple
*/
}
}
/*
* 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
*/
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.
*/
{
/* Searching for extreme points of the X(t) function by solving
* dX(t)
* ---- = 0 equation
* dt
*/
/* 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++) {
}
}
}
/* 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.
*/
{
/* Searching for extreme points of the Y(t) function by solving
* dY(t)
* ----- = 0 equation
* dt
*/
/* 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 (cnt > 0) {
/* Sorting parameter values corresponding to the extreme points
* of the curve
*/
/* Processing obtained monotonic parts */
(float)params[0]);
for (int i = 1; i < cnt; i++) {
if (param > 0) {
/* Scale parameter to match with rest of the curve */
}
}
}
}
/*
* 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
*/
float[] coords,
int[] pixelInfo,
float t)
{
float[] coords1 = new float[8];
}
/* 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
*/
boolean clipped = false;
boolean lastClipped;
//
// TESTANDCLIP(yMin, yMax, y1, x1, y2, x2, res);
//
if (res == CRES_INVISIBLE) return;
//
// TESTANDCLIP(yMin, yMax, y2, x2, y1, x1, res);
//
if (res == CRES_INVISIBLE) return;
//
// TESTANDCLIP(xMin, xMax, x1, y1, x2, y2, res);
//
if (res == CRES_INVISIBLE) return;
//
// TESTANDCLIP(xMin, xMax, x2, y2, x1, y1, res);
//
if (res == CRES_INVISIBLE) return;
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);
*/
/* Clamping only by left boundary */
if (res == CRES_MIN_CLIPPED) {
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);
*/
/* Checking if there was a clip by right boundary */
false, lastClipped);
/* Clamping only by left boundary */
if (res == CRES_MIN_CLIPPED) {
false, lastClipped);
}
}
}
float coords[] = new float[8];
float tCoords[] = new float[8];
float firstCoord[] = new float[2];
int pixelInfo[] = new int[5];
boolean subpathStarted = false;
boolean skip = false;
/* Adjusting boundaries to the capabilities of the
* ProcessPath code
*/
/* 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)
*/
transXf -= 0.5;
transYf -= 0.5;
}
case PathIterator.SEG_MOVETO:
/* Performing closing of the unclosed segments */
if (subpathStarted && !skip) {
{
}
}
}
/* Checking SEG_MOVETO coordinates if they are out of the
* [LOWER_BND, UPPER_BND] range. This check also handles
* NaN and Infinity values. Skipping next path segment in
* case of invalid data.
*/
{
subpathStarted = true;
skip = false;
} else {
skip = true;
}
break;
case PathIterator.SEG_LINETO:
/* Checking SEG_LINETO coordinates if they are out of the
* [LOWER_BND, UPPER_BND] range. This check also handles
* NaN and Infinity values. Ignoring current path segment
* in case of invalid data. If segment is skipped its
* endpoint (if valid) is used to begin new subpath.
*/
{
if (skip) {
subpathStarted = true;
skip = false;
} else {
}
}
break;
case PathIterator.SEG_QUADTO:
/* Checking SEG_QUADTO coordinates if they are out of the
* [LOWER_BND, UPPER_BND] range. This check also handles
* NaN and Infinity values. Ignoring current path segment
* in case of invalid endpoints's data. Equivalent to
* the SEG_LINETO if endpoint coordinates are valid but
* there are invalid data among other coordinates
*/
{
if (skip) {
subpathStarted = true;
skip = false;
} else {
{
} else {
}
}
}
break;
case PathIterator.SEG_CUBICTO:
/* Checking SEG_CUBICTO coordinates if they are out of the
* [LOWER_BND, UPPER_BND] range. This check also handles
* NaN and Infinity values. Ignoring current path segment
* in case of invalid endpoints's data. Equivalent to
* the SEG_LINETO if endpoint coordinates are valid but
* there are invalid data among other coordinates
*/
{
if (skip) {
subpathStarted = true;
skip = false;
} else {
{
} else {
}
}
}
break;
case PathIterator.SEG_CLOSE:
if (subpathStarted && !skip) {
skip = false;
{
/* Storing last path's point for using in following
* segments without initial moveTo
*/
}
}
break;
}
}
/* Performing closing of the unclosed segments */
if (subpathStarted & !skip) {
{
}
}
}
return true;
}
private static class Point {
public int x;
public int y;
public boolean lastPoint;
this.x = x;
this.y = y;
}
};
private static class Edge {
int x;
int dx;
Point p;
int dir;
this.p = p;
this.x = x;
}
};
/* Size of the default buffer in the FillData structure. This buffer is
* replaced with heap allocated in case of large paths.
*/
/* Following class accumulates points of the non-continuous flattened
* general path during iteration through the origin path's segments . The
* end of the each subpath is marked as lastPoint flag set at the last
* point
*/
private static class FillData {
public int plgYMin;
public int plgYMax;
public FillData() {
}
} else {
}
}
public boolean isEmpty() {
}
public boolean isEnded() {
}
public boolean setEnded() {
}
}
private static class ActiveEdgeList {
public boolean isEmpty() {
}
/* Skipping horizontal segments */
return;
} else {
dir = -1;
} else { // (Y1 > Y2)
dir = 1;
}
/* We need to worry only about dX because dY is in denominator
* and abs(dy) < MDP_MULT (cy is a first scanline of the scan
* converted segment and we subtract y coordinate of the
* nearest segment's end from it to obtain dy)
*/
} else {
}
}
}
}
} else {
}
}
}
/**
* Bubble sorting in the ascending order of the linked list. This
* implementation stops processing the list if there were no changes
* during the previous pass.
*
* We could not use O(N) Radix sort here because in most cases list of
* edges almost sorted. So, bubble sort (O(N^2)) is working much
* better. Note, in case of array of edges Shell sort is more
* efficient.
*/
public void sort() {
boolean wasSwap = true;
// r precedes p and s points to the node up to which
// comparisons are to be made
r = p = head;
q = p.next;
wasSwap = false;
while (p != s) {
if (p.x >= q.x) {
wasSwap = true;
if (p == head) {
q.next = p;
head = q;
r = q;
} else {
q.next = p;
r.next = q;
r = q;
}
} else {
r = p;
p = p.next;
}
q = p.next;
if (q == s) s = p;
}
}
// correction of the back links in the double linked edge list
p = head;
q = null;
while (p != null) {
p.prev = q;
q = p;
p = p.next;
}
}
}
int fillRule) {
int k, y, n;
boolean drawing;
/* Because of support of the KEY_STROKE_CONTROL hint we are performing
* shift of the coordinates at the higher level
*/
/* Winding counter */
int counter;
/* Calculating mask to be applied to the winding counter */
int counterMask =
int pntOffset;
if (n <=1) return;
/* Creating double linked list (prev, next links) describing path order
* and hash table with points which fall between scanlines. nextByY
* link is used for the points which are between same scanlines.
* Scanlines are passed through the centers of the pixels.
*/
for (int i = 0; i < n - 1; i++) {
}
{
/* pt.y should be inside hashed interval
* assert(y-MDP_MULT <= pt.y && pt.y < y);
*/
}
}
}
}
}
if (activeList.isEmpty()) continue;
activeList.sort();
counter = 0;
drawing = false;
drawing = true;
}
}
drawing = false;
}
}
/* Performing drawing till the right boundary (for correct
* rendering shapes clipped at the right side)
*/
/* Support of the strokeHint was added into the
* draw and fill methods of the sun.java2d.pipe.LoopPipe
*/
}
}
}
/* 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
*/
int[] pixelInfo, boolean checkBounds,
boolean endSubPath)
{
int res;
/* There is no need to round line coordinates to the forward
* differencing precision anymore. Such a rounding was used for
* preventing the curve go out the endpoint (this sometimes does
* not help). The problem was fixed in the forward differencing
* loops.
*/
if (checkBounds) {
boolean lastClipped;
/* This function is used only for filling shapes, so there is no
* check for the type of clipping
*/
/*
* TESTANDCLIP(outYMin, outYMax, y1, x1, y2, x2, res);
*/
if (res == CRES_INVISIBLE) return;
/*
* TESTANDCLIP(outYMin, outYMax, y2, x2, y1, x1, res);
*/
if (res == CRES_INVISIBLE) return;
/* Clamping starting from first vertex of the the processed
* segment
*
* CLIPCLAMP(outXMin, outXMax, x1, y1, x2, y2, x3, y3, res);
*/
/* Clamping only by left boundary */
if (res == CRES_MIN_CLIPPED) {
false, lastClipped);
} else if (res == CRES_INVISIBLE) {
return;
}
/* Clamping starting from last vertex of the the processed
* segment
*
* CLIPCLAMP(outXMin, outXMax, x2, y2, x1, y1, x3, y3, res);
*/
/* Checking if there was a clip by right boundary */
false, lastClipped);
/* Clamping only by left boundary */
if (res == CRES_MIN_CLIPPED) {
false, lastClipped);
}
return;
}
/* Adding first point of the line only in case of empty or just
* finished path
*/
}
if (endSubPath) {
}
}
super(dhnd, PH_MODE_FILL_CLIP);
}
public void processEndSubPath() {
}
}
}
}