< prev index next >

src/java.desktop/share/classes/sun/java2d/marlin/DDasher.java

Print this page




  30 import sun.java2d.marlin.DTransformingPathConsumer2D.CurveClipSplitter;
  31 
  32 /**
  33  * The <code>DDasher</code> class takes a series of linear commands
  34  * (<code>moveTo</code>, <code>lineTo</code>, <code>close</code> and
  35  * <code>end</code>) and breaks them into smaller segments according to a
  36  * dash pattern array and a starting dash phase.
  37  *
  38  * <p> Issues: in J2Se, a zero length dash segment as drawn as a very
  39  * short dash, whereas Pisces does not draw anything.  The PostScript
  40  * semantics are unclear.
  41  *
  42  */
  43 final class DDasher implements DPathConsumer2D, MarlinConst {
  44 
  45     /* huge circle with radius ~ 2E9 only needs 12 subdivision levels */
  46     static final int REC_LIMIT = 16;
  47     static final double CURVE_LEN_ERR = MarlinProperties.getCurveLengthError(); // 0.01 initial
  48     static final double MIN_T_INC = 1.0d / (1 << REC_LIMIT);
  49 


  50     // 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
  52     // punt and override the phase to just be 0 past that point.
  53     static final double MAX_CYCLES = 16000000.0d;
  54 
  55     private DPathConsumer2D out;
  56     private double[] dash;
  57     private int dashLen;
  58     private double startPhase;
  59     private boolean startDashOn;
  60     private int startIdx;
  61 
  62     private boolean starting;
  63     private boolean needsMoveTo;
  64 
  65     private int idx;
  66     private boolean dashOn;
  67     private double phase;
  68 
  69     // The starting point of the path


 252         this.dashOn = this.startDashOn;
 253         this.phase = this.startPhase;
 254         this.cx0 = x0;
 255         this.cy0 = y0;
 256 
 257         // update starting point:
 258         this.sx0 = x0;
 259         this.sy0 = y0;
 260         this.starting = true;
 261 
 262         if (clipRect != null) {
 263             final int outcode = DHelpers.outcode(x0, y0, clipRect);
 264             this.cOutCode = outcode;
 265             this.outside = false;
 266             this.totalSkipLen = 0.0d;
 267         }
 268     }
 269 
 270     private void emitSeg(double[] buf, int off, int type) {
 271         switch (type) {



 272         case 8:
 273             out.curveTo(buf[off    ], buf[off + 1],
 274                         buf[off + 2], buf[off + 3],
 275                         buf[off + 4], buf[off + 5]);
 276             return;
 277         case 6:
 278             out.quadTo(buf[off    ], buf[off + 1],
 279                        buf[off + 2], buf[off + 3]);
 280             return;
 281         case 4:
 282             out.lineTo(buf[off], buf[off + 1]);
 283             return;
 284         default:
 285         }
 286     }
 287 
 288     private void emitFirstSegments() {
 289         final double[] fSegBuf = firstSegmentsBuffer;
 290 
 291         for (int i = 0, len = firstSegidx; i < len; ) {
 292             int type = (int)fSegBuf[i];
 293             emitSeg(fSegBuf, i + 1, type);
 294             i += (type - 1);
 295         }
 296         firstSegidx = 0;
 297     }
 298 
 299     // precondition: pts must be in relative coordinates (relative to x0,y0)
 300     private void goTo(final double[] pts, final int off, final int type,
 301                       final boolean on)
 302     {
 303         final int index = off + type;


 344         // small arraycopy (2, 4 or 6) but with offset:
 345         System.arraycopy(pts, off, buf, segIdx, len);
 346         firstSegidx = segIdx + len;
 347     }
 348 
 349     @Override
 350     public void lineTo(final double x1, final double y1) {
 351         final int outcode0 = this.cOutCode;
 352 
 353         if (clipRect != null) {
 354             final int outcode1 = DHelpers.outcode(x1, y1, clipRect);
 355 
 356             // Should clip
 357             final int orCode = (outcode0 | outcode1);
 358 
 359             if (orCode != 0) {
 360                 final int sideCode = outcode0 & outcode1;
 361 
 362                 // basic rejection criteria:
 363                 if (sideCode == 0) {
 364                     // ovelap clip:
 365                     if (subdivide) {
 366                         // avoid reentrance
 367                         subdivide = false;
 368                         // subdivide curve => callback with subdivided parts:
 369                         boolean ret = curveSplitter.splitLine(cx0, cy0, x1, y1,
 370                                                               orCode, this);
 371                         // reentrance is done:
 372                         subdivide = true;
 373                         if (ret) {
 374                             return;
 375                         }
 376                     }
 377                     // already subdivided so render it
 378                 } else {
 379                     this.cOutCode = outcode1;
 380                     skipLineTo(x1, y1);
 381                     return;
 382                 }
 383             }
 384 


 399 
 400         double len = dx * dx + dy * dy;
 401         if (len == 0.0d) {
 402             return;
 403         }
 404         len = Math.sqrt(len);
 405 
 406         // The scaling factors needed to get the dx and dy of the
 407         // transformed dash segments.
 408         final double cx = dx / len;
 409         final double cy = dy / len;
 410 
 411         final double[] _curCurvepts = curCurvepts;
 412         final double[] _dash = dash;
 413         final int _dashLen = this.dashLen;
 414 
 415         int _idx = idx;
 416         boolean _dashOn = dashOn;
 417         double _phase = phase;
 418 
 419         double leftInThisDashSegment, d;
 420 
 421         while (true) {
 422             d = _dash[_idx];
 423             leftInThisDashSegment = d - _phase;
 424 
 425             if (len <= leftInThisDashSegment) {
 426                 _curCurvepts[0] = x1;
 427                 _curCurvepts[1] = y1;
 428 
 429                 goTo(_curCurvepts, 0, 4, _dashOn);
 430 
 431                 // Advance phase within current dash segment
 432                 _phase += len;
 433 
 434                 // TODO: compare double values using epsilon:
 435                 if (len == leftInThisDashSegment) {
 436                     _phase = 0.0d;
 437                     _idx = (_idx + 1) % _dashLen;
 438                     _dashOn = !_dashOn;
 439                 }
 440                 break;
 441             }
 442 
 443             if (_phase == 0.0d) {
 444                 _curCurvepts[0] = cx0 + d * cx;
 445                 _curCurvepts[1] = cy0 + d * cy;
 446             } else {
 447                 _curCurvepts[0] = cx0 + leftInThisDashSegment * cx;
 448                 _curCurvepts[1] = cy0 + leftInThisDashSegment * cy;
 449             }
 450 
 451             goTo(_curCurvepts, 0, 4, _dashOn);
 452 
 453             len -= leftInThisDashSegment;
 454             // Advance to next dash segment
 455             _idx = (_idx + 1) % _dashLen;
 456             _dashOn = !_dashOn;
 457             _phase = 0.0d;
 458         }
 459         // Save local state:
 460         idx = _idx;
 461         dashOn = _dashOn;
 462         phase = _phase;
 463     }
 464 
 465     private void skipLineTo(final double x1, final double y1) {
 466         final double dx = x1 - cx0;
 467         final double dy = y1 - cy0;
 468 
 469         double len = dx * dx + dy * dy;
 470         if (len != 0.0d) {
 471             len = Math.sqrt(len);
 472         }
 473 


 489 
 490         final double[] _dash = dash;
 491         final int _dashLen = this.dashLen;
 492 
 493         int _idx = idx;
 494         boolean _dashOn = dashOn;
 495         double _phase = phase;
 496 
 497         // -2 to ensure having 2 iterations of the post-loop
 498         // to compensate the remaining phase
 499         final long fullcycles = (long)Math.floor(len / cycleLen) - 2L;
 500 
 501         if (fullcycles > 0L) {
 502             len -= cycleLen * fullcycles;
 503 
 504             final long iterations = fullcycles * _dashLen;
 505             _idx = (int) (iterations + _idx) % _dashLen;
 506             _dashOn = (iterations + (_dashOn ? 1L : 0L) & 1L) == 1L;
 507         }
 508 
 509         double leftInThisDashSegment, d;
 510 
 511         while (true) {
 512             d = _dash[_idx];
 513             leftInThisDashSegment = d - _phase;
 514 
 515             if (len <= leftInThisDashSegment) {
 516                 // Advance phase within current dash segment
 517                 _phase += len;
 518 
 519                 // TODO: compare double values using epsilon:
 520                 if (len == leftInThisDashSegment) {
 521                     _phase = 0.0d;
 522                     _idx = (_idx + 1) % _dashLen;
 523                     _dashOn = !_dashOn;
 524                 }
 525                 break;
 526             }
 527 
 528             len -= leftInThisDashSegment;
 529             // Advance to next dash segment
 530             _idx = (_idx + 1) % _dashLen;
 531             _dashOn = !_dashOn;
 532             _phase = 0.0d;
 533         }
 534         // Save local state:
 535         idx = _idx;
 536         dashOn = _dashOn;
 537         phase = _phase;
 538     }
 539 
 540     // preconditions: curCurvepts must be an array of length at least 2 * type,
 541     // that contains the curve we want to dash in the first type elements
 542     private void somethingTo(final int type) {
 543         final double[] _curCurvepts = curCurvepts;
 544         if (pointCurve(_curCurvepts, type)) {
 545             return;
 546         }
 547         final LengthIterator _li = li;
 548         final double[] _dash = dash;


 562 
 563         while ((t = _li.next(leftInThisDashSegment)) < 1.0d) {
 564             if (t != 0.0d) {
 565                 DHelpers.subdivideAt((t - prevT) / (1.0d - prevT),
 566                                     _curCurvepts, curCurveoff,
 567                                     _curCurvepts, 0, type);
 568                 prevT = t;
 569                 goTo(_curCurvepts, 2, type, _dashOn);
 570                 curCurveoff = type;
 571             }
 572             // Advance to next dash segment
 573             _idx = (_idx + 1) % _dashLen;
 574             _dashOn = !_dashOn;
 575             _phase = 0.0d;
 576             leftInThisDashSegment = _dash[_idx];
 577         }
 578 
 579         goTo(_curCurvepts, curCurveoff + 2, type, _dashOn);
 580 
 581         _phase += _li.lastSegLen();
 582         if (_phase >= _dash[_idx]) {


 583             _phase = 0.0d;
 584             _idx = (_idx + 1) % _dashLen;
 585             _dashOn = !_dashOn;
 586         }
 587         // Save local state:
 588         idx = _idx;
 589         dashOn = _dashOn;
 590         phase = _phase;
 591 
 592         // reset LengthIterator:
 593         _li.reset();
 594     }
 595 
 596     private void skipSomethingTo(final int type) {
 597         final double[] _curCurvepts = curCurvepts;
 598         if (pointCurve(_curCurvepts, type)) {
 599             return;
 600         }
 601         final LengthIterator _li = li;
 602 


 921 
 922     @Override
 923     public void curveTo(final double x1, final double y1,
 924                         final double x2, final double y2,
 925                         final double x3, final double y3)
 926     {
 927         final int outcode0 = this.cOutCode;
 928 
 929         if (clipRect != null) {
 930             final int outcode1 = DHelpers.outcode(x1, y1, clipRect);
 931             final int outcode2 = DHelpers.outcode(x2, y2, clipRect);
 932             final int outcode3 = DHelpers.outcode(x3, y3, clipRect);
 933 
 934             // Should clip
 935             final int orCode = (outcode0 | outcode1 | outcode2 | outcode3);
 936             if (orCode != 0) {
 937                 final int sideCode = outcode0 & outcode1 & outcode2 & outcode3;
 938 
 939                 // basic rejection criteria:
 940                 if (sideCode == 0) {
 941                     // ovelap clip:
 942                     if (subdivide) {
 943                         // avoid reentrance
 944                         subdivide = false;
 945                         // subdivide curve => callback with subdivided parts:
 946                         boolean ret = curveSplitter.splitCurve(cx0, cy0, x1, y1, x2, y2, x3, y3,
 947                                                                orCode, this);
 948                         // reentrance is done:
 949                         subdivide = true;
 950                         if (ret) {
 951                             return;
 952                         }
 953                     }
 954                     // already subdivided so render it
 955                 } else {
 956                     this.cOutCode = outcode3;
 957                     skipCurveTo(x1, y1, x2, y2, x3, y3);
 958                     return;
 959                 }
 960             }
 961 


1007         this.cy0 = y3;
1008     }
1009 
1010     @Override
1011     public void quadTo(final double x1, final double y1,
1012                        final double x2, final double y2)
1013     {
1014         final int outcode0 = this.cOutCode;
1015 
1016         if (clipRect != null) {
1017             final int outcode1 = DHelpers.outcode(x1, y1, clipRect);
1018             final int outcode2 = DHelpers.outcode(x2, y2, clipRect);
1019 
1020             // Should clip
1021             final int orCode = (outcode0 | outcode1 | outcode2);
1022             if (orCode != 0) {
1023                 final int sideCode = outcode0 & outcode1 & outcode2;
1024 
1025                 // basic rejection criteria:
1026                 if (sideCode == 0) {
1027                     // ovelap clip:
1028                     if (subdivide) {
1029                         // avoid reentrance
1030                         subdivide = false;
1031                         // subdivide curve => call lineTo() with subdivided curves:
1032                         boolean ret = curveSplitter.splitQuad(cx0, cy0, x1, y1,
1033                                                               x2, y2, orCode, this);
1034                         // reentrance is done:
1035                         subdivide = true;
1036                         if (ret) {
1037                             return;
1038                         }
1039                     }
1040                     // already subdivided so render it
1041                 } else {
1042                     this.cOutCode = outcode2;
1043                     skipQuadTo(x1, y1, x2, y2);
1044                     return;
1045                 }
1046             }
1047 




  30 import sun.java2d.marlin.DTransformingPathConsumer2D.CurveClipSplitter;
  31 
  32 /**
  33  * The <code>DDasher</code> class takes a series of linear commands
  34  * (<code>moveTo</code>, <code>lineTo</code>, <code>close</code> and
  35  * <code>end</code>) and breaks them into smaller segments according to a
  36  * dash pattern array and a starting dash phase.
  37  *
  38  * <p> Issues: in J2Se, a zero length dash segment as drawn as a very
  39  * short dash, whereas Pisces does not draw anything.  The PostScript
  40  * semantics are unclear.
  41  *
  42  */
  43 final class DDasher implements DPathConsumer2D, MarlinConst {
  44 
  45     /* huge circle with radius ~ 2E9 only needs 12 subdivision levels */
  46     static final int REC_LIMIT = 16;
  47     static final double CURVE_LEN_ERR = MarlinProperties.getCurveLengthError(); // 0.01 initial
  48     static final double MIN_T_INC = 1.0d / (1 << REC_LIMIT);
  49 
  50     static final double EPS = 1e-6d;
  51 
  52     // More than 24 bits of mantissa means we can no longer accurately
  53     // measure the number of times cycled through the dash array so we
  54     // punt and override the phase to just be 0 past that point.
  55     static final double MAX_CYCLES = 16000000.0d;
  56 
  57     private DPathConsumer2D out;
  58     private double[] dash;
  59     private int dashLen;
  60     private double startPhase;
  61     private boolean startDashOn;
  62     private int startIdx;
  63 
  64     private boolean starting;
  65     private boolean needsMoveTo;
  66 
  67     private int idx;
  68     private boolean dashOn;
  69     private double phase;
  70 
  71     // The starting point of the path


 254         this.dashOn = this.startDashOn;
 255         this.phase = this.startPhase;
 256         this.cx0 = x0;
 257         this.cy0 = y0;
 258 
 259         // update starting point:
 260         this.sx0 = x0;
 261         this.sy0 = y0;
 262         this.starting = true;
 263 
 264         if (clipRect != null) {
 265             final int outcode = DHelpers.outcode(x0, y0, clipRect);
 266             this.cOutCode = outcode;
 267             this.outside = false;
 268             this.totalSkipLen = 0.0d;
 269         }
 270     }
 271 
 272     private void emitSeg(double[] buf, int off, int type) {
 273         switch (type) {
 274         case 4:
 275             out.lineTo(buf[off], buf[off + 1]);
 276             return;
 277         case 8:
 278             out.curveTo(buf[off    ], buf[off + 1],
 279                         buf[off + 2], buf[off + 3],
 280                         buf[off + 4], buf[off + 5]);
 281             return;
 282         case 6:
 283             out.quadTo(buf[off    ], buf[off + 1],
 284                        buf[off + 2], buf[off + 3]);
 285             return;



 286         default:
 287         }
 288     }
 289 
 290     private void emitFirstSegments() {
 291         final double[] fSegBuf = firstSegmentsBuffer;
 292 
 293         for (int i = 0, len = firstSegidx; i < len; ) {
 294             int type = (int)fSegBuf[i];
 295             emitSeg(fSegBuf, i + 1, type);
 296             i += (type - 1);
 297         }
 298         firstSegidx = 0;
 299     }
 300 
 301     // precondition: pts must be in relative coordinates (relative to x0,y0)
 302     private void goTo(final double[] pts, final int off, final int type,
 303                       final boolean on)
 304     {
 305         final int index = off + type;


 346         // small arraycopy (2, 4 or 6) but with offset:
 347         System.arraycopy(pts, off, buf, segIdx, len);
 348         firstSegidx = segIdx + len;
 349     }
 350 
 351     @Override
 352     public void lineTo(final double x1, final double y1) {
 353         final int outcode0 = this.cOutCode;
 354 
 355         if (clipRect != null) {
 356             final int outcode1 = DHelpers.outcode(x1, y1, clipRect);
 357 
 358             // Should clip
 359             final int orCode = (outcode0 | outcode1);
 360 
 361             if (orCode != 0) {
 362                 final int sideCode = outcode0 & outcode1;
 363 
 364                 // basic rejection criteria:
 365                 if (sideCode == 0) {
 366                     // overlap clip:
 367                     if (subdivide) {
 368                         // avoid reentrance
 369                         subdivide = false;
 370                         // subdivide curve => callback with subdivided parts:
 371                         boolean ret = curveSplitter.splitLine(cx0, cy0, x1, y1,
 372                                                               orCode, this);
 373                         // reentrance is done:
 374                         subdivide = true;
 375                         if (ret) {
 376                             return;
 377                         }
 378                     }
 379                     // already subdivided so render it
 380                 } else {
 381                     this.cOutCode = outcode1;
 382                     skipLineTo(x1, y1);
 383                     return;
 384                 }
 385             }
 386 


 401 
 402         double len = dx * dx + dy * dy;
 403         if (len == 0.0d) {
 404             return;
 405         }
 406         len = Math.sqrt(len);
 407 
 408         // The scaling factors needed to get the dx and dy of the
 409         // transformed dash segments.
 410         final double cx = dx / len;
 411         final double cy = dy / len;
 412 
 413         final double[] _curCurvepts = curCurvepts;
 414         final double[] _dash = dash;
 415         final int _dashLen = this.dashLen;
 416 
 417         int _idx = idx;
 418         boolean _dashOn = dashOn;
 419         double _phase = phase;
 420 
 421         double leftInThisDashSegment, rem;
 422 
 423         while (true) {
 424             leftInThisDashSegment = _dash[_idx] - _phase;
 425             rem = len - leftInThisDashSegment;
 426 
 427             if (rem <= EPS) {
 428                 _curCurvepts[0] = x1;
 429                 _curCurvepts[1] = y1;
 430 
 431                 goTo(_curCurvepts, 0, 4, _dashOn);
 432 
 433                 // Advance phase within current dash segment
 434                 _phase += len;
 435 
 436                 // compare values using epsilon:
 437                 if (Math.abs(rem) <= EPS) {
 438                     _phase = 0.0d;
 439                     _idx = (_idx + 1) % _dashLen;
 440                     _dashOn = !_dashOn;
 441                 }
 442                 break;
 443             }
 444 
 445             _curCurvepts[0] = cx0 + leftInThisDashSegment * cx;
 446             _curCurvepts[1] = cy0 + leftInThisDashSegment * cy;





 447 
 448             goTo(_curCurvepts, 0, 4, _dashOn);
 449 
 450             len = rem;
 451             // Advance to next dash segment
 452             _idx = (_idx + 1) % _dashLen;
 453             _dashOn = !_dashOn;
 454             _phase = 0.0d;
 455         }
 456         // Save local state:
 457         idx = _idx;
 458         dashOn = _dashOn;
 459         phase = _phase;
 460     }
 461 
 462     private void skipLineTo(final double x1, final double y1) {
 463         final double dx = x1 - cx0;
 464         final double dy = y1 - cy0;
 465 
 466         double len = dx * dx + dy * dy;
 467         if (len != 0.0d) {
 468             len = Math.sqrt(len);
 469         }
 470 


 486 
 487         final double[] _dash = dash;
 488         final int _dashLen = this.dashLen;
 489 
 490         int _idx = idx;
 491         boolean _dashOn = dashOn;
 492         double _phase = phase;
 493 
 494         // -2 to ensure having 2 iterations of the post-loop
 495         // to compensate the remaining phase
 496         final long fullcycles = (long)Math.floor(len / cycleLen) - 2L;
 497 
 498         if (fullcycles > 0L) {
 499             len -= cycleLen * fullcycles;
 500 
 501             final long iterations = fullcycles * _dashLen;
 502             _idx = (int) (iterations + _idx) % _dashLen;
 503             _dashOn = (iterations + (_dashOn ? 1L : 0L) & 1L) == 1L;
 504         }
 505 
 506         double leftInThisDashSegment, rem;
 507 
 508         while (true) {
 509             leftInThisDashSegment = _dash[_idx] - _phase;
 510             rem = len - leftInThisDashSegment;
 511 
 512             if (rem <= EPS) {
 513                 // Advance phase within current dash segment
 514                 _phase += len;
 515 
 516                 // compare values using epsilon:
 517                 if (Math.abs(rem) <= EPS) {
 518                     _phase = 0.0d;
 519                     _idx = (_idx + 1) % _dashLen;
 520                     _dashOn = !_dashOn;
 521                 }
 522                 break;
 523             }
 524 
 525             len = rem;
 526             // Advance to next dash segment
 527             _idx = (_idx + 1) % _dashLen;
 528             _dashOn = !_dashOn;
 529             _phase = 0.0d;
 530         }
 531         // Save local state:
 532         idx = _idx;
 533         dashOn = _dashOn;
 534         phase = _phase;
 535     }
 536 
 537     // preconditions: curCurvepts must be an array of length at least 2 * type,
 538     // that contains the curve we want to dash in the first type elements
 539     private void somethingTo(final int type) {
 540         final double[] _curCurvepts = curCurvepts;
 541         if (pointCurve(_curCurvepts, type)) {
 542             return;
 543         }
 544         final LengthIterator _li = li;
 545         final double[] _dash = dash;


 559 
 560         while ((t = _li.next(leftInThisDashSegment)) < 1.0d) {
 561             if (t != 0.0d) {
 562                 DHelpers.subdivideAt((t - prevT) / (1.0d - prevT),
 563                                     _curCurvepts, curCurveoff,
 564                                     _curCurvepts, 0, type);
 565                 prevT = t;
 566                 goTo(_curCurvepts, 2, type, _dashOn);
 567                 curCurveoff = type;
 568             }
 569             // Advance to next dash segment
 570             _idx = (_idx + 1) % _dashLen;
 571             _dashOn = !_dashOn;
 572             _phase = 0.0d;
 573             leftInThisDashSegment = _dash[_idx];
 574         }
 575 
 576         goTo(_curCurvepts, curCurveoff + 2, type, _dashOn);
 577 
 578         _phase += _li.lastSegLen();
 579 
 580         // compare values using epsilon:
 581         if (_phase + EPS >= _dash[_idx]) {
 582             _phase = 0.0d;
 583             _idx = (_idx + 1) % _dashLen;
 584             _dashOn = !_dashOn;
 585         }
 586         // Save local state:
 587         idx = _idx;
 588         dashOn = _dashOn;
 589         phase = _phase;
 590 
 591         // reset LengthIterator:
 592         _li.reset();
 593     }
 594 
 595     private void skipSomethingTo(final int type) {
 596         final double[] _curCurvepts = curCurvepts;
 597         if (pointCurve(_curCurvepts, type)) {
 598             return;
 599         }
 600         final LengthIterator _li = li;
 601 


 920 
 921     @Override
 922     public void curveTo(final double x1, final double y1,
 923                         final double x2, final double y2,
 924                         final double x3, final double y3)
 925     {
 926         final int outcode0 = this.cOutCode;
 927 
 928         if (clipRect != null) {
 929             final int outcode1 = DHelpers.outcode(x1, y1, clipRect);
 930             final int outcode2 = DHelpers.outcode(x2, y2, clipRect);
 931             final int outcode3 = DHelpers.outcode(x3, y3, clipRect);
 932 
 933             // Should clip
 934             final int orCode = (outcode0 | outcode1 | outcode2 | outcode3);
 935             if (orCode != 0) {
 936                 final int sideCode = outcode0 & outcode1 & outcode2 & outcode3;
 937 
 938                 // basic rejection criteria:
 939                 if (sideCode == 0) {
 940                     // overlap clip:
 941                     if (subdivide) {
 942                         // avoid reentrance
 943                         subdivide = false;
 944                         // subdivide curve => callback with subdivided parts:
 945                         boolean ret = curveSplitter.splitCurve(cx0, cy0, x1, y1, x2, y2, x3, y3,
 946                                                                orCode, this);
 947                         // reentrance is done:
 948                         subdivide = true;
 949                         if (ret) {
 950                             return;
 951                         }
 952                     }
 953                     // already subdivided so render it
 954                 } else {
 955                     this.cOutCode = outcode3;
 956                     skipCurveTo(x1, y1, x2, y2, x3, y3);
 957                     return;
 958                 }
 959             }
 960 


1006         this.cy0 = y3;
1007     }
1008 
1009     @Override
1010     public void quadTo(final double x1, final double y1,
1011                        final double x2, final double y2)
1012     {
1013         final int outcode0 = this.cOutCode;
1014 
1015         if (clipRect != null) {
1016             final int outcode1 = DHelpers.outcode(x1, y1, clipRect);
1017             final int outcode2 = DHelpers.outcode(x2, y2, clipRect);
1018 
1019             // Should clip
1020             final int orCode = (outcode0 | outcode1 | outcode2);
1021             if (orCode != 0) {
1022                 final int sideCode = outcode0 & outcode1 & outcode2;
1023 
1024                 // basic rejection criteria:
1025                 if (sideCode == 0) {
1026                     // overlap clip:
1027                     if (subdivide) {
1028                         // avoid reentrance
1029                         subdivide = false;
1030                         // subdivide curve => call lineTo() with subdivided curves:
1031                         boolean ret = curveSplitter.splitQuad(cx0, cy0, x1, y1,
1032                                                               x2, y2, orCode, this);
1033                         // reentrance is done:
1034                         subdivide = true;
1035                         if (ret) {
1036                             return;
1037                         }
1038                     }
1039                     // already subdivided so render it
1040                 } else {
1041                     this.cOutCode = outcode2;
1042                     skipQuadTo(x1, y1, x2, y2);
1043                     return;
1044                 }
1045             }
1046 


< prev index next >