< prev index next >

modules/javafx.graphics/src/main/java/com/sun/marlin/DRenderer.java

Print this page

        

@@ -26,24 +26,24 @@
 package com.sun.marlin;
 
 import static com.sun.marlin.OffHeapArray.SIZE_INT;
 import jdk.internal.misc.Unsafe;
 
-public final class Renderer implements MarlinRenderer, MarlinConst {
+public final class DRenderer implements DMarlinRenderer, MarlinConst {
 
     static final boolean DISABLE_RENDER = false;
 
     private static final int ALL_BUT_LSB = 0xfffffffe;
-    private static final int ERR_STEP_MAX = 0x7fffffff; // = 2^31 - 1
+    private static final int ERR_STEP_MAX = 0x7Dffffff; // = 2^31 - 1
 
     private static final double POWER_2_TO_32 = 0x1.0p32;
 
-    // use float to make tosubpix methods faster (no int to float conversion)
-    static final float F_SUBPIXEL_POSITIONS_X
-        = (float) SUBPIXEL_POSITIONS_X;
-    static final float F_SUBPIXEL_POSITIONS_Y
-        = (float) SUBPIXEL_POSITIONS_Y;
+    // use double to make tosubpix methods faster (no int to double conversion)
+    static final double F_SUBPIXEL_POSITIONS_X
+        =  SUBPIXEL_POSITIONS_X;
+    static final double F_SUBPIXEL_POSITIONS_Y
+        =  SUBPIXEL_POSITIONS_Y;
     static final int SUBPIXEL_MASK_X = SUBPIXEL_POSITIONS_X - 1;
     static final int SUBPIXEL_MASK_Y = SUBPIXEL_POSITIONS_Y - 1;
 
     // 2048 (pixelSize) pixels (height) x 8 subpixels = 64K
     static final int INITIAL_BUCKET_ARRAY

@@ -65,47 +65,54 @@
     // size of one edge in bytes
     public static final int SIZEOF_EDGE_BYTES = (int)(OFF_YMAX + SIZE_INT);
 
     // curve break into lines
     // cubic error in subpixels to decrement step
-    private static final float CUB_DEC_ERR_SUBPIX
-        = 1f * (NORM_SUBPIXELS / 8f); // 1 subpixel for typical 8x8 subpixels
+    private static final double CUB_DEC_ERR_SUBPIX
+        = 1D * (NORM_SUBPIXELS / 8D); // 1 subpixel for typical 8x8 subpixels
     // cubic error in subpixels to increment step
-    private static final float CUB_INC_ERR_SUBPIX
-        = 0.4f * (NORM_SUBPIXELS / 8f); // 0.4 subpixel for typical 8x8 subpixels
+    private static final double CUB_INC_ERR_SUBPIX
+        = 0.4D * (NORM_SUBPIXELS / 8D); // 0.4 subpixel for typical 8x8 subpixels
 
     // cubic bind length to decrement step = 8 * error in subpixels
     // multiply by 8 = error scale factor:
-    public static final float CUB_DEC_BND
-        = 8f * CUB_DEC_ERR_SUBPIX;
+    public static final double CUB_DEC_BND
+        = 8D * CUB_DEC_ERR_SUBPIX;
     // cubic bind length to increment step = 8 * error in subpixels
-    public static final float CUB_INC_BND
-        = 8f * CUB_INC_ERR_SUBPIX;
+    public static final double CUB_INC_BND
+        = 8D * CUB_INC_ERR_SUBPIX;
 
     // cubic countlg
     public static final int CUB_COUNT_LG = 2;
     // cubic count = 2^countlg
     private static final int CUB_COUNT = 1 << CUB_COUNT_LG;
     // cubic count^2 = 4^countlg
     private static final int CUB_COUNT_2 = 1 << (2 * CUB_COUNT_LG);
     // cubic count^3 = 8^countlg
     private static final int CUB_COUNT_3 = 1 << (3 * CUB_COUNT_LG);
     // cubic dt = 1 / count
-    private static final float CUB_INV_COUNT = 1f / CUB_COUNT;
+    private static final double CUB_INV_COUNT = 1D / CUB_COUNT;
     // cubic dt^2 = 1 / count^2 = 1 / 4^countlg
-    private static final float CUB_INV_COUNT_2 = 1f / CUB_COUNT_2;
+    private static final double CUB_INV_COUNT_2 = 1D / CUB_COUNT_2;
     // cubic dt^3 = 1 / count^3 = 1 / 8^countlg
-    private static final float CUB_INV_COUNT_3 = 1f / CUB_COUNT_3;
+    private static final double CUB_INV_COUNT_3 = 1D / CUB_COUNT_3;
 
     // quad break into lines
     // quadratic error in subpixels
-    private static final float QUAD_DEC_ERR_SUBPIX
-        = 1f * (NORM_SUBPIXELS / 8f); // 1 subpixel for typical 8x8 subpixels
+    private static final double QUAD_DEC_ERR_SUBPIX
+        = 0.5D * (NORM_SUBPIXELS / 8D); // 1 subpixel for typical 8x8 subpixels
 
     // quadratic bind length to decrement step = 8 * error in subpixels
-    public static final float QUAD_DEC_BND
-        = 8f * QUAD_DEC_ERR_SUBPIX;
+    public static final double QUAD_DEC_BND
+        = 8D * QUAD_DEC_ERR_SUBPIX;
+
+    public static final boolean USE_SUBDIVIDE_QUAD = false;
+    public static final int SUBDIVIDE_MAX = 20;
+
+    public static final double QUAD_ERR_SUBPIX = 1D / 16D;
+    public static final double MAX_FLAT_SQ
+        = 4D * QUAD_ERR_SUBPIX * QUAD_ERR_SUBPIX; // x4
 
 //////////////////////////////////////////////////////////////////////////////
 //  SCAN LINE
 //////////////////////////////////////////////////////////////////////////////
     // crossings ie subpixel edge x coordinates

@@ -137,14 +144,14 @@
 //////////////////////////////////////////////////////////////////////////////
 //  EDGE LIST
 //////////////////////////////////////////////////////////////////////////////
     private int edgeMinY = Integer.MAX_VALUE;
     private int edgeMaxY = Integer.MIN_VALUE;
-    private float edgeMinX = Float.POSITIVE_INFINITY;
-    private float edgeMaxX = Float.NEGATIVE_INFINITY;
+    private double edgeMinX = Double.POSITIVE_INFINITY;
+    private double edgeMaxX = Double.NEGATIVE_INFINITY;
 
-    // edges [floats|ints] stored in off-heap memory
+    // edges [doubles|ints] stored in off-heap memory
     private final OffHeapArray edges;
 
     private int[] edgeBuckets;
     private int[] edgeBucketCounts; // 2*newedges + (1 if pruning needed)
     // used range for edgeBuckets / edgeBucketCounts

@@ -159,42 +166,42 @@
     boolean useRLE = false;
 
     // 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).
-    private void quadBreakIntoLinesAndAdd(float x0, float y0,
-                                          final Curve c,
-                                          final float x2, final float y2)
+    private void quadBreakIntoLinesAndAdd(double x0, double y0,
+                                          final DCurve c,
+                                          final double x2, final double y2)
     {
         int count = 1; // dt = 1 / count
 
         // maximum(ddX|Y) = norm(dbx, dby) * dt^2 (= 1)
-        float maxDD = FloatMath.max(Math.abs(c.dbx), Math.abs(c.dby));
+        double maxDD = FloatMath.max(Math.abs(c.dbx), Math.abs(c.dby));
 
-        final float _DEC_BND = QUAD_DEC_BND;
+        final double _DEC_BND = QUAD_DEC_BND;
 
         while (maxDD >= _DEC_BND) {
             // divide step by half:
-            maxDD /= 4f; // error divided by 2^2 = 4
+            maxDD /= 4D; // error divided by 2^2 = 4
 
             count <<= 1;
             if (DO_STATS) {
                 rdrCtx.stats.stat_rdr_quadBreak_dec.add(count);
             }
         }
 
         int nL = 0; // line count
         if (count > 1) {
-            final float icount = 1f / count; // dt
-            final float icount2 = icount * icount; // dt^2
+            final double icount = 1D / count; // dt
+            final double icount2 = icount * icount; // dt^2
 
-            final float ddx = c.dbx * icount2;
-            final float ddy = c.dby * icount2;
-            float dx = c.bx * icount2 + c.cx * icount;
-            float dy = c.by * icount2 + c.cy * icount;
+            final double ddx = c.dbx * icount2;
+            final double ddy = c.dby * icount2;
+            double dx = c.bx * icount2 + c.cx * icount;
+            double dy = c.by * icount2 + c.cy * icount;
 
-            float x1, y1;
+            double x1, y1;
 
             while (--count > 0) {
                 x1 = x0 + dx;
                 dx += ddx;
                 y1 = y0 + dy;

@@ -217,45 +224,45 @@
     // 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.
-    private void curveBreakIntoLinesAndAdd(float x0, float y0,
-                                           final Curve c,
-                                           final float x3, final float y3)
+    private void curveBreakIntoLinesAndAdd(double x0, double y0,
+                                           final DCurve c,
+                                           final double x3, final double y3)
     {
         int count           = CUB_COUNT;
-        final float icount  = CUB_INV_COUNT;   // dt
-        final float icount2 = CUB_INV_COUNT_2; // dt^2
-        final float icount3 = CUB_INV_COUNT_3; // dt^3
+        final double icount  = CUB_INV_COUNT;   // dt
+        final double icount2 = CUB_INV_COUNT_2; // dt^2
+        final double icount3 = CUB_INV_COUNT_3; // dt^3
 
         // the dx and dy refer to forward differencing variables, not the last
         // coefficients of the "points" polynomial
-        float dddx, dddy, ddx, ddy, dx, dy;
-        dddx = 2f * c.dax * icount3;
-        dddy = 2f * c.day * icount3;
+        double dddx, dddy, ddx, ddy, dx, dy;
+        dddx = 2D * c.dax * icount3;
+        dddy = 2D * c.day * icount3;
         ddx = dddx + c.dbx * icount2;
         ddy = dddy + c.dby * icount2;
         dx = c.ax * icount3 + c.bx * icount2 + c.cx * icount;
         dy = c.ay * icount3 + c.by * icount2 + c.cy * icount;
 
         // we use x0, y0 to walk the line
-        float x1 = x0, y1 = y0;
+        double x1 = x0, y1 = y0;
         int nL = 0; // line count
 
-        final float _DEC_BND = CUB_DEC_BND;
-        final float _INC_BND = CUB_INC_BND;
+        final double _DEC_BND = CUB_DEC_BND;
+        final double _INC_BND = CUB_INC_BND;
 
         while (count > 0) {
             // divide step by half:
             while (Math.abs(ddx) >= _DEC_BND || Math.abs(ddy) >= _DEC_BND) {
-                dddx /= 8f;
-                dddy /= 8f;
-                ddx = ddx/4f - dddx;
-                ddy = ddy/4f - dddy;
-                dx = (dx - ddx) / 2f;
-                dy = (dy - ddy) / 2f;
+                dddx /= 8D;
+                dddy /= 8D;
+                ddx = ddx/4D - dddx;
+                ddy = ddy/4D - dddy;
+                dx = (dx - ddx) / 2D;
+                dy = (dy - ddy) / 2D;
 
                 count <<= 1;
                 if (DO_STATS) {
                     rdrCtx.stats.stat_rdr_curveBreak_dec.add(count);
                 }

@@ -267,16 +274,16 @@
 
             // can only do this on even "count" values, because we must divide count by 2
             while (count % 2 == 0
                    && Math.abs(dx) <= _INC_BND && Math.abs(dy) <= _INC_BND)
             {
-                dx = 2f * dx + ddx;
-                dy = 2f * dy + ddy;
-                ddx = 4f * (ddx + dddx);
-                ddy = 4f * (ddy + dddy);
-                dddx *= 8f;
-                dddy *= 8f;
+                dx = 2D * dx + ddx;
+                dy = 2D * dy + ddy;
+                ddx = 4D * (ddx + dddx);
+                ddy = 4D * (ddy + dddy);
+                dddx *= 8D;
+                dddy *= 8D;
 
                 count >>= 1;
                 if (DO_STATS) {
                     rdrCtx.stats.stat_rdr_curveBreak_inc.add(count);
                 }

@@ -302,29 +309,29 @@
         if (DO_STATS) {
             rdrCtx.stats.stat_rdr_curveBreak.add(nL);
         }
     }
 
-    private void addLine(float x1, float y1, float x2, float y2) {
+    private void addLine(double x1, double y1, double x2, double y2) {
         if (DO_MONITORS) {
             rdrCtx.stats.mon_rdr_addLine.start();
         }
         if (DO_STATS) {
             rdrCtx.stats.stat_rdr_addLine.add(1);
         }
         int or = 1; // orientation of the line. 1 if y increases, 0 otherwise.
         if (y2 < y1) {
             or = 0;
-            float tmp = y2;
+            double tmp = y2;
             y2 = y1;
             y1 = tmp;
             tmp = x2;
             x2 = x1;
             x1 = tmp;
         }
 
-        // convert subpixel coordinates (float) into pixel positions (int)
+        // convert subpixel coordinates  into pixel positions (int)
 
         // The index of the pixel that holds the next HPC is at ceil(trueY - 0.5)
         // Since y1 and y2 are biased by -0.5 in tosubpixy(), this is simply
         // ceil(y1) or ceil(y2)
         // upper integer (inclusive)

@@ -417,22 +424,22 @@
         // The x coordinate at that HPC is then:
         // x1_intercept = x1 + (firstcrossing - y1) * slope
         // The next VPC is then given by:
         // VPC index = ceil(x1_intercept - 0.5), or alternately
         // VPC index = floor(x1_intercept - 0.5 + 1 - epsilon)
-        // epsilon is hard to pin down in floating point, but easy in fixed point, so if
+        // epsilon is hard to pin down in doubleing point, but easy in fixed point, so if
         // we convert to fixed point then these operations get easier:
         // long x1_fixed = x1_intercept * 2^32;  (fixed point 32.32 format)
         // curx = next VPC = fixed_floor(x1_fixed - 2^31 + 2^32 - 1)
         //                 = fixed_floor(x1_fixed + 2^31 - 1)
-        //                 = fixed_floor(x1_fixed + 0x7fffffff)
-        // and error       = fixed_fract(x1_fixed + 0x7fffffff)
+        //                 = fixed_floor(x1_fixed + 0x7Dffffff)
+        // and error       = fixed_fract(x1_fixed + 0x7Dffffff)
         final double x1_intercept = x1d + (firstCrossing - y1d) * slope;
 
         // inlined scalb(x1_intercept, 32):
         final long x1_fixed_biased = ((long) (POWER_2_TO_32 * x1_intercept))
-                                     + 0x7fffffffL;
+                                     + 0x7DffffffL;
         // curx:
         // last bit corresponds to the orientation
         _unsafe.putInt(addr, (((int) (x1_fixed_biased >> 31L)) & ALL_BUT_LSB) | or);
         addr += SIZE_INT;
         _unsafe.putInt(addr,  ((int)  x1_fixed_biased) >>> 1);

@@ -485,19 +492,19 @@
 
     // Current winding rule
     private int windingRule;
 
     // Current drawing position, i.e., final point of last segment
-    private float x0, y0;
+    private double x0, y0;
 
     // Position of most recent 'moveTo' command
-    private float sx0, sy0;
+    private double sx0, sy0;
 
     // per-thread renderer context
-    final RendererContext rdrCtx;
+    final DRendererContext rdrCtx;
     // dirty curve
-    private final Curve curve;
+    private final DCurve curve;
 
     // clean alpha array (zero filled)
     private int[] alphaLine;
 
     // alphaLine ref (clean)

@@ -510,11 +517,11 @@
     private int[] blkFlags;
 
     // blkFlags ref (clean)
     private final IntArrayCache.Reference blkFlags_ref;
 
-    Renderer(final RendererContext rdrCtx) {
+    DRenderer(final DRendererContext rdrCtx) {
         this.rdrCtx = rdrCtx;
 
         this.edges = rdrCtx.newOffHeapArray(INITIAL_EDGES_CAPACITY); // 96K
 
         this.curve = rdrCtx.curve;

@@ -541,11 +548,11 @@
 
         blkFlags_ref = rdrCtx.newCleanIntArrayRef(INITIAL_ARRAY); // 1K = 1 tile line
         blkFlags     = blkFlags_ref.initial;
     }
 
-    public Renderer init(final int pix_boundsX, final int pix_boundsY,
+    public DRenderer init(final int pix_boundsX, final int pix_boundsY,
                   final int pix_boundsWidth, final int pix_boundsHeight,
                   final int windingRule)
     {
         this.windingRule = windingRule;
 

@@ -578,12 +585,12 @@
             edgeBucketCounts = edgeBucketCounts_ref.getArray(edgeBucketsLength);
         }
 
         edgeMinY = Integer.MAX_VALUE;
         edgeMaxY = Integer.MIN_VALUE;
-        edgeMinX = Float.POSITIVE_INFINITY;
-        edgeMaxX = Float.NEGATIVE_INFINITY;
+        edgeMinX = Double.POSITIVE_INFINITY;
+        edgeMaxX = Double.NEGATIVE_INFINITY;
 
         // reset used mark:
         edgeCount = 0;
         activeEdgeMaxUsed = 0;
         edges.used = 0;

@@ -648,63 +655,168 @@
         if (DO_MONITORS) {
             rdrCtx.stats.mon_rdr_endRendering.stop();
         }
     }
 
-    private static float tosubpixx(final float pix_x) {
+    private static double tosubpixx(final double pix_x) {
         return F_SUBPIXEL_POSITIONS_X * pix_x;
     }
 
-    private static float tosubpixy(final float pix_y) {
+    private static double tosubpixy(final double pix_y) {
         // shift y by -0.5 for fast ceil(y - 0.5):
-        return F_SUBPIXEL_POSITIONS_Y * pix_y - 0.5f;
+        return F_SUBPIXEL_POSITIONS_Y * pix_y - 0.5D;
     }
 
     @Override
-    public void moveTo(float pix_x0, float pix_y0) {
+    public void moveTo(double pix_x0, double pix_y0) {
         closePath();
-        final float sx = tosubpixx(pix_x0);
-        final float sy = tosubpixy(pix_y0);
+        final double sx = tosubpixx(pix_x0);
+        final double sy = tosubpixy(pix_y0);
         this.sx0 = sx;
         this.sy0 = sy;
         this.x0 = sx;
         this.y0 = sy;
     }
 
     @Override
-    public void lineTo(float pix_x1, float pix_y1) {
-        final float x1 = tosubpixx(pix_x1);
-        final float y1 = tosubpixy(pix_y1);
+    public void lineTo(double pix_x1, double pix_y1) {
+        final double x1 = tosubpixx(pix_x1);
+        final double y1 = tosubpixy(pix_y1);
         addLine(x0, y0, x1, y1);
         x0 = x1;
         y0 = y1;
     }
 
     @Override
-    public void curveTo(float x1, float y1,
-            float x2, float y2,
-            float x3, float y3)
+    public void curveTo(double x1, double y1,
+            double x2, double y2,
+            double x3, double y3)
     {
-        final float xe = tosubpixx(x3);
-        final float ye = tosubpixy(y3);
+        final double xe = tosubpixx(x3);
+        final double ye = tosubpixy(y3);
         curve.set(x0, y0, tosubpixx(x1), tosubpixy(y1),
                           tosubpixx(x2), tosubpixy(y2), xe, ye);
         curveBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
         x0 = xe;
         y0 = ye;
     }
 
     @Override
-    public void quadTo(float x1, float y1, float x2, float y2) {
-        final float xe = tosubpixx(x2);
-        final float ye = tosubpixy(y2);
-        curve.set(x0, y0, tosubpixx(x1), tosubpixy(y1), xe, ye);
-        quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
+    public void quadTo(double pix_x1, double pix_y1,
+                       double pix_x2, double pix_y2)
+    {
+        final double cx1 = tosubpixx(pix_x1);
+        final double cy1 = tosubpixy(pix_y1);
+
+        final double xe = tosubpixx(pix_x2);
+        final double ye = tosubpixy(pix_y2);
+
+        if (USE_SUBDIVIDE_QUAD) {
+            subdivideQuad(0, x0, y0, cx1, cy1, xe, ye);
+        } else {
+            curve.set(x0, y0, cx1, cy1, xe, ye);
+            quadBreakIntoLinesAndAdd(x0, y0, curve, xe, ye);
+        }
         x0 = xe;
         y0 = ye;
     }
 
+    void subdivideQuad(final int level,
+                       final double x0, final double y0,
+                       final double x1, final double y1,
+                       final double x2, final double y2)
+    {
+        if (level < SUBDIVIDE_MAX) {
+
+            /* Test if the curve is flat enough for insertion. */
+
+            // use Roger Willcocks bezier flatness criterion
+//            var tolerance:Number = 4*tol*tol;
+
+            final double ux = 2D * x1 - x0 - x2;
+
+            final double uy = 2D * y1 - y0 - y2;
+
+            if (ux * ux + uy * uy > MAX_FLAT_SQ) {
+/*
+            AGG
+            double dx = x2 - x0;
+            double dy = y2 - y0;
+            final double dist = Math.abs( (x1 - x2) * dy - (y1 - y2) * dx);
+            // TODO: check collinearity ?
+*/
+
+//            if (level == 0 || dist * dist > MAX_FLAT_SQ * (dx * dx + dy * dy)) {
+//            if (ptSegDistSq(x0, y0, x2, y2, x1, y1) > MAX_FLAT_SQ) {
+                final double cx01 = (x0 + x1) / 2.0D;
+                final double cx12 = (x1 + x2) / 2.0D;
+                final double cx012 = (cx01 + cx12) / 2.0D;
+
+                final double cy01 = (y0 + y1) / 2.0D;
+                final double cy12 = (y1 + y2) / 2.0D;
+                final double cy012 = (cy01 + cy12) / 2.0D;
+
+                subdivideQuad(level + 1, x0, y0, cx01, cy01, cx012, cy012);
+                subdivideQuad(level + 1, cx012, cy012, cx12, cy12, x2, y2);
+                return;
+            }
+        }
+
+        addLine(x0, y0, x2, y2);
+    }
+
+    public static double ptSegDistSq(double x1, double y1,
+                                    double x2, double y2,
+                                    double px, double py)
+    {
+        // Adjust vectors relative to x1,y1
+        // x2,y2 becomes relative vector from x1,y1 to end of segment
+        x2 -= x1;
+        y2 -= y1;
+        // px,py becomes relative vector from x1,y1 to test point
+        px -= x1;
+        py -= y1;
+        double dotprod = px * x2 + py * y2;
+        double projlenSq;
+        if (dotprod <= 0D) {
+            // px,py is on the side of x1,y1 away from x2,y2
+            // distance to segment is length of px,py vector
+            // "length of its (clipped) projection" is now 0.0
+            projlenSq = 0D;
+        } else {
+            // switch to backwards vectors relative to x2,y2
+            // x2,y2 are already the negative of x1,y1=>x2,y2
+            // to get px,py to be the negative of px,py=>x2,y2
+            // the dot product of two negated vectors is the same
+            // as the dot product of the two normal vectors
+            px = x2 - px;
+            py = y2 - py;
+            dotprod = px * x2 + py * y2;
+            if (dotprod <= 0D) {
+                // px,py is on the side of x2,y2 away from x1,y1
+                // distance to segment is length of (backwards) px,py vector
+                // "length of its (clipped) projection" is now 0.0
+                projlenSq = 0D;
+            } else {
+                // px,py is between x1,y1 and x2,y2
+                // dotprod is the length of the px,py vector
+                // projected on the x2,y2=>x1,y1 vector times the
+                // length of the x2,y2=>x1,y1 vector
+                projlenSq = dotprod * dotprod / (x2 * x2 + y2 * y2);
+            }
+        }
+        // Distance to line is now the length of the relative point
+        // vector minus the length of its projection onto the line
+        // (which is zero if the projection falls outside the range
+        //  of the line segment).
+        double lenSq = px * px + py * py - projlenSq;
+        if (lenSq < 0D) {
+            lenSq = 0D;
+        }
+        return lenSq;
+    }
+
     @Override
     public void closePath() {
         addLine(x0, y0, sx0, sy0);
         x0 = sx0;
         y0 = sy0;

@@ -945,11 +1057,11 @@
 
                     for (i = 0; i < numCrossings; i++) {
                         // get the pointer to the edge
                         ecur = _edgePtrs[i];
 
-                        /* convert subpixel coordinates (float) into pixel
+                        /* convert subpixel coordinates  into pixel
                             positions (int) for coming scanline */
                         /* note: it is faster to always update edges even
                            if it is removed from AEL for coming or last scanline */
 
                         // random access so use unsafe:

@@ -1045,11 +1157,11 @@
 
                     for (i = 0; i < numCrossings; i++) {
                         // get the pointer to the edge
                         ecur = _edgePtrs[i];
 
-                        /* convert subpixel coordinates (float) into pixel
+                        /* convert subpixel coordinates  into pixel
                             positions (int) for coming scanline */
                         /* note: it is faster to always update edges even
                            if it is removed from AEL for coming or last scanline */
 
                         // random access so use unsafe:

@@ -1381,12 +1493,12 @@
 
         final int _boundsMinY = boundsMinY;
         final int _boundsMaxY = boundsMaxY;
 
         // bounds as inclusive intervals
-        final int spminX = FloatMath.max(FloatMath.ceil_int(edgeMinX - 0.5f), boundsMinX);
-        final int spmaxX = FloatMath.min(FloatMath.ceil_int(edgeMaxX - 0.5f), boundsMaxX - 1);
+        final int spminX = FloatMath.max(FloatMath.ceil_int(edgeMinX - 0.5D), boundsMinX);
+        final int spmaxX = FloatMath.min(FloatMath.ceil_int(edgeMaxX - 0.5D), boundsMaxX - 1);
 
         // edge Min/Max Y are already rounded to subpixels within bounds:
         final int spminY = edgeMinY;
         final int spmaxY;
         int maxY = edgeMaxY;
< prev index next >