/*
* 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.
*/
private class ScanlineIterator {
private int[] crossings;
// crossing bounds. The bounds are not necessarily tight (the scan line
// at minY, for example, might have no crossings). The x bounds will
// be accumulated as crossings are computed.
private final int maxY;
private int nextY;
// indices into the segment pointer lists. They indicate the "active"
// sublist in the segment lists (the portion of the list that contains
// all the segments that cross the next scan line).
private int edgeCount;
private int[] edgePtrs;
// Preconditions: Only subpixel scanlines in the range
// (start <= subpixel_y <= end) will be evaluated. No
// edge may have a valid (i.e. inside the supplied clip)
// crossing that would be generated outside that range.
crossings = new int[INIT_CROSSINGS_SIZE];
edgePtrs = new int[INIT_CROSSINGS_SIZE];
edgeCount = 0;
}
private int next() {
int newCount = 0;
for (int i = 0; i < count; i++) {
}
}
}
// REMIND: Adjust start Y if necessary
}
// if ((count & 0x1) != 0) {
// System.out.println("ODD NUMBER OF EDGES!!!!");
// }
}
for (int i = 0; i < count; i++) {
cross |= 1;
}
int j = i;
while (--j >= 0) {
break;
}
}
}
return count;
}
private boolean hasNext() {
}
private int curY() {
return nextY - 1;
}
}
//////////////////////////////////////////////////////////////////////////////
// EDGE LIST
//////////////////////////////////////////////////////////////////////////////
// TODO(maybe): very tempting to use fixed point here. A lot of opportunities
// for shifts and just removing certain operations altogether.
// common to all types of input path segments.
// NEXT and OR are meant to be indices into "int" fields, but arrays must
// be homogenous, so every field is a float. However floats can represent
// exactly up to 26 bit ints, so we're ok.
// don't just set NULL to -1, because we want NULL+NEXT to be negative.
private int numEdges;
// each bucket is a linked list. this method adds eptr to the
// start of the "bucket"th linked list.
}
// Flattens using adaptive forward differencing. This only carries out
// one iteration of the AFD loop. All it does is update AFD variables (i.e.
// X0, Y0, D*[X|Y], COUNT; not variables used for computing scanline crossings).
final Curve c,
{
final float QUAD_DEC_BND = 32;
final int countlg = 4;
while (maxDD > QUAD_DEC_BND) {
maxDD /= 4;
count <<= 1;
}
while (count-- > 1) {
}
}
// x0, y0 and x3,y3 are the endpoints of the curve. We could compute these
// using c.xat(0),c.yat(0) and c.xat(1),c.yat(1), but this might introduce
// numerical errors, and our callers already have the exact values.
// Another alternative would be to pass all the control points, and call c.set
// here, but then too many numbers are passed around.
final Curve c,
{
final int countlg = 3;
// the dx and dy refer to forward differencing variables, not the last
// coefficients of the "points" polynomial
// we use x0, y0 to walk the line
while (count > 0) {
dddx /= 8;
dddy /= 8;
count <<= 1;
}
// can only do this on even "count" values, because we must divide count by 2
count >>= 1;
}
count--;
if (count > 0) {
} else {
}
}
}
or = 0;
}
if (firstCrossing >= lastCrossing) {
return;
}
} else {
}
numEdges++;
}
// END EDGE LIST
//////////////////////////////////////////////////////////////////////////////
// Antialiasing
final private int SUBPIXEL_LG_POSITIONS_X;
final private int SUBPIXEL_LG_POSITIONS_Y;
final private int SUBPIXEL_POSITIONS_X;
final private int SUBPIXEL_POSITIONS_Y;
final private int SUBPIXEL_MASK_X;
final private int SUBPIXEL_MASK_Y;
final int MAX_AA_ALPHA;
// Cache to store RLE-encoded coverage mask of the current primitive
// Bounds of the drawing region, at subpixel precision.
// Current winding rule
private final int windingRule;
// Current drawing position, i.e., final point of last segment
// Position of most recent 'moveTo' command
int pix_boundsX, int pix_boundsY,
int pix_boundsWidth, int pix_boundsHeight,
int windingRule)
{
this.windingRule = windingRule;
numEdges = 0;
}
return pix_x * SUBPIXEL_POSITIONS_X;
}
return pix_y * SUBPIXEL_POSITIONS_Y;
}
closePath();
}
}
{
}
}
public void closePath() {
// lineTo expects its input in pixel coordinates.
}
public void pathDone() {
closePath();
}
public long getNativeConsumer() {
throw new InternalError("Renderer does not use a native consumer.");
}
{
// Mask to determine the relevant bit of the crossing sum
// 0x1 if EVEN_ODD, all bits if NON_ZERO
// add 2 to better deal with the last pixel in a pixel row.
// Now we iterate through the scanlines. We must tell emitRow the coord
// of the first non-transparent pixel, so we must keep accumulators for
// the first and last pixels of the section of the current pixel row
// that we will emit.
// We also need to accumulate pix_bbox*, but the iterator does it
// for us. We will just get the values from it once this loop is done
int y = boundsMinY; // needs to be declared here so we emit the last row properly.
if (numCrossings > 0) {
}
int sum = 0;
for (int i = 0; i < numCrossings; i++) {
// to turn {0, 1} into {-1, 1}, multiply by 2 and subtract 1.
if (pix_x == pix_xmaxm1) {
// Start and end in same pixel
} else {
}
}
}
sum += crorientation;
}
// even if this last row had no crossings, alpha will be zeroed
// from the last emitRow call. But this doesn't matter because
// maxX < minX, so no row will be emitted to the cache.
if ((y & SUBPIXEL_MASK_Y) == SUBPIXEL_MASK_Y) {
}
}
// Emit final row
}
}
public void endRendering() {
return;
}
}
throw new InternalError("cache not yet initialized");
}
return cache;
}
// Copy rowAA data into the cache if one is present
// Perform run-length encoding and store results in the cache
int runLen = 1;
runLen++;
} else {
runLen = 1;
}
}
}
}
}
}