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