src/java.desktop/share/classes/sun/java2d/marlin/DDasher.java
changeset 57929 13178f7e75d5
parent 50135 793e481c7641
equal deleted inserted replaced
57928:f95327be136a 57929:13178f7e75d5
    45     /* huge circle with radius ~ 2E9 only needs 12 subdivision levels */
    45     /* huge circle with radius ~ 2E9 only needs 12 subdivision levels */
    46     static final int REC_LIMIT = 16;
    46     static final int REC_LIMIT = 16;
    47     static final double CURVE_LEN_ERR = MarlinProperties.getCurveLengthError(); // 0.01 initial
    47     static final double CURVE_LEN_ERR = MarlinProperties.getCurveLengthError(); // 0.01 initial
    48     static final double MIN_T_INC = 1.0d / (1 << REC_LIMIT);
    48     static final double MIN_T_INC = 1.0d / (1 << REC_LIMIT);
    49 
    49 
       
    50     static final double EPS = 1e-6d;
       
    51 
    50     // More than 24 bits of mantissa means we can no longer accurately
    52     // More than 24 bits of mantissa means we can no longer accurately
    51     // measure the number of times cycled through the dash array so we
    53     // measure the number of times cycled through the dash array so we
    52     // punt and override the phase to just be 0 past that point.
    54     // punt and override the phase to just be 0 past that point.
    53     static final double MAX_CYCLES = 16000000.0d;
    55     static final double MAX_CYCLES = 16000000.0d;
    54 
    56 
   267         }
   269         }
   268     }
   270     }
   269 
   271 
   270     private void emitSeg(double[] buf, int off, int type) {
   272     private void emitSeg(double[] buf, int off, int type) {
   271         switch (type) {
   273         switch (type) {
       
   274         case 4:
       
   275             out.lineTo(buf[off], buf[off + 1]);
       
   276             return;
   272         case 8:
   277         case 8:
   273             out.curveTo(buf[off    ], buf[off + 1],
   278             out.curveTo(buf[off    ], buf[off + 1],
   274                         buf[off + 2], buf[off + 3],
   279                         buf[off + 2], buf[off + 3],
   275                         buf[off + 4], buf[off + 5]);
   280                         buf[off + 4], buf[off + 5]);
   276             return;
   281             return;
   277         case 6:
   282         case 6:
   278             out.quadTo(buf[off    ], buf[off + 1],
   283             out.quadTo(buf[off    ], buf[off + 1],
   279                        buf[off + 2], buf[off + 3]);
   284                        buf[off + 2], buf[off + 3]);
   280             return;
   285             return;
   281         case 4:
       
   282             out.lineTo(buf[off], buf[off + 1]);
       
   283             return;
       
   284         default:
   286         default:
   285         }
   287         }
   286     }
   288     }
   287 
   289 
   288     private void emitFirstSegments() {
   290     private void emitFirstSegments() {
   359             if (orCode != 0) {
   361             if (orCode != 0) {
   360                 final int sideCode = outcode0 & outcode1;
   362                 final int sideCode = outcode0 & outcode1;
   361 
   363 
   362                 // basic rejection criteria:
   364                 // basic rejection criteria:
   363                 if (sideCode == 0) {
   365                 if (sideCode == 0) {
   364                     // ovelap clip:
   366                     // overlap clip:
   365                     if (subdivide) {
   367                     if (subdivide) {
   366                         // avoid reentrance
   368                         // avoid reentrance
   367                         subdivide = false;
   369                         subdivide = false;
   368                         // subdivide curve => callback with subdivided parts:
   370                         // subdivide curve => callback with subdivided parts:
   369                         boolean ret = curveSplitter.splitLine(cx0, cy0, x1, y1,
   371                         boolean ret = curveSplitter.splitLine(cx0, cy0, x1, y1,
   414 
   416 
   415         int _idx = idx;
   417         int _idx = idx;
   416         boolean _dashOn = dashOn;
   418         boolean _dashOn = dashOn;
   417         double _phase = phase;
   419         double _phase = phase;
   418 
   420 
   419         double leftInThisDashSegment, d;
   421         double leftInThisDashSegment, rem;
   420 
   422 
   421         while (true) {
   423         while (true) {
   422             d = _dash[_idx];
   424             leftInThisDashSegment = _dash[_idx] - _phase;
   423             leftInThisDashSegment = d - _phase;
   425             rem = len - leftInThisDashSegment;
   424 
   426 
   425             if (len <= leftInThisDashSegment) {
   427             if (rem <= EPS) {
   426                 _curCurvepts[0] = x1;
   428                 _curCurvepts[0] = x1;
   427                 _curCurvepts[1] = y1;
   429                 _curCurvepts[1] = y1;
   428 
   430 
   429                 goTo(_curCurvepts, 0, 4, _dashOn);
   431                 goTo(_curCurvepts, 0, 4, _dashOn);
   430 
   432 
   431                 // Advance phase within current dash segment
   433                 // Advance phase within current dash segment
   432                 _phase += len;
   434                 _phase += len;
   433 
   435 
   434                 // TODO: compare double values using epsilon:
   436                 // compare values using epsilon:
   435                 if (len == leftInThisDashSegment) {
   437                 if (Math.abs(rem) <= EPS) {
   436                     _phase = 0.0d;
   438                     _phase = 0.0d;
   437                     _idx = (_idx + 1) % _dashLen;
   439                     _idx = (_idx + 1) % _dashLen;
   438                     _dashOn = !_dashOn;
   440                     _dashOn = !_dashOn;
   439                 }
   441                 }
   440                 break;
   442                 break;
   441             }
   443             }
   442 
   444 
   443             if (_phase == 0.0d) {
   445             _curCurvepts[0] = cx0 + leftInThisDashSegment * cx;
   444                 _curCurvepts[0] = cx0 + d * cx;
   446             _curCurvepts[1] = cy0 + leftInThisDashSegment * cy;
   445                 _curCurvepts[1] = cy0 + d * cy;
       
   446             } else {
       
   447                 _curCurvepts[0] = cx0 + leftInThisDashSegment * cx;
       
   448                 _curCurvepts[1] = cy0 + leftInThisDashSegment * cy;
       
   449             }
       
   450 
   447 
   451             goTo(_curCurvepts, 0, 4, _dashOn);
   448             goTo(_curCurvepts, 0, 4, _dashOn);
   452 
   449 
   453             len -= leftInThisDashSegment;
   450             len = rem;
   454             // Advance to next dash segment
   451             // Advance to next dash segment
   455             _idx = (_idx + 1) % _dashLen;
   452             _idx = (_idx + 1) % _dashLen;
   456             _dashOn = !_dashOn;
   453             _dashOn = !_dashOn;
   457             _phase = 0.0d;
   454             _phase = 0.0d;
   458         }
   455         }
   504             final long iterations = fullcycles * _dashLen;
   501             final long iterations = fullcycles * _dashLen;
   505             _idx = (int) (iterations + _idx) % _dashLen;
   502             _idx = (int) (iterations + _idx) % _dashLen;
   506             _dashOn = (iterations + (_dashOn ? 1L : 0L) & 1L) == 1L;
   503             _dashOn = (iterations + (_dashOn ? 1L : 0L) & 1L) == 1L;
   507         }
   504         }
   508 
   505 
   509         double leftInThisDashSegment, d;
   506         double leftInThisDashSegment, rem;
   510 
   507 
   511         while (true) {
   508         while (true) {
   512             d = _dash[_idx];
   509             leftInThisDashSegment = _dash[_idx] - _phase;
   513             leftInThisDashSegment = d - _phase;
   510             rem = len - leftInThisDashSegment;
   514 
   511 
   515             if (len <= leftInThisDashSegment) {
   512             if (rem <= EPS) {
   516                 // Advance phase within current dash segment
   513                 // Advance phase within current dash segment
   517                 _phase += len;
   514                 _phase += len;
   518 
   515 
   519                 // TODO: compare double values using epsilon:
   516                 // compare values using epsilon:
   520                 if (len == leftInThisDashSegment) {
   517                 if (Math.abs(rem) <= EPS) {
   521                     _phase = 0.0d;
   518                     _phase = 0.0d;
   522                     _idx = (_idx + 1) % _dashLen;
   519                     _idx = (_idx + 1) % _dashLen;
   523                     _dashOn = !_dashOn;
   520                     _dashOn = !_dashOn;
   524                 }
   521                 }
   525                 break;
   522                 break;
   526             }
   523             }
   527 
   524 
   528             len -= leftInThisDashSegment;
   525             len = rem;
   529             // Advance to next dash segment
   526             // Advance to next dash segment
   530             _idx = (_idx + 1) % _dashLen;
   527             _idx = (_idx + 1) % _dashLen;
   531             _dashOn = !_dashOn;
   528             _dashOn = !_dashOn;
   532             _phase = 0.0d;
   529             _phase = 0.0d;
   533         }
   530         }
   577         }
   574         }
   578 
   575 
   579         goTo(_curCurvepts, curCurveoff + 2, type, _dashOn);
   576         goTo(_curCurvepts, curCurveoff + 2, type, _dashOn);
   580 
   577 
   581         _phase += _li.lastSegLen();
   578         _phase += _li.lastSegLen();
   582         if (_phase >= _dash[_idx]) {
   579 
       
   580         // compare values using epsilon:
       
   581         if (_phase + EPS >= _dash[_idx]) {
   583             _phase = 0.0d;
   582             _phase = 0.0d;
   584             _idx = (_idx + 1) % _dashLen;
   583             _idx = (_idx + 1) % _dashLen;
   585             _dashOn = !_dashOn;
   584             _dashOn = !_dashOn;
   586         }
   585         }
   587         // Save local state:
   586         // Save local state:
   936             if (orCode != 0) {
   935             if (orCode != 0) {
   937                 final int sideCode = outcode0 & outcode1 & outcode2 & outcode3;
   936                 final int sideCode = outcode0 & outcode1 & outcode2 & outcode3;
   938 
   937 
   939                 // basic rejection criteria:
   938                 // basic rejection criteria:
   940                 if (sideCode == 0) {
   939                 if (sideCode == 0) {
   941                     // ovelap clip:
   940                     // overlap clip:
   942                     if (subdivide) {
   941                     if (subdivide) {
   943                         // avoid reentrance
   942                         // avoid reentrance
   944                         subdivide = false;
   943                         subdivide = false;
   945                         // subdivide curve => callback with subdivided parts:
   944                         // subdivide curve => callback with subdivided parts:
   946                         boolean ret = curveSplitter.splitCurve(cx0, cy0, x1, y1, x2, y2, x3, y3,
   945                         boolean ret = curveSplitter.splitCurve(cx0, cy0, x1, y1, x2, y2, x3, y3,
  1022             if (orCode != 0) {
  1021             if (orCode != 0) {
  1023                 final int sideCode = outcode0 & outcode1 & outcode2;
  1022                 final int sideCode = outcode0 & outcode1 & outcode2;
  1024 
  1023 
  1025                 // basic rejection criteria:
  1024                 // basic rejection criteria:
  1026                 if (sideCode == 0) {
  1025                 if (sideCode == 0) {
  1027                     // ovelap clip:
  1026                     // overlap clip:
  1028                     if (subdivide) {
  1027                     if (subdivide) {
  1029                         // avoid reentrance
  1028                         // avoid reentrance
  1030                         subdivide = false;
  1029                         subdivide = false;
  1031                         // subdivide curve => call lineTo() with subdivided curves:
  1030                         // subdivide curve => call lineTo() with subdivided curves:
  1032                         boolean ret = curveSplitter.splitQuad(cx0, cy0, x1, y1,
  1031                         boolean ret = curveSplitter.splitQuad(cx0, cy0, x1, y1,