Skip to content

Commit 00d6848

Browse files
committed
Merge pull request processing#3715 from JakubValtar/fx-paths
FX - paths, contours, curves
2 parents 1c69959 + eef516d commit 00d6848

1 file changed

Lines changed: 95 additions & 53 deletions

File tree

core/src/processing/javafx/PGraphicsFX2D.java

Lines changed: 95 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222

2323
package processing.javafx;
2424

25+
import com.sun.javafx.geom.Path2D;
26+
import com.sun.javafx.geom.PathIterator;
27+
import com.sun.javafx.geom.Shape;
28+
2529
import java.nio.IntBuffer;
2630

2731
import javafx.scene.SnapshotParameters;
@@ -35,8 +39,6 @@
3539
import javafx.scene.paint.Color;
3640
import javafx.scene.paint.Paint;
3741
import javafx.scene.shape.ArcType;
38-
import javafx.scene.shape.ClosePath;
39-
import javafx.scene.shape.Path;
4042
import javafx.scene.shape.StrokeLineCap;
4143
import javafx.scene.shape.StrokeLineJoin;
4244
import javafx.scene.transform.Affine;
@@ -53,12 +55,14 @@ public class PGraphicsFX2D extends PGraphics {
5355

5456
WritableImage snapshotImage;
5557

56-
Path workPath;
57-
Path auxPath;
58+
Path2D workPath = new Path2D();
59+
Path2D auxPath = new Path2D();
5860
boolean openContour;
5961
/// break the shape at the next vertex (next vertex() call is a moveto())
6062
boolean breakShape;
6163

64+
private float pathCoordsBuffer[] = new float[6];
65+
6266
/// coordinates for internal curve calculation
6367
float[] curveCoordX;
6468
float[] curveCoordY;
@@ -197,15 +201,14 @@ public void endDraw() {
197201
public void beginShape(int kind) {
198202
shape = kind;
199203
vertexCount = 0;
200-
curveVertexCount = 0;
201204

202-
// set gpath to null, because when mixing curves and straight
203-
// lines, vertexCount will be set back to zero, so vertexCount == 1
204-
// is no longer a good indicator of whether the shape is new.
205-
// this way, just check to see if gpath is null, and if it isn't
206-
// then just use it to continue the shape.
207-
workPath = null;
208-
auxPath = null;
205+
workPath.reset();
206+
auxPath.reset();
207+
208+
if (drawingThinLines()) {
209+
pushMatrix();
210+
translate(0.5f, 0.5f);
211+
}
209212
}
210213

211214

@@ -226,9 +229,6 @@ public void texture(PImage image) {
226229

227230
@Override
228231
public void vertex(float x, float y) {
229-
curveVertexCount = 0;
230-
//float vertex[];
231-
232232
if (vertexCount == vertices.length) {
233233
float temp[][] = new float[vertexCount<<1][VERTEX_FIELD_COUNT];
234234
System.arraycopy(vertices, 0, temp, 0, vertexCount);
@@ -322,13 +322,11 @@ public void vertex(float x, float y) {
322322
break;
323323

324324
case POLYGON:
325-
if (workPath == null) {
326-
context.moveTo(x, y);
327-
} else if (breakShape) {
328-
context.moveTo(x, y);
325+
if (workPath.getNumCommands() == 0 || breakShape) {
326+
workPath.moveTo(x, y);
329327
breakShape = false;
330328
} else {
331-
context.lineTo(x, y);
329+
workPath.lineTo(x, y);
332330
}
333331
break;
334332
}
@@ -367,16 +365,14 @@ public void beginContour() {
367365
}
368366

369367
// draw contours to auxiliary path so main path can be closed later
370-
Path temp = auxPath;
368+
Path2D contourPath = auxPath;
371369
auxPath = workPath;
372-
workPath = temp;
370+
workPath = contourPath;
373371

374-
// if (auxPath != null) { // first contour does not break
375-
breakShape = true;
376-
auxPath = new Path();
377-
// }
372+
if (contourPath.getNumCommands() > 0) { // first contour does not break
373+
breakShape = true;
374+
}
378375

379-
breakShape = true;
380376
openContour = true;
381377
}
382378

@@ -388,15 +384,9 @@ public void endContour() {
388384
return;
389385
}
390386

391-
// close this contour
392-
if (workPath != null) {
393-
//gpath.closePath();
394-
auxPath.getElements().addAll(workPath.getElements());
395-
auxPath.getElements().add(new ClosePath());
396-
}
387+
if (workPath.getNumCommands() > 0) workPath.closePath();
397388

398-
// switch back to main path
399-
Path temp = workPath;
389+
Path2D temp = workPath;
400390
workPath = auxPath;
401391
auxPath = temp;
402392

@@ -410,21 +400,56 @@ public void endShape(int mode) {
410400
endContour();
411401
PGraphics.showWarning("Missing endContour() before endShape()");
412402
}
413-
if (workPath != null) { // make sure something has been drawn
403+
if (workPath.getNumCommands() > 0) {
414404
if (shape == POLYGON) {
415405
if (mode == CLOSE) {
416-
//gpath.closePath();
417-
workPath.getElements().add(new ClosePath());
406+
workPath.closePath();
418407
}
419-
if (auxPath != null) {
420-
//gpath.append(auxPath, false);
421-
workPath.getElements().addAll(auxPath.getElements());
408+
if (auxPath.getNumCommands() > 0) {
409+
workPath.append(auxPath, false);
422410
}
423-
//drawShape(gpath);
424-
// TODO argh, can't go this route
411+
drawShape(workPath);
425412
}
426413
}
427414
shape = 0;
415+
416+
if (drawingThinLines()) {
417+
popMatrix();
418+
}
419+
}
420+
421+
422+
private void drawShape(Shape s) {
423+
context.beginPath();
424+
PathIterator pi = s.getPathIterator(null);
425+
while (!pi.isDone()) {
426+
int pitype = pi.currentSegment(pathCoordsBuffer);
427+
switch (pitype) {
428+
case PathIterator.SEG_MOVETO:
429+
context.moveTo(pathCoordsBuffer[0], pathCoordsBuffer[1]);
430+
break;
431+
case PathIterator.SEG_LINETO:
432+
context.lineTo(pathCoordsBuffer[0], pathCoordsBuffer[1]);
433+
break;
434+
case PathIterator.SEG_QUADTO:
435+
context.quadraticCurveTo(pathCoordsBuffer[0], pathCoordsBuffer[1],
436+
pathCoordsBuffer[2], pathCoordsBuffer[3]);
437+
break;
438+
case PathIterator.SEG_CUBICTO:
439+
context.bezierCurveTo(pathCoordsBuffer[0], pathCoordsBuffer[1],
440+
pathCoordsBuffer[2], pathCoordsBuffer[3],
441+
pathCoordsBuffer[4], pathCoordsBuffer[5]);
442+
break;
443+
case PathIterator.SEG_CLOSE:
444+
context.closePath();
445+
break;
446+
default:
447+
showWarning("Unknown segment type " + pitype);
448+
}
449+
pi.next();
450+
}
451+
if (fill) context.fill();
452+
if (stroke) context.stroke();
428453
}
429454

430455

@@ -484,13 +509,24 @@ protected void blendModeImpl() {
484509
// BEZIER VERTICES
485510

486511

512+
@Override
513+
protected void bezierVertexCheck() {
514+
if (shape == 0 || shape != POLYGON) {
515+
throw new RuntimeException("beginShape() or beginShape(POLYGON) " +
516+
"must be used before bezierVertex() or quadraticVertex()");
517+
}
518+
if (workPath.getNumCommands() == 0) {
519+
throw new RuntimeException("vertex() must be used at least once " +
520+
"before bezierVertex() or quadraticVertex()");
521+
}
522+
}
523+
487524
@Override
488525
public void bezierVertex(float x1, float y1,
489526
float x2, float y2,
490527
float x3, float y3) {
491528
bezierVertexCheck();
492-
context.bezierCurveTo(x1, y1, x2, y2, x3, y3);
493-
529+
workPath.curveTo(x1, y1, x2, y2, x3, y3);
494530
}
495531

496532

@@ -511,7 +547,8 @@ public void bezierVertex(float x2, float y2, float z2,
511547
@Override
512548
public void quadraticVertex(float ctrlX, float ctrlY,
513549
float endX, float endY) {
514-
context.quadraticCurveTo(ctrlX, ctrlY, endX, endY);
550+
bezierVertexCheck();
551+
workPath.quadTo(ctrlX, ctrlY, endX, endY);
515552
}
516553

517554

@@ -530,7 +567,12 @@ public void quadraticVertex(float x2, float y2, float z2,
530567

531568
@Override
532569
protected void curveVertexCheck() {
533-
super.curveVertexCheck();
570+
if (shape != POLYGON) {
571+
throw new RuntimeException("You must use beginShape() or " +
572+
"beginShape(POLYGON) before curveVertex()");
573+
}
574+
575+
curveInitCheck();
534576

535577
if (curveCoordX == null) {
536578
curveCoordX = new float[4];
@@ -563,14 +605,14 @@ protected void curveVertexSegment(float x1, float y1,
563605

564606
// since the paths are continuous,
565607
// only the first point needs the actual moveto
566-
if (workPath == null) {
567-
// gpath = new GeneralPath();
568-
context.moveTo(curveDrawX[0], curveDrawY[0]);
608+
if (workPath.getNumCommands() == 0) {
609+
workPath.moveTo(curveDrawX[0], curveDrawY[0]);
610+
breakShape = false;
569611
}
570612

571-
context.bezierCurveTo(curveDrawX[1], curveDrawY[1],
572-
curveDrawX[2], curveDrawY[2],
573-
curveDrawX[3], curveDrawY[3]);
613+
workPath.curveTo(curveDrawX[1], curveDrawY[1],
614+
curveDrawX[2], curveDrawY[2],
615+
curveDrawX[3], curveDrawY[3]);
574616
}
575617

576618

0 commit comments

Comments
 (0)