< prev index next >

openjfx9/modules/javafx.graphics/src/main/java/com/sun/marlin/Dasher.java

Print this page

        

@@ -21,14 +21,14 @@
  * 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.
  */
 
-package sun.java2d.marlin;
+package com.sun.marlin;
 
 import java.util.Arrays;
-import sun.awt.geom.PathConsumer2D;
+import com.sun.javafx.geom.PathConsumer2D;
 
 /**
  * The <code>Dasher</code> class takes a series of linear commands
  * (<code>moveTo</code>, <code>lineTo</code>, <code>close</code> and
  * <code>end</code>) and breaks them into smaller segments according to a

@@ -37,16 +37,21 @@
  * <p> Issues: in J2Se, a zero length dash segment as drawn as a very
  * short dash, whereas Pisces does not draw anything.  The PostScript
  * semantics are unclear.
  *
  */
-final class Dasher implements sun.awt.geom.PathConsumer2D, MarlinConst {
+public final class Dasher implements PathConsumer2D, MarlinConst {
 
     static final int REC_LIMIT = 4;
     static final float ERR = 0.01f;
     static final float MIN_T_INC = 1f / (1 << REC_LIMIT);
 
+    // More than 24 bits of mantissa means we can no longer accurately
+    // measure the number of times cycled through the dash array so we
+    // punt and override the phase to just be 0 past that point.
+    static final float MAX_CYCLES = 16000000f;
+
     private PathConsumer2D out;
     private float[] dash;
     private int dashLen;
     private float startPhase;
     private boolean startDashOn;

@@ -101,33 +106,63 @@
      * @param dashLen length of the given dash array
      * @param phase a <code>float</code> containing the dash phase
      * @param recycleDashes true to indicate to recycle the given dash array
      * @return this instance
      */
-    Dasher init(final PathConsumer2D out, float[] dash, int dashLen,
+    public Dasher init(final PathConsumer2D out, float[] dash, int dashLen,
                 float phase, boolean recycleDashes)
     {
-        if (phase < 0f) {
-            throw new IllegalArgumentException("phase < 0 !");
-        }
         this.out = out;
 
         // Normalize so 0 <= phase < dash[0]
-        int idx = 0;
+        int sidx = 0;
         dashOn = true;
-        float d;
-        while (phase >= (d = dash[idx])) {
-            phase -= d;
-            idx = (idx + 1) % dashLen;
-            dashOn = !dashOn;
+        float sum = 0f;
+        for (float d : dash) {
+            sum += d;
+        }
+        float cycles = phase / sum;
+        if (phase < 0f) {
+            if (-cycles >= MAX_CYCLES) {
+                phase = 0f;
+            } else {
+                int fullcycles = FloatMath.floor_int(-cycles);
+                if ((fullcycles & dash.length & 1) != 0) {
+                    dashOn = !dashOn;
+                }
+                phase += fullcycles * sum;
+                while (phase < 0f) {
+                    if (--sidx < 0) {
+                        sidx = dash.length - 1;
+                    }
+                    phase += dash[sidx];
+                    dashOn = !dashOn;
+                }
+            }
+        } else if (phase > 0) {
+            if (cycles >= MAX_CYCLES) {
+                phase = 0f;
+            } else {
+                int fullcycles = FloatMath.floor_int(cycles);
+                if ((fullcycles & dash.length & 1) != 0) {
+                    dashOn = !dashOn;
+                }
+                phase -= fullcycles * sum;
+                float d;
+                while (phase >= (d = dash[sidx])) {
+                    phase -= d;
+                    sidx = (sidx + 1) % dash.length;
+                    dashOn = !dashOn;
+                }
+            }
         }
 
         this.dash = dash;
         this.dashLen = dashLen;
         this.startPhase = this.phase = phase;
         this.startDashOn = dashOn;
-        this.startIdx = idx;
+        this.startIdx = sidx;
         this.starting = true;
         needsMoveTo = false;
         firstSegidx = 0;
 
         this.recycleDashes = recycleDashes;

@@ -149,10 +184,25 @@
             dash = dashes_ref.putArray(dash);
         }
         firstSegmentsBuffer = firstSegmentsBuffer_ref.putArray(firstSegmentsBuffer);
     }
 
+    public float[] copyDashArray(final float[] dashes) {
+        final int len = dashes.length;
+        final float[] newDashes;
+        if (len <= MarlinConst.INITIAL_ARRAY) {
+            newDashes = rdrCtx.dasher.dashes_ref.initial;
+        } else {
+            if (DO_STATS) {
+                rdrCtx.stats.stat_array_dasher_dasher.add(len);
+            }
+            newDashes = rdrCtx.dasher.dashes_ref.getArray(len);
+        }
+        System.arraycopy(dashes, 0, newDashes, 0, len);
+        return newDashes;
+    }
+
     @Override
     public void moveTo(float x0, float y0) {
         if (firstSegidx > 0) {
             out.moveTo(sx, sy);
             emitFirstSegments();

@@ -206,11 +256,11 @@
     private void goTo(float[] pts, int off, final int type) {
         float x = pts[off + type - 4];
         float y = pts[off + type - 3];
         if (dashOn) {
             if (starting) {
-                int len = type - 2 + 1;
+                int len = type - 1; // - 2 + 1
                 int segIdx = firstSegidx;
                 float[] buf = firstSegmentsBuffer;
                 if (segIdx + len  > buf.length) {
                     if (DO_STATS) {
                         rdrCtx.stats.stat_array_dasher_firstSegmentsBuffer

@@ -687,12 +737,7 @@
         out.pathDone();
 
         // Dispose this instance:
         dispose();
     }
-
-    @Override
-    public long getNativeConsumer() {
-        throw new InternalError("Dasher does not use a native consumer");
-    }
 }
 
< prev index next >