525 @Override
526 public void lineTo(final float x1, final float y1) {
527 lineTo(x1, y1, false);
528 }
529
530 private void lineTo(final float x1, final float y1,
531 final boolean force)
532 {
533 final int outcode0 = this.cOutCode;
534
535 if (!force && clipRect != null) {
536 final int outcode1 = Helpers.outcode(x1, y1, clipRect);
537
538 // Should clip
539 final int orCode = (outcode0 | outcode1);
540 if (orCode != 0) {
541 final int sideCode = outcode0 & outcode1;
542
543 // basic rejection criteria:
544 if (sideCode == 0) {
545 // ovelap clip:
546 if (subdivide) {
547 // avoid reentrance
548 subdivide = false;
549 // subdivide curve => callback with subdivided parts:
550 boolean ret = curveSplitter.splitLine(cx0, cy0, x1, y1,
551 orCode, this);
552 // reentrance is done:
553 subdivide = true;
554 if (ret) {
555 return;
556 }
557 }
558 // already subdivided so render it
559 } else {
560 this.cOutCode = outcode1;
561 _moveTo(x1, y1, outcode0);
562 opened = true;
563 return;
564 }
565 }
619 // basic acceptance criteria
620 if ((sOutCode & cOutCode) == 0) {
621 if (cx0 != sx0 || cy0 != sy0) {
622 lineTo(sx0, sy0, true);
623 }
624
625 drawJoin(cdx, cdy, cx0, cy0, sdx, sdy, cmx, cmy, smx, smy, sOutCode);
626
627 emitLineTo(sx0 + smx, sy0 + smy);
628
629 if (opened) {
630 emitLineTo(sx0 - smx, sy0 - smy);
631 } else {
632 emitMoveTo(sx0 - smx, sy0 - smy);
633 }
634 }
635 // Ignore caps like finish(false)
636 emitReverse();
637
638 this.prev = CLOSE;
639
640 if (opened) {
641 // do not emit close
642 opened = false;
643 } else {
644 emitClose();
645 }
646 }
647
648 private void emitReverse() {
649 reverse.popAll(out);
650 }
651
652 @Override
653 public void pathDone() {
654 if (prev == DRAWING_OP_TO) {
655 finish(cOutCode);
656 }
657
658 out.pathDone();
659
660 // this shouldn't matter since this object won't be used
661 // after the call to this method.
662 this.prev = CLOSE;
663
664 // Dispose this instance:
665 dispose();
666 }
667
668 private void finish(final int outcode) {
669 // Problem: impossible to guess if the path will be closed in advance
670 // i.e. if caps must be drawn or not ?
671 // Solution: use the ClosedPathDetector before Stroker to determine
672 // if the path is a closed path or not
673 if (!rdrCtx.closedPath) {
674 if (outcode == 0) {
675 // current point = end's cap:
676 if (capStyle == CAP_ROUND) {
677 drawRoundCap(cx0, cy0, cmx, cmy);
678 } else if (capStyle == CAP_SQUARE) {
679 emitLineTo(cx0 - cmy + cmx, cy0 + cmx + cmy);
680 emitLineTo(cx0 - cmy - cmx, cy0 + cmx - cmy);
681 }
682 }
683 emitReverse();
684
685 if (!capStart) {
686 capStart = true;
687
688 if (sOutCode == 0) {
689 // starting point = initial cap:
690 if (capStyle == CAP_ROUND) {
691 drawRoundCap(sx0, sy0, -smx, -smy);
692 } else if (capStyle == CAP_SQUARE) {
693 emitLineTo(sx0 + smy - smx, sy0 - smx - smy);
694 emitLineTo(sx0 + smy + smx, sy0 - smx + smy);
695 }
696 }
697 }
698 } else {
699 emitReverse();
700 }
701 emitClose();
702 }
703
704 private void emitMoveTo(final float x0, final float y0) {
705 out.moveTo(x0, y0);
706 }
707
708 private void emitLineTo(final float x1, final float y1) {
709 out.lineTo(x1, y1);
710 }
711
712 private void emitLineToRev(final float x1, final float y1) {
713 reverse.pushLine(x1, y1);
714 }
715
716 private void emitLineTo(final float x1, final float y1,
717 final boolean rev)
718 {
719 if (rev) {
1043
1044 @Override
1045 public void curveTo(final float x1, final float y1,
1046 final float x2, final float y2,
1047 final float x3, final float y3)
1048 {
1049 final int outcode0 = this.cOutCode;
1050
1051 if (clipRect != null) {
1052 final int outcode1 = Helpers.outcode(x1, y1, clipRect);
1053 final int outcode2 = Helpers.outcode(x2, y2, clipRect);
1054 final int outcode3 = Helpers.outcode(x3, y3, clipRect);
1055
1056 // Should clip
1057 final int orCode = (outcode0 | outcode1 | outcode2 | outcode3);
1058 if (orCode != 0) {
1059 final int sideCode = outcode0 & outcode1 & outcode2 & outcode3;
1060
1061 // basic rejection criteria:
1062 if (sideCode == 0) {
1063 // ovelap clip:
1064 if (subdivide) {
1065 // avoid reentrance
1066 subdivide = false;
1067 // subdivide curve => callback with subdivided parts:
1068 boolean ret = curveSplitter.splitCurve(cx0, cy0, x1, y1,
1069 x2, y2, x3, y3,
1070 orCode, this);
1071 // reentrance is done:
1072 subdivide = true;
1073 if (ret) {
1074 return;
1075 }
1076 }
1077 // already subdivided so render it
1078 } else {
1079 this.cOutCode = outcode3;
1080 _moveTo(x3, y3, outcode0);
1081 opened = true;
1082 return;
1083 }
1191 this.cmy = (l[kind - 1] - r[kind - 1]) / 2.0f;
1192 }
1193
1194 @Override
1195 public void quadTo(final float x1, final float y1,
1196 final float x2, final float y2)
1197 {
1198 final int outcode0 = this.cOutCode;
1199
1200 if (clipRect != null) {
1201 final int outcode1 = Helpers.outcode(x1, y1, clipRect);
1202 final int outcode2 = Helpers.outcode(x2, y2, clipRect);
1203
1204 // Should clip
1205 final int orCode = (outcode0 | outcode1 | outcode2);
1206 if (orCode != 0) {
1207 final int sideCode = outcode0 & outcode1 & outcode2;
1208
1209 // basic rejection criteria:
1210 if (sideCode == 0) {
1211 // ovelap clip:
1212 if (subdivide) {
1213 // avoid reentrance
1214 subdivide = false;
1215 // subdivide curve => call lineTo() with subdivided curves:
1216 boolean ret = curveSplitter.splitQuad(cx0, cy0, x1, y1,
1217 x2, y2, orCode, this);
1218 // reentrance is done:
1219 subdivide = true;
1220 if (ret) {
1221 return;
1222 }
1223 }
1224 // already subdivided so render it
1225 } else {
1226 this.cOutCode = outcode2;
1227 _moveTo(x2, y2, outcode0);
1228 opened = true;
1229 return;
1230 }
1231 }
|
525 @Override
526 public void lineTo(final float x1, final float y1) {
527 lineTo(x1, y1, false);
528 }
529
530 private void lineTo(final float x1, final float y1,
531 final boolean force)
532 {
533 final int outcode0 = this.cOutCode;
534
535 if (!force && clipRect != null) {
536 final int outcode1 = Helpers.outcode(x1, y1, clipRect);
537
538 // Should clip
539 final int orCode = (outcode0 | outcode1);
540 if (orCode != 0) {
541 final int sideCode = outcode0 & outcode1;
542
543 // basic rejection criteria:
544 if (sideCode == 0) {
545 // overlap clip:
546 if (subdivide) {
547 // avoid reentrance
548 subdivide = false;
549 // subdivide curve => callback with subdivided parts:
550 boolean ret = curveSplitter.splitLine(cx0, cy0, x1, y1,
551 orCode, this);
552 // reentrance is done:
553 subdivide = true;
554 if (ret) {
555 return;
556 }
557 }
558 // already subdivided so render it
559 } else {
560 this.cOutCode = outcode1;
561 _moveTo(x1, y1, outcode0);
562 opened = true;
563 return;
564 }
565 }
619 // basic acceptance criteria
620 if ((sOutCode & cOutCode) == 0) {
621 if (cx0 != sx0 || cy0 != sy0) {
622 lineTo(sx0, sy0, true);
623 }
624
625 drawJoin(cdx, cdy, cx0, cy0, sdx, sdy, cmx, cmy, smx, smy, sOutCode);
626
627 emitLineTo(sx0 + smx, sy0 + smy);
628
629 if (opened) {
630 emitLineTo(sx0 - smx, sy0 - smy);
631 } else {
632 emitMoveTo(sx0 - smx, sy0 - smy);
633 }
634 }
635 // Ignore caps like finish(false)
636 emitReverse();
637
638 this.prev = CLOSE;
639 this.cx0 = sx0;
640 this.cy0 = sy0;
641 this.cOutCode = sOutCode;
642
643 if (opened) {
644 // do not emit close
645 opened = false;
646 } else {
647 emitClose();
648 }
649 }
650
651 private void emitReverse() {
652 reverse.popAll(out);
653 }
654
655 @Override
656 public void pathDone() {
657 if (prev == DRAWING_OP_TO) {
658 finish(cOutCode);
659 }
660
661 out.pathDone();
662
663 // this shouldn't matter since this object won't be used
664 // after the call to this method.
665 this.prev = CLOSE;
666
667 // Dispose this instance:
668 dispose();
669 }
670
671 private void finish(final int outcode) {
672 // Problem: impossible to guess if the path will be closed in advance
673 // i.e. if caps must be drawn or not ?
674 // Solution: use the ClosedPathDetector before Stroker to determine
675 // if the path is a closed path or not
676 if (rdrCtx.closedPath) {
677 emitReverse();
678 } else {
679 if (outcode == 0) {
680 // current point = end's cap:
681 if (capStyle == CAP_ROUND) {
682 drawRoundCap(cx0, cy0, cmx, cmy);
683 } else if (capStyle == CAP_SQUARE) {
684 emitLineTo(cx0 - cmy + cmx, cy0 + cmx + cmy);
685 emitLineTo(cx0 - cmy - cmx, cy0 + cmx - cmy);
686 }
687 }
688 emitReverse();
689
690 if (!capStart) {
691 capStart = true;
692
693 if (sOutCode == 0) {
694 // starting point = initial cap:
695 if (capStyle == CAP_ROUND) {
696 drawRoundCap(sx0, sy0, -smx, -smy);
697 } else if (capStyle == CAP_SQUARE) {
698 emitLineTo(sx0 + smy - smx, sy0 - smx - smy);
699 emitLineTo(sx0 + smy + smx, sy0 - smx + smy);
700 }
701 }
702 }
703 }
704 emitClose();
705 }
706
707 private void emitMoveTo(final float x0, final float y0) {
708 out.moveTo(x0, y0);
709 }
710
711 private void emitLineTo(final float x1, final float y1) {
712 out.lineTo(x1, y1);
713 }
714
715 private void emitLineToRev(final float x1, final float y1) {
716 reverse.pushLine(x1, y1);
717 }
718
719 private void emitLineTo(final float x1, final float y1,
720 final boolean rev)
721 {
722 if (rev) {
1046
1047 @Override
1048 public void curveTo(final float x1, final float y1,
1049 final float x2, final float y2,
1050 final float x3, final float y3)
1051 {
1052 final int outcode0 = this.cOutCode;
1053
1054 if (clipRect != null) {
1055 final int outcode1 = Helpers.outcode(x1, y1, clipRect);
1056 final int outcode2 = Helpers.outcode(x2, y2, clipRect);
1057 final int outcode3 = Helpers.outcode(x3, y3, clipRect);
1058
1059 // Should clip
1060 final int orCode = (outcode0 | outcode1 | outcode2 | outcode3);
1061 if (orCode != 0) {
1062 final int sideCode = outcode0 & outcode1 & outcode2 & outcode3;
1063
1064 // basic rejection criteria:
1065 if (sideCode == 0) {
1066 // overlap clip:
1067 if (subdivide) {
1068 // avoid reentrance
1069 subdivide = false;
1070 // subdivide curve => callback with subdivided parts:
1071 boolean ret = curveSplitter.splitCurve(cx0, cy0, x1, y1,
1072 x2, y2, x3, y3,
1073 orCode, this);
1074 // reentrance is done:
1075 subdivide = true;
1076 if (ret) {
1077 return;
1078 }
1079 }
1080 // already subdivided so render it
1081 } else {
1082 this.cOutCode = outcode3;
1083 _moveTo(x3, y3, outcode0);
1084 opened = true;
1085 return;
1086 }
1194 this.cmy = (l[kind - 1] - r[kind - 1]) / 2.0f;
1195 }
1196
1197 @Override
1198 public void quadTo(final float x1, final float y1,
1199 final float x2, final float y2)
1200 {
1201 final int outcode0 = this.cOutCode;
1202
1203 if (clipRect != null) {
1204 final int outcode1 = Helpers.outcode(x1, y1, clipRect);
1205 final int outcode2 = Helpers.outcode(x2, y2, clipRect);
1206
1207 // Should clip
1208 final int orCode = (outcode0 | outcode1 | outcode2);
1209 if (orCode != 0) {
1210 final int sideCode = outcode0 & outcode1 & outcode2;
1211
1212 // basic rejection criteria:
1213 if (sideCode == 0) {
1214 // overlap clip:
1215 if (subdivide) {
1216 // avoid reentrance
1217 subdivide = false;
1218 // subdivide curve => call lineTo() with subdivided curves:
1219 boolean ret = curveSplitter.splitQuad(cx0, cy0, x1, y1,
1220 x2, y2, orCode, this);
1221 // reentrance is done:
1222 subdivide = true;
1223 if (ret) {
1224 return;
1225 }
1226 }
1227 // already subdivided so render it
1228 } else {
1229 this.cOutCode = outcode2;
1230 _moveTo(x2, y2, outcode0);
1231 opened = true;
1232 return;
1233 }
1234 }
|