propane 3.1.0.pre-java → 3.2.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.mvn/wrapper/maven-wrapper.properties +1 -0
- data/CHANGELOG.md +1 -5
- data/README.md +23 -12
- data/Rakefile +23 -12
- data/lib/propane/helpers/version_error.rb +6 -0
- data/lib/propane/runner.rb +12 -0
- data/lib/propane/version.rb +1 -1
- data/library/slider/slider.rb +1 -1
- data/mvnw +234 -0
- data/mvnw.cmd +145 -0
- data/pom.xml +28 -27
- data/propane.gemspec +2 -2
- data/src/main/java/japplemenubar/JAppleMenuBar.java +41 -47
- data/src/main/java/monkstone/ColorUtil.java +1 -1
- data/src/main/java/monkstone/MathToolModule.java +12 -11
- data/src/main/java/monkstone/PropaneLibrary.java +9 -10
- data/src/main/java/monkstone/core/LibraryProxy.java +124 -113
- data/src/main/java/monkstone/fastmath/Deglut.java +86 -89
- data/src/main/java/monkstone/filechooser/Chooser.java +7 -13
- data/src/main/java/monkstone/noise/SimplexNoise.java +0 -1
- data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +4 -4
- data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +9 -9
- data/src/main/java/monkstone/slider/SimpleSlider.java +0 -9
- data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +11 -13
- data/src/main/java/monkstone/slider/Slider.java +1 -1
- data/src/main/java/monkstone/slider/SliderBar.java +1 -1
- data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
- data/src/main/java/monkstone/slider/WheelHandler.java +8 -9
- data/src/main/java/monkstone/vecmath/AppRender.java +2 -2
- data/src/main/java/monkstone/vecmath/ShapeRender.java +2 -2
- data/src/main/java/monkstone/vecmath/package-info.java +2 -2
- data/src/main/java/monkstone/vecmath/vec2/Vec2.java +2 -2
- data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
- data/src/main/java/monkstone/videoevent/VideoInterface.java +11 -5
- data/src/main/java/monkstone/videoevent/package-info.java +2 -2
- data/src/main/java/processing/awt/PGraphicsJava2D.java +1742 -2243
- data/src/main/java/processing/awt/PShapeJava2D.java +268 -270
- data/src/main/java/processing/awt/PSurfaceAWT.java +821 -920
- data/src/main/java/processing/core/DesktopHandler.java +94 -0
- data/src/main/java/processing/core/PApplet.java +14170 -14082
- data/src/main/java/processing/core/PConstants.java +447 -473
- data/src/main/java/processing/core/PFont.java +867 -873
- data/src/main/java/processing/core/PGraphics.java +7193 -7428
- data/src/main/java/processing/core/PImage.java +3051 -3117
- data/src/main/java/processing/core/PMatrix.java +159 -172
- data/src/main/java/processing/core/PMatrix2D.java +403 -444
- data/src/main/java/processing/core/PMatrix3D.java +735 -749
- data/src/main/java/processing/core/PShape.java +2651 -2793
- data/src/main/java/processing/core/PShapeOBJ.java +415 -422
- data/src/main/java/processing/core/PShapeSVG.java +1466 -1475
- data/src/main/java/processing/core/PStyle.java +37 -40
- data/src/main/java/processing/core/PSurface.java +98 -103
- data/src/main/java/processing/core/PSurfaceNone.java +208 -236
- data/src/main/java/processing/core/PVector.java +961 -990
- data/src/main/java/processing/data/DoubleDict.java +709 -753
- data/src/main/java/processing/data/DoubleList.java +695 -748
- data/src/main/java/processing/data/FloatDict.java +702 -746
- data/src/main/java/processing/data/FloatList.java +697 -751
- data/src/main/java/processing/data/IntDict.java +673 -718
- data/src/main/java/processing/data/IntList.java +633 -699
- data/src/main/java/processing/data/JSONArray.java +873 -931
- data/src/main/java/processing/data/JSONObject.java +1165 -1262
- data/src/main/java/processing/data/JSONTokener.java +341 -351
- data/src/main/java/processing/data/LongDict.java +662 -707
- data/src/main/java/processing/data/LongList.java +634 -700
- data/src/main/java/processing/data/Sort.java +41 -37
- data/src/main/java/processing/data/StringDict.java +486 -522
- data/src/main/java/processing/data/StringList.java +580 -624
- data/src/main/java/processing/data/Table.java +3508 -3686
- data/src/main/java/processing/data/TableRow.java +183 -182
- data/src/main/java/processing/data/XML.java +883 -957
- data/src/main/java/processing/event/Event.java +66 -87
- data/src/main/java/processing/event/KeyEvent.java +41 -48
- data/src/main/java/processing/event/MouseEvent.java +93 -103
- data/src/main/java/processing/event/TouchEvent.java +6 -10
- data/src/main/java/processing/javafx/PGraphicsFX2D.java +5 -69
- data/src/main/java/processing/javafx/PSurfaceFX.java +2 -7
- data/src/main/java/processing/opengl/FontTexture.java +270 -290
- data/src/main/java/processing/opengl/FrameBuffer.java +363 -375
- data/src/main/java/processing/opengl/LinePath.java +500 -543
- data/src/main/java/processing/opengl/LineStroker.java +582 -593
- data/src/main/java/processing/opengl/PGL.java +2881 -2904
- data/src/main/java/processing/opengl/PGraphics2D.java +315 -408
- data/src/main/java/processing/opengl/PGraphics3D.java +72 -107
- data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12043 -12230
- data/src/main/java/processing/opengl/PJOGL.java +1681 -1745
- data/src/main/java/processing/opengl/PShader.java +1257 -1260
- data/src/main/java/processing/opengl/PShapeOpenGL.java +4599 -4662
- data/src/main/java/processing/opengl/PSurfaceJOGL.java +1030 -1047
- data/src/main/java/processing/opengl/Texture.java +1397 -1462
- data/src/main/java/processing/opengl/VertexBuffer.java +55 -57
- data/src/main/resources/icon/icon-1024.png +0 -0
- data/src/main/resources/icon/icon-128.png +0 -0
- data/src/main/resources/icon/icon-16.png +0 -0
- data/src/main/resources/icon/icon-256.png +0 -0
- data/src/main/resources/icon/icon-32.png +0 -0
- data/src/main/resources/icon/icon-48.png +0 -0
- data/src/main/resources/icon/icon-512.png +0 -0
- data/src/main/resources/icon/icon-64.png +0 -0
- data/vendors/Rakefile +1 -1
- metadata +12 -8
- data/src/main/java/processing/core/ThinkDifferent.java +0 -70
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
|
|
2
|
-
|
|
3
1
|
/*
|
|
4
2
|
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
|
5
3
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
@@ -24,662 +22,653 @@
|
|
|
24
22
|
* or visit www.oracle.com if you need additional information or have any
|
|
25
23
|
* questions.
|
|
26
24
|
*/
|
|
27
|
-
|
|
28
25
|
package processing.opengl;
|
|
29
26
|
|
|
30
27
|
import processing.core.PMatrix2D;
|
|
31
28
|
|
|
32
|
-
public class LineStroker
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
this.m10_2_m11_2 = (double) m10 * m10 + (double) m11 * m11;
|
|
154
|
-
this.m00_m10_m01_m11 = (double) m00 * m10 + (double) m01 * m11;
|
|
155
|
-
|
|
156
|
-
double dm00 = m00 / 65536.0;
|
|
157
|
-
double dm01 = m01 / 65536.0;
|
|
158
|
-
double dm10 = m10 / 65536.0;
|
|
159
|
-
double dm11 = m11 / 65536.0;
|
|
160
|
-
double determinant = dm00 * dm11 - dm01 * dm10;
|
|
161
|
-
|
|
162
|
-
if (joinStyle == LinePath.JOIN_MITER) {
|
|
163
|
-
double limit = (miterLimit / 65536.0) * (lineWidth2 / 65536.0)
|
|
164
|
-
* determinant;
|
|
165
|
-
double limitSq = limit * limit;
|
|
166
|
-
this.miterLimitSq = (long) (limitSq * 65536.0 * 65536.0);
|
|
167
|
-
}
|
|
29
|
+
public class LineStroker {
|
|
30
|
+
|
|
31
|
+
private LineStroker output;
|
|
32
|
+
private int capStyle;
|
|
33
|
+
private int joinStyle;
|
|
34
|
+
private int m00, m01;
|
|
35
|
+
private int m10, m11;
|
|
36
|
+
private int lineWidth2;
|
|
37
|
+
private long scaledLineWidth2;
|
|
38
|
+
|
|
39
|
+
// For any pen offset (pen_dx, pen_dy) that does not depend on
|
|
40
|
+
// the line orientation, the pen should be transformed so that:
|
|
41
|
+
//
|
|
42
|
+
// pen_dx' = m00*pen_dx + m01*pen_dy
|
|
43
|
+
// pen_dy' = m10*pen_dx + m11*pen_dy
|
|
44
|
+
//
|
|
45
|
+
// For a round pen, this means:
|
|
46
|
+
//
|
|
47
|
+
// pen_dx(r, theta) = r*cos(theta)
|
|
48
|
+
// pen_dy(r, theta) = r*sin(theta)
|
|
49
|
+
//
|
|
50
|
+
// pen_dx'(r, theta) = r*(m00*cos(theta) + m01*sin(theta))
|
|
51
|
+
// pen_dy'(r, theta) = r*(m10*cos(theta) + m11*sin(theta))
|
|
52
|
+
private int numPenSegments;
|
|
53
|
+
private int[] pen_dx;
|
|
54
|
+
private int[] pen_dy;
|
|
55
|
+
|
|
56
|
+
private boolean[] penIncluded;
|
|
57
|
+
private int[] join;
|
|
58
|
+
private int[] offset = new int[2];
|
|
59
|
+
private int[] reverse = new int[100];
|
|
60
|
+
private int[] miter = new int[2];
|
|
61
|
+
private long miterLimitSq;
|
|
62
|
+
private int prev;
|
|
63
|
+
private int rindex;
|
|
64
|
+
private boolean started;
|
|
65
|
+
private boolean lineToOrigin;
|
|
66
|
+
private boolean joinToOrigin;
|
|
67
|
+
private int sx0, sy0, sx1, sy1, x0, y0;
|
|
68
|
+
private int scolor0, pcolor0, color0;
|
|
69
|
+
private int mx0, my0, omx, omy;
|
|
70
|
+
private int px0, py0;
|
|
71
|
+
private double m00_2_m01_2;
|
|
72
|
+
private double m10_2_m11_2;
|
|
73
|
+
private double m00_m10_m01_m11;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Empty constructor. <code>setOutput</code> and <code>setParameters</code>
|
|
77
|
+
* must be called prior to calling any other methods.
|
|
78
|
+
*/
|
|
79
|
+
public LineStroker() {
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Constructs a <code>LineStroker</code>.
|
|
84
|
+
*
|
|
85
|
+
* @param output an output <code>LineStroker</code>.
|
|
86
|
+
* @param lineWidth the desired line width in pixels, in S15.16 format.
|
|
87
|
+
* @param capStyle the desired end cap style, one of <code>CAP_BUTT</code>,
|
|
88
|
+
* <code>CAP_ROUND</code> or <code>CAP_SQUARE</code>.
|
|
89
|
+
* @param joinStyle the desired line join style, one of
|
|
90
|
+
* <code>JOIN_MITER</code>, <code>JOIN_ROUND</code> or
|
|
91
|
+
* <code>JOIN_BEVEL</code>.
|
|
92
|
+
* @param miterLimit the desired miter limit, in S15.16 format.
|
|
93
|
+
* @param transform a <code>Transform4</code> object indicating the
|
|
94
|
+
* transform that has been previously applied to all incoming coordinates.
|
|
95
|
+
* This is required in order to produce consistently shaped end caps and
|
|
96
|
+
* joins.
|
|
97
|
+
*/
|
|
98
|
+
public LineStroker(LineStroker output, int lineWidth, int capStyle, int joinStyle,
|
|
99
|
+
int miterLimit, PMatrix2D transform) {
|
|
100
|
+
setOutput(output);
|
|
101
|
+
setParameters(lineWidth, capStyle, joinStyle, miterLimit, transform);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Sets the output <code>LineStroker</code> of this
|
|
106
|
+
* <code>LineStroker</code>.
|
|
107
|
+
*
|
|
108
|
+
* @param output an output <code>LineStroker</code>.
|
|
109
|
+
*/
|
|
110
|
+
public void setOutput(LineStroker output) {
|
|
111
|
+
this.output = output;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Sets the parameters of this <code>LineStroker</code>.
|
|
116
|
+
*
|
|
117
|
+
* @param lineWidth the desired line width in pixels, in S15.16 format.
|
|
118
|
+
* @param capStyle the desired end cap style, one of <code>CAP_BUTT</code>,
|
|
119
|
+
* <code>CAP_ROUND</code> or <code>CAP_SQUARE</code>.
|
|
120
|
+
* @param joinStyle the desired line join style, one of
|
|
121
|
+
* <code>JOIN_MITER</code>, <code>JOIN_ROUND</code> or
|
|
122
|
+
* <code>JOIN_BEVEL</code>.
|
|
123
|
+
* @param miterLimit the desired miter limit, in S15.16 format.
|
|
124
|
+
* @param transform a <code>Transform4</code> object indicating the
|
|
125
|
+
* transform that has been previously applied to all incoming coordinates.
|
|
126
|
+
* This is required in order to produce consistently shaped end caps and
|
|
127
|
+
* joins.
|
|
128
|
+
*/
|
|
129
|
+
public void setParameters(int lineWidth, int capStyle, int joinStyle,
|
|
130
|
+
int miterLimit, PMatrix2D transform) {
|
|
131
|
+
this.m00 = LinePath.FloatToS15_16(transform.m00);
|
|
132
|
+
this.m01 = LinePath.FloatToS15_16(transform.m01);
|
|
133
|
+
this.m10 = LinePath.FloatToS15_16(transform.m10);
|
|
134
|
+
this.m11 = LinePath.FloatToS15_16(transform.m11);
|
|
135
|
+
|
|
136
|
+
this.lineWidth2 = lineWidth >> 1;
|
|
137
|
+
this.scaledLineWidth2 = ((long) m00 * lineWidth2) >> 16;
|
|
138
|
+
this.capStyle = capStyle;
|
|
139
|
+
this.joinStyle = joinStyle;
|
|
140
|
+
|
|
141
|
+
this.m00_2_m01_2 = (double) m00 * m00 + (double) m01 * m01;
|
|
142
|
+
this.m10_2_m11_2 = (double) m10 * m10 + (double) m11 * m11;
|
|
143
|
+
this.m00_m10_m01_m11 = (double) m00 * m10 + (double) m01 * m11;
|
|
144
|
+
|
|
145
|
+
double dm00 = m00 / 65536.0;
|
|
146
|
+
double dm01 = m01 / 65536.0;
|
|
147
|
+
double dm10 = m10 / 65536.0;
|
|
148
|
+
double dm11 = m11 / 65536.0;
|
|
149
|
+
double determinant = dm00 * dm11 - dm01 * dm10;
|
|
168
150
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
151
|
+
if (joinStyle == LinePath.JOIN_MITER) {
|
|
152
|
+
double limit = (miterLimit / 65536.0) * (lineWidth2 / 65536.0)
|
|
153
|
+
* determinant;
|
|
154
|
+
double limitSq = limit * limit;
|
|
155
|
+
this.miterLimitSq = (long) (limitSq * 65536.0 * 65536.0);
|
|
156
|
+
}
|
|
176
157
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
158
|
+
this.numPenSegments = (int) (3.14159f * lineWidth / 65536.0f);
|
|
159
|
+
if (pen_dx == null || pen_dx.length < numPenSegments) {
|
|
160
|
+
this.pen_dx = new int[numPenSegments];
|
|
161
|
+
this.pen_dy = new int[numPenSegments];
|
|
162
|
+
this.penIncluded = new boolean[numPenSegments];
|
|
163
|
+
this.join = new int[2 * numPenSegments];
|
|
164
|
+
}
|
|
180
165
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
pen_dy[i] = (int) (r * (dm10 * cos + dm11 * sin));
|
|
185
|
-
}
|
|
166
|
+
for (int i = 0; i < numPenSegments; i++) {
|
|
167
|
+
double r = lineWidth / 2.0;
|
|
168
|
+
double theta = i * 2 * Math.PI / numPenSegments;
|
|
186
169
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
private void computeOffset(int x0, int y0, int x1, int y1, int[] m) {
|
|
194
|
-
long lx = (long) x1 - (long) x0;
|
|
195
|
-
long ly = (long) y1 - (long) y0;
|
|
196
|
-
|
|
197
|
-
int dx, dy;
|
|
198
|
-
if (m00 > 0 && m00 == m11 && m01 == 0 & m10 == 0) {
|
|
199
|
-
long ilen = LinePath.hypot(lx, ly);
|
|
200
|
-
if (ilen == 0) {
|
|
201
|
-
dx = dy = 0;
|
|
202
|
-
} else {
|
|
203
|
-
dx = (int) ((ly * scaledLineWidth2) / ilen);
|
|
204
|
-
dy = (int) (-(lx * scaledLineWidth2) / ilen);
|
|
205
|
-
}
|
|
206
|
-
} else {
|
|
207
|
-
double dlx = x1 - x0;
|
|
208
|
-
double dly = y1 - y0;
|
|
209
|
-
double det = (double) m00 * m11 - (double) m01 * m10;
|
|
210
|
-
int sdet = (det > 0) ? 1 : -1;
|
|
211
|
-
double a = dly * m00 - dlx * m10;
|
|
212
|
-
double b = dly * m01 - dlx * m11;
|
|
213
|
-
double dh = LinePath.hypot(a, b);
|
|
214
|
-
double div = sdet * lineWidth2 / (65536.0 * dh);
|
|
215
|
-
double ddx = dly * m00_2_m01_2 - dlx * m00_m10_m01_m11;
|
|
216
|
-
double ddy = dly * m00_m10_m01_m11 - dlx * m10_2_m11_2;
|
|
217
|
-
dx = (int) (ddx * div);
|
|
218
|
-
dy = (int) (ddy * div);
|
|
219
|
-
}
|
|
170
|
+
double cos = Math.cos(theta);
|
|
171
|
+
double sin = Math.sin(theta);
|
|
172
|
+
pen_dx[i] = (int) (r * (dm00 * cos + dm01 * sin));
|
|
173
|
+
pen_dy[i] = (int) (r * (dm10 * cos + dm11 * sin));
|
|
174
|
+
}
|
|
220
175
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
176
|
+
prev = LinePath.SEG_CLOSE;
|
|
177
|
+
rindex = 0;
|
|
178
|
+
started = false;
|
|
179
|
+
lineToOrigin = false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private void computeOffset(int x0, int y0, int x1, int y1, int[] m) {
|
|
183
|
+
long lx = (long) x1 - (long) x0;
|
|
184
|
+
long ly = (long) y1 - (long) y0;
|
|
185
|
+
|
|
186
|
+
int dx, dy;
|
|
187
|
+
if (m00 > 0 && m00 == m11 && m01 == 0 & m10 == 0) {
|
|
188
|
+
long ilen = LinePath.hypot(lx, ly);
|
|
189
|
+
if (ilen == 0) {
|
|
190
|
+
dx = dy = 0;
|
|
191
|
+
} else {
|
|
192
|
+
dx = (int) ((ly * scaledLineWidth2) / ilen);
|
|
193
|
+
dy = (int) (-(lx * scaledLineWidth2) / ilen);
|
|
194
|
+
}
|
|
195
|
+
} else {
|
|
196
|
+
double dlx = x1 - x0;
|
|
197
|
+
double dly = y1 - y0;
|
|
198
|
+
double det = (double) m00 * m11 - (double) m01 * m10;
|
|
199
|
+
int sdet = (det > 0) ? 1 : -1;
|
|
200
|
+
double a = dly * m00 - dlx * m10;
|
|
201
|
+
double b = dly * m01 - dlx * m11;
|
|
202
|
+
double dh = LinePath.hypot(a, b);
|
|
203
|
+
double div = sdet * lineWidth2 / (65536.0 * dh);
|
|
204
|
+
double ddx = dly * m00_2_m01_2 - dlx * m00_m10_m01_m11;
|
|
205
|
+
double ddy = dly * m00_m10_m01_m11 - dlx * m10_2_m11_2;
|
|
206
|
+
dx = (int) (ddx * div);
|
|
207
|
+
dy = (int) (ddy * div);
|
|
208
|
+
}
|
|
224
209
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
int[] tmp = new int[Math.max(newrindex, 6 * reverse.length / 5)];
|
|
228
|
-
System.arraycopy(reverse, 0, tmp, 0, rindex);
|
|
229
|
-
this.reverse = tmp;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
private boolean isCCW(int x0, int y0, int x1, int y1, int x2, int y2) {
|
|
234
|
-
int dx0 = x1 - x0;
|
|
235
|
-
int dy0 = y1 - y0;
|
|
236
|
-
int dx1 = x2 - x1;
|
|
237
|
-
int dy1 = y2 - y1;
|
|
238
|
-
return (long) dx0 * dy1 < (long) dy0 * dx1;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
private boolean side(int x, int y, int x0, int y0, int x1, int y1) {
|
|
242
|
-
long lx = x;
|
|
243
|
-
long ly = y;
|
|
244
|
-
long lx0 = x0;
|
|
245
|
-
long ly0 = y0;
|
|
246
|
-
long lx1 = x1;
|
|
247
|
-
long ly1 = y1;
|
|
248
|
-
|
|
249
|
-
return (ly0 - ly1) * lx + (lx1 - lx0) * ly + (lx0 * ly1 - lx1 * ly0) > 0;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
private int computeRoundJoin(int cx, int cy, int xa, int ya, int xb, int yb,
|
|
253
|
-
int side, boolean flip, int[] join) {
|
|
254
|
-
int px, py;
|
|
255
|
-
int ncoords = 0;
|
|
256
|
-
|
|
257
|
-
boolean centerSide;
|
|
258
|
-
if (side == 0) {
|
|
259
|
-
centerSide = side(cx, cy, xa, ya, xb, yb);
|
|
260
|
-
} else {
|
|
261
|
-
centerSide = (side == 1) ? true : false;
|
|
262
|
-
}
|
|
263
|
-
for (int i = 0; i < numPenSegments; i++) {
|
|
264
|
-
px = cx + pen_dx[i];
|
|
265
|
-
py = cy + pen_dy[i];
|
|
266
|
-
|
|
267
|
-
boolean penSide = side(px, py, xa, ya, xb, yb);
|
|
268
|
-
if (penSide != centerSide) {
|
|
269
|
-
penIncluded[i] = true;
|
|
270
|
-
} else {
|
|
271
|
-
penIncluded[i] = false;
|
|
272
|
-
}
|
|
210
|
+
m[0] = dx;
|
|
211
|
+
m[1] = dy;
|
|
273
212
|
}
|
|
274
213
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if (penIncluded[i] && !penIncluded[(i + 1) % numPenSegments]) {
|
|
282
|
-
end = i;
|
|
283
|
-
}
|
|
214
|
+
private void ensureCapacity(int newrindex) {
|
|
215
|
+
if (reverse.length < newrindex) {
|
|
216
|
+
int[] tmp = new int[Math.max(newrindex, 6 * reverse.length / 5)];
|
|
217
|
+
System.arraycopy(reverse, 0, tmp, 0, rindex);
|
|
218
|
+
this.reverse = tmp;
|
|
219
|
+
}
|
|
284
220
|
}
|
|
285
221
|
|
|
286
|
-
|
|
287
|
-
|
|
222
|
+
private boolean isCCW(int x0, int y0, int x1, int y1, int x2, int y2) {
|
|
223
|
+
int dx0 = x1 - x0;
|
|
224
|
+
int dy0 = y1 - y0;
|
|
225
|
+
int dx1 = x2 - x1;
|
|
226
|
+
int dy1 = y2 - y1;
|
|
227
|
+
return (long) dx0 * dy1 < (long) dy0 * dx1;
|
|
288
228
|
}
|
|
289
229
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
while (true) {
|
|
300
|
-
int idx = i % numPenSegments;
|
|
301
|
-
px = cx + pen_dx[idx];
|
|
302
|
-
py = cy + pen_dy[idx];
|
|
303
|
-
join[ncoords++] = px;
|
|
304
|
-
join[ncoords++] = py;
|
|
305
|
-
if (i == (rev ? start : end)) {
|
|
306
|
-
break;
|
|
307
|
-
}
|
|
308
|
-
i += incr;
|
|
309
|
-
}
|
|
230
|
+
private boolean side(int x, int y, int x0, int y0, int x1, int y1) {
|
|
231
|
+
long lx = x;
|
|
232
|
+
long ly = y;
|
|
233
|
+
long lx0 = x0;
|
|
234
|
+
long ly0 = y0;
|
|
235
|
+
long lx1 = x1;
|
|
236
|
+
long ly1 = y1;
|
|
237
|
+
|
|
238
|
+
return (ly0 - ly1) * lx + (lx1 - lx0) * ly + (lx0 * ly1 - lx1 * ly0) > 0;
|
|
310
239
|
}
|
|
311
240
|
|
|
312
|
-
|
|
313
|
-
|
|
241
|
+
private int computeRoundJoin(int cx, int cy, int xa, int ya, int xb, int yb,
|
|
242
|
+
int side, boolean flip, int[] join) {
|
|
243
|
+
int px, py;
|
|
244
|
+
int ncoords = 0;
|
|
314
245
|
|
|
315
|
-
|
|
316
|
-
|
|
246
|
+
boolean centerSide;
|
|
247
|
+
if (side == 0) {
|
|
248
|
+
centerSide = side(cx, cy, xa, ya, xb, yb);
|
|
249
|
+
} else {
|
|
250
|
+
centerSide = (side == 1) ? true : false;
|
|
251
|
+
}
|
|
252
|
+
for (int i = 0; i < numPenSegments; i++) {
|
|
253
|
+
px = cx + pen_dx[i];
|
|
254
|
+
py = cy + pen_dy[i];
|
|
255
|
+
|
|
256
|
+
boolean penSide = side(px, py, xa, ya, xb, yb);
|
|
257
|
+
if (penSide != centerSide) {
|
|
258
|
+
penIncluded[i] = true;
|
|
259
|
+
} else {
|
|
260
|
+
penIncluded[i] = false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
317
263
|
|
|
318
|
-
|
|
264
|
+
int start = -1, end = -1;
|
|
265
|
+
for (int i = 0; i < numPenSegments; i++) {
|
|
266
|
+
if (penIncluded[i]
|
|
267
|
+
&& !penIncluded[(i + numPenSegments - 1) % numPenSegments]) {
|
|
268
|
+
start = i;
|
|
269
|
+
}
|
|
270
|
+
if (penIncluded[i] && !penIncluded[(i + 1) % numPenSegments]) {
|
|
271
|
+
end = i;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
319
274
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) {
|
|
324
|
-
return;
|
|
325
|
-
}
|
|
275
|
+
if (end < start) {
|
|
276
|
+
end += numPenSegments;
|
|
277
|
+
}
|
|
326
278
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
279
|
+
if (start != -1 && end != -1) {
|
|
280
|
+
long dxa = cx + pen_dx[start] - xa;
|
|
281
|
+
long dya = cy + pen_dy[start] - ya;
|
|
282
|
+
long dxb = cx + pen_dx[start] - xb;
|
|
283
|
+
long dyb = cy + pen_dy[start] - yb;
|
|
284
|
+
|
|
285
|
+
boolean rev = (dxa * dxa + dya * dya > dxb * dxb + dyb * dyb);
|
|
286
|
+
int i = rev ? end : start;
|
|
287
|
+
int incr = rev ? -1 : 1;
|
|
288
|
+
while (true) {
|
|
289
|
+
int idx = i % numPenSegments;
|
|
290
|
+
px = cx + pen_dx[idx];
|
|
291
|
+
py = cy + pen_dy[idx];
|
|
292
|
+
join[ncoords++] = px;
|
|
293
|
+
join[ncoords++] = py;
|
|
294
|
+
if (i == (rev ? start : end)) {
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
i += incr;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
333
300
|
|
|
334
|
-
|
|
335
|
-
omx = -omx;
|
|
336
|
-
omy = -omy;
|
|
337
|
-
mx = -mx;
|
|
338
|
-
my = -my;
|
|
301
|
+
return ncoords / 2;
|
|
339
302
|
}
|
|
340
303
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
int bx1 = x + mx;
|
|
344
|
-
int by1 = y + my;
|
|
304
|
+
//private static final long ROUND_JOIN_THRESHOLD = 1000L;
|
|
305
|
+
private static final long ROUND_JOIN_THRESHOLD = 100000000L;
|
|
345
306
|
|
|
346
|
-
|
|
347
|
-
for (int i = 0; i < npoints; i++) {
|
|
348
|
-
emitLineTo(join[2 * i], join[2 * i + 1], color, rev);
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
// Return the intersection point of the lines (ix0, iy0) -> (ix1, iy1)
|
|
353
|
-
// and (ix0p, iy0p) -> (ix1p, iy1p) in m[0] and m[1]
|
|
354
|
-
private void computeMiter(int ix0, int iy0, int ix1, int iy1, int ix0p,
|
|
355
|
-
int iy0p, int ix1p, int iy1p, int[] m) {
|
|
356
|
-
long x0 = ix0;
|
|
357
|
-
long y0 = iy0;
|
|
358
|
-
long x1 = ix1;
|
|
359
|
-
long y1 = iy1;
|
|
360
|
-
|
|
361
|
-
long x0p = ix0p;
|
|
362
|
-
long y0p = iy0p;
|
|
363
|
-
long x1p = ix1p;
|
|
364
|
-
long y1p = iy1p;
|
|
365
|
-
|
|
366
|
-
long x10 = x1 - x0;
|
|
367
|
-
long y10 = y1 - y0;
|
|
368
|
-
long x10p = x1p - x0p;
|
|
369
|
-
long y10p = y1p - y0p;
|
|
370
|
-
|
|
371
|
-
long den = (x10 * y10p - x10p * y10) >> 16;
|
|
372
|
-
if (den == 0) {
|
|
373
|
-
m[0] = ix0;
|
|
374
|
-
m[1] = iy0;
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
307
|
+
private static final long ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000L;
|
|
377
308
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
309
|
+
private void drawRoundJoin(int x, int y, int omx, int omy, int mx, int my,
|
|
310
|
+
int side, int color,
|
|
311
|
+
boolean flip, boolean rev, long threshold) {
|
|
312
|
+
if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
382
315
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
316
|
+
long domx = (long) omx - mx;
|
|
317
|
+
long domy = (long) omy - my;
|
|
318
|
+
long len = domx * domx + domy * domy;
|
|
319
|
+
if (len < threshold) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (rev) {
|
|
324
|
+
omx = -omx;
|
|
325
|
+
omy = -omy;
|
|
326
|
+
mx = -mx;
|
|
327
|
+
my = -my;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
int bx0 = x + omx;
|
|
331
|
+
int by0 = y + omy;
|
|
332
|
+
int bx1 = x + mx;
|
|
333
|
+
int by1 = y + my;
|
|
334
|
+
|
|
335
|
+
int npoints = computeRoundJoin(x, y, bx0, by0, bx1, by1, side, flip, join);
|
|
336
|
+
for (int i = 0; i < npoints; i++) {
|
|
337
|
+
emitLineTo(join[2 * i], join[2 * i + 1], color, rev);
|
|
338
|
+
}
|
|
394
339
|
}
|
|
395
340
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
341
|
+
// Return the intersection point of the lines (ix0, iy0) -> (ix1, iy1)
|
|
342
|
+
// and (ix0p, iy0p) -> (ix1p, iy1p) in m[0] and m[1]
|
|
343
|
+
private void computeMiter(int ix0, int iy0, int ix1, int iy1, int ix0p,
|
|
344
|
+
int iy0p, int ix1p, int iy1p, int[] m) {
|
|
345
|
+
long x0 = ix0;
|
|
346
|
+
long y0 = iy0;
|
|
347
|
+
long x1 = ix1;
|
|
348
|
+
long y1 = iy1;
|
|
349
|
+
|
|
350
|
+
long x0p = ix0p;
|
|
351
|
+
long y0p = iy0p;
|
|
352
|
+
long x1p = ix1p;
|
|
353
|
+
long y1p = iy1p;
|
|
354
|
+
|
|
355
|
+
long x10 = x1 - x0;
|
|
356
|
+
long y10 = y1 - y0;
|
|
357
|
+
long x10p = x1p - x0p;
|
|
358
|
+
long y10p = y1p - y0p;
|
|
359
|
+
|
|
360
|
+
long den = (x10 * y10p - x10p * y10) >> 16;
|
|
361
|
+
if (den == 0) {
|
|
362
|
+
m[0] = ix0;
|
|
363
|
+
m[1] = iy0;
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
long t = (x1p * (y0 - y0p) - x0 * y10p + x0p * (y1p - y0)) >> 16;
|
|
368
|
+
m[0] = (int) (x0 + (t * x10) / den);
|
|
369
|
+
m[1] = (int) (y0 + (t * y10) / den);
|
|
401
370
|
}
|
|
402
371
|
|
|
403
|
-
|
|
404
|
-
|
|
372
|
+
private void drawMiter(int px0, int py0, int x0, int y0, int x1, int y1,
|
|
373
|
+
int omx, int omy, int mx, int my, int color,
|
|
374
|
+
boolean rev) {
|
|
375
|
+
if (mx == omx && my == omy) {
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
if (px0 == x0 && py0 == y0) {
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
if (x0 == x1 && y0 == y1) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
405
384
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
385
|
+
if (rev) {
|
|
386
|
+
omx = -omx;
|
|
387
|
+
omy = -omy;
|
|
388
|
+
mx = -mx;
|
|
389
|
+
my = -my;
|
|
390
|
+
}
|
|
412
391
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
}
|
|
392
|
+
computeMiter(px0 + omx, py0 + omy, x0 + omx, y0 + omy, x0 + mx, y0 + my, x1
|
|
393
|
+
+ mx, y1 + my, miter);
|
|
417
394
|
|
|
418
|
-
|
|
419
|
-
|
|
395
|
+
// Compute miter length in untransformed coordinates
|
|
396
|
+
long dx = (long) miter[0] - x0;
|
|
397
|
+
long dy = (long) miter[1] - y0;
|
|
398
|
+
long a = (dy * m00 - dx * m10) >> 16;
|
|
399
|
+
long b = (dy * m01 - dx * m11) >> 16;
|
|
400
|
+
long lenSq = a * a + b * b;
|
|
420
401
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
lineToOrigin = false;
|
|
402
|
+
if (lenSq < miterLimitSq) {
|
|
403
|
+
emitLineTo(miter[0], miter[1], color, rev);
|
|
404
|
+
}
|
|
425
405
|
}
|
|
426
406
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}
|
|
407
|
+
public void moveTo(int x0, int y0, int c0) {
|
|
408
|
+
// System.out.println("LineStroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
|
|
430
409
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
this.joinSegment = false;
|
|
437
|
-
this.prev = LinePath.SEG_MOVETO;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
boolean joinSegment = false;
|
|
441
|
-
|
|
442
|
-
public void lineJoin() {
|
|
443
|
-
// System.out.println("LineStroker.lineJoin()");
|
|
444
|
-
this.joinSegment = true;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
public void lineTo(int x1, int y1, int c1) {
|
|
448
|
-
// System.out.println("LineStroker.lineTo(" + x1/65536.0 + ", " + y1/65536.0 + ")");
|
|
449
|
-
|
|
450
|
-
if (lineToOrigin) {
|
|
451
|
-
if (x1 == sx0 && y1 == sy0) {
|
|
452
|
-
// staying in the starting point
|
|
453
|
-
return;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
// not closing the path, do the previous lineTo
|
|
457
|
-
lineToImpl(sx0, sy0, scolor0, joinToOrigin);
|
|
458
|
-
lineToOrigin = false;
|
|
459
|
-
} else if (x1 == x0 && y1 == y0) {
|
|
460
|
-
return;
|
|
461
|
-
} else if (x1 == sx0 && y1 == sy0) {
|
|
462
|
-
lineToOrigin = true;
|
|
463
|
-
joinToOrigin = joinSegment;
|
|
464
|
-
joinSegment = false;
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
410
|
+
if (lineToOrigin) {
|
|
411
|
+
// not closing the path, do the previous lineTo
|
|
412
|
+
lineToImpl(sx0, sy0, scolor0, joinToOrigin);
|
|
413
|
+
lineToOrigin = false;
|
|
414
|
+
}
|
|
467
415
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
private void lineToImpl(int x1, int y1, int c1, boolean joinSegment) {
|
|
473
|
-
computeOffset(x0, y0, x1, y1, offset);
|
|
474
|
-
int mx = offset[0];
|
|
475
|
-
int my = offset[1];
|
|
476
|
-
|
|
477
|
-
if (!started) {
|
|
478
|
-
emitMoveTo(x0 + mx, y0 + my, color0);
|
|
479
|
-
this.sx1 = x1;
|
|
480
|
-
this.sy1 = y1;
|
|
481
|
-
this.mx0 = mx;
|
|
482
|
-
this.my0 = my;
|
|
483
|
-
started = true;
|
|
484
|
-
} else {
|
|
485
|
-
boolean ccw = isCCW(px0, py0, x0, y0, x1, y1);
|
|
486
|
-
if (joinSegment) {
|
|
487
|
-
if (joinStyle == LinePath.JOIN_MITER) {
|
|
488
|
-
drawMiter(px0, py0, x0, y0, x1, y1, omx, omy, mx, my, color0, ccw);
|
|
489
|
-
} else if (joinStyle == LinePath.JOIN_ROUND) {
|
|
490
|
-
drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
|
|
491
|
-
ROUND_JOIN_THRESHOLD);
|
|
416
|
+
if (prev == LinePath.SEG_LINETO) {
|
|
417
|
+
finish();
|
|
492
418
|
}
|
|
493
|
-
} else {
|
|
494
|
-
// Draw internal joins as round
|
|
495
|
-
drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
|
|
496
|
-
ROUND_JOIN_INTERNAL_THRESHOLD);
|
|
497
|
-
}
|
|
498
419
|
|
|
499
|
-
|
|
500
|
-
|
|
420
|
+
this.sx0 = this.x0 = x0;
|
|
421
|
+
this.sy0 = this.y0 = y0;
|
|
422
|
+
this.scolor0 = this.color0 = c0;
|
|
423
|
+
this.rindex = 0;
|
|
424
|
+
this.started = false;
|
|
425
|
+
this.joinSegment = false;
|
|
426
|
+
this.prev = LinePath.SEG_MOVETO;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
boolean joinSegment = false;
|
|
430
|
+
|
|
431
|
+
public void lineJoin() {
|
|
432
|
+
// System.out.println("LineStroker.lineJoin()");
|
|
433
|
+
this.joinSegment = true;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
public void lineTo(int x1, int y1, int c1) {
|
|
437
|
+
// System.out.println("LineStroker.lineTo(" + x1/65536.0 + ", " + y1/65536.0 + ")");
|
|
438
|
+
|
|
439
|
+
if (lineToOrigin) {
|
|
440
|
+
if (x1 == sx0 && y1 == sy0) {
|
|
441
|
+
// staying in the starting point
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// not closing the path, do the previous lineTo
|
|
446
|
+
lineToImpl(sx0, sy0, scolor0, joinToOrigin);
|
|
447
|
+
lineToOrigin = false;
|
|
448
|
+
} else if (x1 == x0 && y1 == y0) {
|
|
449
|
+
return;
|
|
450
|
+
} else if (x1 == sx0 && y1 == sy0) {
|
|
451
|
+
lineToOrigin = true;
|
|
452
|
+
joinToOrigin = joinSegment;
|
|
453
|
+
joinSegment = false;
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
501
456
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
457
|
+
lineToImpl(x1, y1, c1, joinSegment);
|
|
458
|
+
joinSegment = false;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
private void lineToImpl(int x1, int y1, int c1, boolean joinSegment) {
|
|
462
|
+
computeOffset(x0, y0, x1, y1, offset);
|
|
463
|
+
int mx = offset[0];
|
|
464
|
+
int my = offset[1];
|
|
465
|
+
|
|
466
|
+
if (!started) {
|
|
467
|
+
emitMoveTo(x0 + mx, y0 + my, color0);
|
|
468
|
+
this.sx1 = x1;
|
|
469
|
+
this.sy1 = y1;
|
|
470
|
+
this.mx0 = mx;
|
|
471
|
+
this.my0 = my;
|
|
472
|
+
started = true;
|
|
473
|
+
} else {
|
|
474
|
+
boolean ccw = isCCW(px0, py0, x0, y0, x1, y1);
|
|
475
|
+
if (joinSegment) {
|
|
476
|
+
if (joinStyle == LinePath.JOIN_MITER) {
|
|
477
|
+
drawMiter(px0, py0, x0, y0, x1, y1, omx, omy, mx, my, color0, ccw);
|
|
478
|
+
} else if (joinStyle == LinePath.JOIN_ROUND) {
|
|
479
|
+
drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
|
|
480
|
+
ROUND_JOIN_THRESHOLD);
|
|
481
|
+
}
|
|
482
|
+
} else {
|
|
483
|
+
// Draw internal joins as round
|
|
484
|
+
drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
|
|
485
|
+
ROUND_JOIN_INTERNAL_THRESHOLD);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
emitLineTo(x0, y0, color0, !ccw);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
emitLineTo(x0 + mx, y0 + my, color0, false);
|
|
492
|
+
emitLineTo(x1 + mx, y1 + my, c1, false);
|
|
493
|
+
|
|
494
|
+
emitLineTo(x0 - mx, y0 - my, color0, true);
|
|
495
|
+
emitLineTo(x1 - mx, y1 - my, c1, true);
|
|
524
496
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
497
|
+
this.omx = mx;
|
|
498
|
+
this.omy = my;
|
|
499
|
+
this.px0 = x0;
|
|
500
|
+
this.py0 = y0;
|
|
501
|
+
this.pcolor0 = color0;
|
|
502
|
+
this.x0 = x1;
|
|
503
|
+
this.y0 = y1;
|
|
504
|
+
this.color0 = c1;
|
|
505
|
+
this.prev = LinePath.SEG_LINETO;
|
|
528
506
|
}
|
|
529
507
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
508
|
+
public void close() {
|
|
509
|
+
if (lineToOrigin) {
|
|
510
|
+
// ignore the previous lineTo
|
|
511
|
+
lineToOrigin = false;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
if (!started) {
|
|
515
|
+
finish();
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
computeOffset(x0, y0, sx0, sy0, offset);
|
|
520
|
+
int mx = offset[0];
|
|
521
|
+
int my = offset[1];
|
|
522
|
+
|
|
523
|
+
// Draw penultimate join
|
|
524
|
+
boolean ccw = isCCW(px0, py0, x0, y0, sx0, sy0);
|
|
525
|
+
if (joinSegment) {
|
|
526
|
+
if (joinStyle == LinePath.JOIN_MITER) {
|
|
527
|
+
drawMiter(px0, py0, x0, y0, sx0, sy0, omx, omy, mx, my, pcolor0, ccw);
|
|
528
|
+
} else if (joinStyle == LinePath.JOIN_ROUND) {
|
|
529
|
+
drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
|
|
530
|
+
ROUND_JOIN_THRESHOLD);
|
|
531
|
+
}
|
|
532
|
+
} else {
|
|
533
|
+
// Draw internal joins as round
|
|
534
|
+
drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
|
|
546
535
|
ROUND_JOIN_INTERNAL_THRESHOLD);
|
|
547
|
-
|
|
536
|
+
}
|
|
548
537
|
|
|
549
|
-
|
|
550
|
-
|
|
538
|
+
emitLineTo(x0 + mx, y0 + my, color0);
|
|
539
|
+
emitLineTo(sx0 + mx, sy0 + my, scolor0);
|
|
551
540
|
|
|
552
|
-
|
|
541
|
+
ccw = isCCW(x0, y0, sx0, sy0, sx1, sy1);
|
|
553
542
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
543
|
+
// Draw final join on the outside
|
|
544
|
+
if (!ccw) {
|
|
545
|
+
if (joinStyle == LinePath.JOIN_MITER) {
|
|
546
|
+
drawMiter(x0, y0, sx0, sy0, sx1, sy1, mx, my, mx0, my0, color0, false);
|
|
547
|
+
} else if (joinStyle == LinePath.JOIN_ROUND) {
|
|
548
|
+
drawRoundJoin(sx0, sy0, mx, my, mx0, my0, 0, scolor0, false, false,
|
|
549
|
+
ROUND_JOIN_THRESHOLD);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
563
552
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
553
|
+
emitLineTo(sx0 + mx0, sy0 + my0, scolor0);
|
|
554
|
+
emitLineTo(sx0 - mx0, sy0 - my0, scolor0); // same as reverse[0], reverse[1]
|
|
555
|
+
|
|
556
|
+
// Draw final join on the inside
|
|
557
|
+
if (ccw) {
|
|
558
|
+
if (joinStyle == LinePath.JOIN_MITER) {
|
|
559
|
+
drawMiter(x0, y0, sx0, sy0, sx1, sy1, -mx, -my, -mx0, -my0, color0,
|
|
560
|
+
false);
|
|
561
|
+
} else if (joinStyle == LinePath.JOIN_ROUND) {
|
|
562
|
+
drawRoundJoin(sx0, sy0, -mx, -my, -mx0, -my0, 0, scolor0, true, false,
|
|
563
|
+
ROUND_JOIN_THRESHOLD);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
emitLineTo(sx0 - mx, sy0 - my, scolor0);
|
|
568
|
+
emitLineTo(x0 - mx, y0 - my, color0);
|
|
569
|
+
for (int i = rindex - 3; i >= 0; i -= 3) {
|
|
570
|
+
emitLineTo(reverse[i], reverse[i + 1], reverse[i + 2]);
|
|
571
|
+
}
|
|
577
572
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
573
|
+
this.x0 = this.sx0;
|
|
574
|
+
this.y0 = this.sy0;
|
|
575
|
+
this.rindex = 0;
|
|
576
|
+
this.started = false;
|
|
577
|
+
this.joinSegment = false;
|
|
578
|
+
this.prev = LinePath.SEG_CLOSE;
|
|
579
|
+
emitClose();
|
|
582
580
|
}
|
|
583
581
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
582
|
+
public void end() {
|
|
583
|
+
if (lineToOrigin) {
|
|
584
|
+
// not closing the path, do the previous lineTo
|
|
585
|
+
lineToImpl(sx0, sy0, scolor0, joinToOrigin);
|
|
586
|
+
lineToOrigin = false;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
if (prev == LinePath.SEG_LINETO) {
|
|
590
|
+
finish();
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
output.end();
|
|
594
|
+
this.joinSegment = false;
|
|
595
|
+
this.prev = LinePath.SEG_MOVETO;
|
|
598
596
|
}
|
|
599
597
|
|
|
600
|
-
|
|
601
|
-
|
|
598
|
+
long lineLength(long ldx, long ldy) {
|
|
599
|
+
long ldet = ((long) m00 * m11 - (long) m01 * m10) >> 16;
|
|
600
|
+
long la = (ldy * m00 - ldx * m10) / ldet;
|
|
601
|
+
long lb = (ldy * m01 - ldx * m11) / ldet;
|
|
602
|
+
long llen = (int) LinePath.hypot(la, lb);
|
|
603
|
+
return llen;
|
|
602
604
|
}
|
|
603
605
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
long lineLength(long ldx, long ldy) {
|
|
610
|
-
long ldet = ((long) m00 * m11 - (long) m01 * m10) >> 16;
|
|
611
|
-
long la = (ldy * m00 - ldx * m10) / ldet;
|
|
612
|
-
long lb = (ldy * m01 - ldx * m11) / ldet;
|
|
613
|
-
long llen = (int) LinePath.hypot(la, lb);
|
|
614
|
-
return llen;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
private void finish() {
|
|
618
|
-
if (capStyle == LinePath.CAP_ROUND) {
|
|
619
|
-
drawRoundJoin(x0, y0, omx, omy, -omx, -omy, 1, color0, false, false,
|
|
606
|
+
private void finish() {
|
|
607
|
+
if (capStyle == LinePath.CAP_ROUND) {
|
|
608
|
+
drawRoundJoin(x0, y0, omx, omy, -omx, -omy, 1, color0, false, false,
|
|
620
609
|
ROUND_JOIN_THRESHOLD);
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
610
|
+
} else if (capStyle == LinePath.CAP_SQUARE) {
|
|
611
|
+
long ldx = px0 - x0;
|
|
612
|
+
long ldy = py0 - y0;
|
|
613
|
+
long llen = lineLength(ldx, ldy);
|
|
614
|
+
if (0 < llen) {
|
|
615
|
+
long s = (long) lineWidth2 * 65536 / llen;
|
|
616
|
+
|
|
617
|
+
int capx = x0 - (int) (ldx * s >> 16);
|
|
618
|
+
int capy = y0 - (int) (ldy * s >> 16);
|
|
619
|
+
|
|
620
|
+
emitLineTo(capx + omx, capy + omy, color0);
|
|
621
|
+
emitLineTo(capx - omx, capy - omy, color0);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
for (int i = rindex - 3; i >= 0; i -= 3) {
|
|
626
|
+
emitLineTo(reverse[i], reverse[i + 1], reverse[i + 2]);
|
|
627
|
+
}
|
|
628
|
+
this.rindex = 0;
|
|
629
|
+
|
|
630
|
+
if (capStyle == LinePath.CAP_ROUND) {
|
|
631
|
+
drawRoundJoin(sx0, sy0, -mx0, -my0, mx0, my0, 1, scolor0, false, false,
|
|
632
|
+
ROUND_JOIN_THRESHOLD);
|
|
633
|
+
} else if (capStyle == LinePath.CAP_SQUARE) {
|
|
634
|
+
long ldx = sx1 - sx0;
|
|
635
|
+
long ldy = sy1 - sy0;
|
|
636
|
+
long llen = lineLength(ldx, ldy);
|
|
637
|
+
if (0 < llen) {
|
|
638
|
+
long s = (long) lineWidth2 * 65536 / llen;
|
|
639
|
+
|
|
640
|
+
int capx = sx0 - (int) (ldx * s >> 16);
|
|
641
|
+
int capy = sy0 - (int) (ldy * s >> 16);
|
|
642
|
+
|
|
643
|
+
emitLineTo(capx - mx0, capy - my0, scolor0);
|
|
644
|
+
emitLineTo(capx + mx0, capy + my0, scolor0);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
emitClose();
|
|
649
|
+
this.joinSegment = false;
|
|
634
650
|
}
|
|
635
651
|
|
|
636
|
-
|
|
637
|
-
|
|
652
|
+
private void emitMoveTo(int x0, int y0, int c0) {
|
|
653
|
+
output.moveTo(x0, y0, c0);
|
|
638
654
|
}
|
|
639
|
-
this.rindex = 0;
|
|
640
655
|
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
ROUND_JOIN_THRESHOLD);
|
|
644
|
-
} else if (capStyle == LinePath.CAP_SQUARE) {
|
|
645
|
-
long ldx = sx1 - sx0;
|
|
646
|
-
long ldy = sy1 - sy0;
|
|
647
|
-
long llen = lineLength(ldx, ldy);
|
|
648
|
-
if (0 < llen) {
|
|
649
|
-
long s = (long) lineWidth2 * 65536 / llen;
|
|
650
|
-
|
|
651
|
-
int capx = sx0 - (int) (ldx * s >> 16);
|
|
652
|
-
int capy = sy0 - (int) (ldy * s >> 16);
|
|
653
|
-
|
|
654
|
-
emitLineTo(capx - mx0, capy - my0, scolor0);
|
|
655
|
-
emitLineTo(capx + mx0, capy + my0, scolor0);
|
|
656
|
-
}
|
|
656
|
+
private void emitLineTo(int x1, int y1, int c1) {
|
|
657
|
+
output.lineTo(x1, y1, c1);
|
|
657
658
|
}
|
|
658
659
|
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
output.lineTo(x1, y1, c1);
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
private void emitLineTo(int x1, int y1, int c1, boolean rev) {
|
|
672
|
-
if (rev) {
|
|
673
|
-
ensureCapacity(rindex + 3);
|
|
674
|
-
reverse[rindex++] = x1;
|
|
675
|
-
reverse[rindex++] = y1;
|
|
676
|
-
reverse[rindex++] = c1;
|
|
677
|
-
} else {
|
|
678
|
-
emitLineTo(x1, y1, c1);
|
|
660
|
+
private void emitLineTo(int x1, int y1, int c1, boolean rev) {
|
|
661
|
+
if (rev) {
|
|
662
|
+
ensureCapacity(rindex + 3);
|
|
663
|
+
reverse[rindex++] = x1;
|
|
664
|
+
reverse[rindex++] = y1;
|
|
665
|
+
reverse[rindex++] = c1;
|
|
666
|
+
} else {
|
|
667
|
+
emitLineTo(x1, y1, c1);
|
|
668
|
+
}
|
|
679
669
|
}
|
|
680
|
-
}
|
|
681
670
|
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
671
|
+
private void emitClose() {
|
|
672
|
+
output.close();
|
|
673
|
+
}
|
|
685
674
|
}
|