propane 3.4.2-java → 3.5.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.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/wrapper/MavenWrapperDownloader.java +1 -1
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG.md +5 -1
  5. data/Gemfile +2 -0
  6. data/README.md +15 -3
  7. data/Rakefile +9 -10
  8. data/bin/propane +3 -1
  9. data/lib/propane.rb +2 -1
  10. data/lib/propane/app.rb +2 -1
  11. data/lib/propane/creators/sketch_class.rb +7 -1
  12. data/lib/propane/creators/sketch_factory.rb +4 -2
  13. data/lib/propane/creators/sketch_writer.rb +1 -0
  14. data/lib/propane/helper_methods.rb +22 -22
  15. data/lib/propane/helpers/numeric.rb +2 -0
  16. data/lib/propane/helpers/version_error.rb +1 -0
  17. data/lib/propane/library.rb +5 -1
  18. data/lib/propane/library_loader.rb +2 -0
  19. data/lib/propane/native_folder.rb +10 -9
  20. data/lib/propane/native_loader.rb +3 -0
  21. data/lib/propane/runner.rb +11 -5
  22. data/lib/propane/version.rb +2 -1
  23. data/library/boids/boids.rb +21 -11
  24. data/library/color_group/color_group.rb +2 -0
  25. data/library/control_panel/control_panel.rb +8 -5
  26. data/library/dxf/dxf.rb +2 -0
  27. data/library/file_chooser/chooser.rb +10 -9
  28. data/library/file_chooser/file_chooser.rb +10 -9
  29. data/library/library_proxy/library_proxy.rb +2 -0
  30. data/library/net/net.rb +2 -0
  31. data/library/simplex_noise/simplex_noise.rb +2 -0
  32. data/library/slider/slider.rb +23 -22
  33. data/library/vector_utils/vector_utils.rb +4 -0
  34. data/library/video_event/video_event.rb +2 -0
  35. data/pom.rb +46 -45
  36. data/pom.xml +4 -4
  37. data/propane.gemspec +8 -7
  38. data/src/main/java/monkstone/ColorUtil.java +1 -3
  39. data/src/main/java/monkstone/MathToolModule.java +1 -1
  40. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  41. data/src/main/java/monkstone/fastmath/Deglut.java +1 -1
  42. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  43. data/src/main/java/monkstone/noise/SimplexNoise.java +2 -2
  44. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  45. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  46. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  47. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  48. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  49. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  50. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  51. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  52. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  53. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -2
  54. data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
  55. data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
  56. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  57. data/src/main/java/processing/awt/PGraphicsJava2D.java +788 -283
  58. data/src/main/java/processing/awt/PImageAWT.java +260 -0
  59. data/src/main/java/processing/awt/PShapeJava2D.java +56 -53
  60. data/src/main/java/processing/awt/PSurfaceAWT.java +309 -211
  61. data/src/main/java/processing/awt/ShimAWT.java +580 -0
  62. data/src/main/java/processing/core/PApplet.java +2877 -2098
  63. data/src/main/java/processing/core/PConstants.java +477 -447
  64. data/src/main/java/processing/core/PFont.java +930 -884
  65. data/src/main/java/processing/core/PGraphics.java +337 -309
  66. data/src/main/java/processing/core/PImage.java +1689 -1689
  67. data/src/main/java/processing/core/PMatrix.java +172 -159
  68. data/src/main/java/processing/core/PMatrix2D.java +456 -410
  69. data/src/main/java/processing/core/PMatrix3D.java +755 -735
  70. data/src/main/java/processing/core/PShape.java +2910 -2656
  71. data/src/main/java/processing/core/PShapeOBJ.java +97 -94
  72. data/src/main/java/processing/core/PShapeSVG.java +1656 -1462
  73. data/src/main/java/processing/core/PStyle.java +40 -37
  74. data/src/main/java/processing/core/PSurface.java +134 -97
  75. data/src/main/java/processing/core/PSurfaceNone.java +292 -218
  76. data/src/main/java/processing/core/PVector.java +991 -966
  77. data/src/main/java/processing/core/ThinkDifferent.java +12 -8
  78. data/src/main/java/processing/data/DoubleDict.java +756 -710
  79. data/src/main/java/processing/data/DoubleList.java +749 -696
  80. data/src/main/java/processing/data/FloatDict.java +748 -702
  81. data/src/main/java/processing/data/FloatList.java +751 -697
  82. data/src/main/java/processing/data/IntDict.java +720 -673
  83. data/src/main/java/processing/data/IntList.java +699 -633
  84. data/src/main/java/processing/data/JSONArray.java +931 -873
  85. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  86. data/src/main/java/processing/data/JSONTokener.java +351 -341
  87. data/src/main/java/processing/data/LongDict.java +710 -663
  88. data/src/main/java/processing/data/LongList.java +701 -635
  89. data/src/main/java/processing/data/Sort.java +37 -41
  90. data/src/main/java/processing/data/StringDict.java +525 -486
  91. data/src/main/java/processing/data/StringList.java +626 -580
  92. data/src/main/java/processing/data/Table.java +3693 -3513
  93. data/src/main/java/processing/data/TableRow.java +182 -183
  94. data/src/main/java/processing/data/XML.java +954 -880
  95. data/src/main/java/processing/event/Event.java +87 -67
  96. data/src/main/java/processing/event/KeyEvent.java +48 -41
  97. data/src/main/java/processing/event/MouseEvent.java +87 -113
  98. data/src/main/java/processing/event/TouchEvent.java +10 -6
  99. data/src/main/java/processing/javafx/PSurfaceFX.java +26 -0
  100. data/src/main/java/processing/net/Client.java +20 -20
  101. data/src/main/java/processing/net/Server.java +9 -9
  102. data/src/main/java/processing/opengl/FontTexture.java +286 -266
  103. data/src/main/java/processing/opengl/FrameBuffer.java +390 -376
  104. data/src/main/java/processing/opengl/LinePath.java +130 -91
  105. data/src/main/java/processing/opengl/LineStroker.java +593 -582
  106. data/src/main/java/processing/opengl/PGL.java +645 -579
  107. data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
  108. data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
  109. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12287 -12030
  110. data/src/main/java/processing/opengl/PJOGL.java +1743 -1672
  111. data/src/main/java/processing/opengl/PShader.java +345 -416
  112. data/src/main/java/processing/opengl/PShapeOpenGL.java +4601 -4543
  113. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1113 -1029
  114. data/src/main/java/processing/opengl/Texture.java +1489 -1401
  115. data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
  116. data/test/create_test.rb +21 -20
  117. data/test/deglut_spec_test.rb +4 -2
  118. data/test/helper_methods_test.rb +49 -20
  119. data/test/math_tool_test.rb +39 -32
  120. data/test/native_folder.rb +47 -0
  121. data/test/respond_to_test.rb +3 -2
  122. data/test/sketches/key_event.rb +2 -2
  123. data/test/sketches/library/my_library/my_library.rb +3 -0
  124. data/test/test_helper.rb +2 -0
  125. data/test/vecmath_spec_test.rb +35 -22
  126. data/vendors/Rakefile +28 -22
  127. metadata +13 -13
  128. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  129. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  130. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  131. data/src/main/java/processing/opengl/shaders/TexLightVert-vc4.glsl +0 -160
@@ -1,3 +1,5 @@
1
+ /* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2
+
1
3
  /*
2
4
  * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3
5
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -22,653 +24,662 @@
22
24
  * or visit www.oracle.com if you need additional information or have any
23
25
  * questions.
24
26
  */
27
+
25
28
  package processing.opengl;
26
29
 
27
30
  import processing.core.PMatrix2D;
28
31
 
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;
32
+ public class LineStroker {
33
+ private LineStroker output;
34
+ private int capStyle;
35
+ private int joinStyle;
36
+ private int m00, m01;
37
+ private int m10, m11;
38
+ private int lineWidth2;
39
+ private long scaledLineWidth2;
40
+
41
+ // For any pen offset (pen_dx, pen_dy) that does not depend on
42
+ // the line orientation, the pen should be transformed so that:
43
+ //
44
+ // pen_dx' = m00*pen_dx + m01*pen_dy
45
+ // pen_dy' = m10*pen_dx + m11*pen_dy
46
+ //
47
+ // For a round pen, this means:
48
+ //
49
+ // pen_dx(r, theta) = r*cos(theta)
50
+ // pen_dy(r, theta) = r*sin(theta)
51
+ //
52
+ // pen_dx'(r, theta) = r*(m00*cos(theta) + m01*sin(theta))
53
+ // pen_dy'(r, theta) = r*(m10*cos(theta) + m11*sin(theta))
54
+ private int numPenSegments;
55
+ private int[] pen_dx;
56
+ private int[] pen_dy;
57
+
58
+ private boolean[] penIncluded;
59
+ private int[] join;
60
+ private int[] offset = new int[2];
61
+ private int[] reverse = new int[100];
62
+ private int[] miter = new int[2];
63
+ private long miterLimitSq;
64
+ private int prev;
65
+ private int rindex;
66
+ private boolean started;
67
+ private boolean lineToOrigin;
68
+ private boolean joinToOrigin;
69
+ private int sx0, sy0, sx1, sy1, x0, y0;
70
+ private int scolor0, pcolor0, color0;
71
+ private int mx0, my0, omx, omy;
72
+ private int px0, py0;
73
+ private double m00_2_m01_2;
74
+ private double m10_2_m11_2;
75
+ private double m00_m10_m01_m11;
76
+
77
+ /**
78
+ * Empty constructor. <code>setOutput</code> and <code>setParameters</code>
79
+ * must be called prior to calling any other methods.
80
+ */
81
+ public LineStroker() {
82
+ }
83
+
84
+ /**
85
+ * Constructs a <code>LineStroker</code>.
86
+ *
87
+ * @param output
88
+ * an output <code>LineStroker</code>.
89
+ * @param lineWidth
90
+ * the desired line width in pixels, in S15.16 format.
91
+ * @param capStyle
92
+ * the desired end cap style, one of <code>CAP_BUTT</code>,
93
+ * <code>CAP_ROUND</code> or <code>CAP_SQUARE</code>.
94
+ * @param joinStyle
95
+ * the desired line join style, one of <code>JOIN_MITER</code>,
96
+ * <code>JOIN_ROUND</code> or <code>JOIN_BEVEL</code>.
97
+ * @param miterLimit
98
+ * the desired miter limit, in S15.16 format.
99
+ * @param transform
100
+ * a <code>Transform4</code> object indicating the transform that has
101
+ * been previously applied to all incoming coordinates. This is
102
+ * required in order to produce consistently shaped end caps and
103
+ * joins.
104
+ */
105
+ public LineStroker(LineStroker output, int lineWidth, int capStyle, int joinStyle,
106
+ int miterLimit, PMatrix2D transform) {
107
+ setOutput(output);
108
+ setParameters(lineWidth, capStyle, joinStyle, miterLimit, transform);
109
+ }
110
+
111
+ /**
112
+ * Sets the output <code>LineStroker</code> of this <code>LineStroker</code>.
113
+ *
114
+ * @param output
115
+ * an output <code>LineStroker</code>.
116
+ */
117
+ public void setOutput(LineStroker output) {
118
+ this.output = output;
119
+ }
120
+
121
+ /**
122
+ * Sets the parameters of this <code>LineStroker</code>.
123
+ *
124
+ * @param lineWidth
125
+ * the desired line width in pixels, in S15.16 format.
126
+ * @param capStyle
127
+ * the desired end cap style, one of <code>CAP_BUTT</code>,
128
+ * <code>CAP_ROUND</code> or <code>CAP_SQUARE</code>.
129
+ * @param joinStyle
130
+ * the desired line join style, one of <code>JOIN_MITER</code>,
131
+ * <code>JOIN_ROUND</code> or <code>JOIN_BEVEL</code>.
132
+ * @param miterLimit
133
+ * the desired miter limit, in S15.16 format.
134
+ * @param transform
135
+ * a <code>Transform4</code> object indicating the transform that has
136
+ * been previously applied to all incoming coordinates. This is
137
+ * required in order to produce consistently shaped end caps and
138
+ * joins.
139
+ */
140
+ public void setParameters(int lineWidth, int capStyle, int joinStyle,
141
+ int miterLimit, PMatrix2D transform) {
142
+ this.m00 = LinePath.FloatToS15_16(transform.m00);
143
+ this.m01 = LinePath.FloatToS15_16(transform.m01);
144
+ this.m10 = LinePath.FloatToS15_16(transform.m10);
145
+ this.m11 = LinePath.FloatToS15_16(transform.m11);
146
+
147
+ this.lineWidth2 = lineWidth >> 1;
148
+ this.scaledLineWidth2 = ((long) m00 * lineWidth2) >> 16;
149
+ this.capStyle = capStyle;
150
+ this.joinStyle = joinStyle;
151
+
152
+ this.m00_2_m01_2 = (double) m00 * m00 + (double) m01 * m01;
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
+ }
150
168
 
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
- }
169
+ this.numPenSegments = (int) (3.14159f * lineWidth / 65536.0f);
170
+ if (pen_dx == null || pen_dx.length < numPenSegments) {
171
+ this.pen_dx = new int[numPenSegments];
172
+ this.pen_dy = new int[numPenSegments];
173
+ this.penIncluded = new boolean[numPenSegments];
174
+ this.join = new int[2 * numPenSegments];
175
+ }
157
176
 
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
- }
177
+ for (int i = 0; i < numPenSegments; i++) {
178
+ double r = lineWidth / 2.0;
179
+ double theta = i * 2 * Math.PI / numPenSegments;
165
180
 
166
- for (int i = 0; i < numPenSegments; i++) {
167
- double r = lineWidth / 2.0;
168
- double theta = i * 2 * Math.PI / numPenSegments;
181
+ double cos = Math.cos(theta);
182
+ double sin = Math.sin(theta);
183
+ pen_dx[i] = (int) (r * (dm00 * cos + dm01 * sin));
184
+ pen_dy[i] = (int) (r * (dm10 * cos + dm11 * sin));
185
+ }
169
186
 
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
- }
187
+ prev = LinePath.SEG_CLOSE;
188
+ rindex = 0;
189
+ started = false;
190
+ lineToOrigin = false;
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
+ }
175
220
 
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
- }
221
+ m[0] = dx;
222
+ m[1] = dy;
223
+ }
209
224
 
210
- m[0] = dx;
211
- m[1] = dy;
225
+ private void ensureCapacity(int newrindex) {
226
+ if (reverse.length < newrindex) {
227
+ int[] tmp = new int[Math.max(newrindex, 6 * reverse.length / 5)];
228
+ System.arraycopy(reverse, 0, tmp, 0, rindex);
229
+ this.reverse = tmp;
212
230
  }
213
-
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
- }
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;
220
262
  }
221
-
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;
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
+ }
228
273
  }
229
274
 
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;
275
+ int start = -1, end = -1;
276
+ for (int i = 0; i < numPenSegments; i++) {
277
+ if (penIncluded[i]
278
+ && !penIncluded[(i + numPenSegments - 1) % numPenSegments]) {
279
+ start = i;
280
+ }
281
+ if (penIncluded[i] && !penIncluded[(i + 1) % numPenSegments]) {
282
+ end = i;
283
+ }
239
284
  }
240
285
 
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;
245
-
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
- }
263
-
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
- }
274
-
275
- if (end < start) {
276
- end += numPenSegments;
277
- }
278
-
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
- }
300
-
301
- return ncoords / 2;
286
+ if (end < start) {
287
+ end += numPenSegments;
302
288
  }
303
289
 
304
- //private static final long ROUND_JOIN_THRESHOLD = 1000L;
305
- private static final long ROUND_JOIN_THRESHOLD = 100000000L;
306
-
307
- private static final long ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000L;
290
+ if (start != -1 && end != -1) {
291
+ long dxa = cx + pen_dx[start] - xa;
292
+ long dya = cy + pen_dy[start] - ya;
293
+ long dxb = cx + pen_dx[start] - xb;
294
+ long dyb = cy + pen_dy[start] - yb;
295
+
296
+ boolean rev = (dxa * dxa + dya * dya > dxb * dxb + dyb * dyb);
297
+ int i = rev ? end : start;
298
+ int incr = rev ? -1 : 1;
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
+ }
310
+ }
308
311
 
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
- }
312
+ return ncoords / 2;
313
+ }
315
314
 
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
- }
315
+ //private static final long ROUND_JOIN_THRESHOLD = 1000L;
316
+ private static final long ROUND_JOIN_THRESHOLD = 100000000L;
329
317
 
330
- int bx0 = x + omx;
331
- int by0 = y + omy;
332
- int bx1 = x + mx;
333
- int by1 = y + my;
318
+ private static final long ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000L;
334
319
 
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
- }
320
+ private void drawRoundJoin(int x, int y, int omx, int omy, int mx, int my,
321
+ int side, int color,
322
+ boolean flip, boolean rev, long threshold) {
323
+ if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) {
324
+ return;
339
325
  }
340
326
 
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);
327
+ long domx = (long) omx - mx;
328
+ long domy = (long) omy - my;
329
+ long len = domx * domx + domy * domy;
330
+ if (len < threshold) {
331
+ return;
370
332
  }
371
333
 
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
- }
384
-
385
- if (rev) {
386
- omx = -omx;
387
- omy = -omy;
388
- mx = -mx;
389
- my = -my;
390
- }
391
-
392
- computeMiter(px0 + omx, py0 + omy, x0 + omx, y0 + omy, x0 + mx, y0 + my, x1
393
- + mx, y1 + my, miter);
334
+ if (rev) {
335
+ omx = -omx;
336
+ omy = -omy;
337
+ mx = -mx;
338
+ my = -my;
339
+ }
394
340
 
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;
341
+ int bx0 = x + omx;
342
+ int by0 = y + omy;
343
+ int bx1 = x + mx;
344
+ int by1 = y + my;
401
345
 
402
- if (lenSq < miterLimitSq) {
403
- emitLineTo(miter[0], miter[1], color, rev);
404
- }
346
+ int npoints = computeRoundJoin(x, y, bx0, by0, bx1, by1, side, flip, join);
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;
405
376
  }
406
377
 
407
- public void moveTo(int x0, int y0, int c0) {
408
- // System.out.println("LineStroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
378
+ long t = (x1p * (y0 - y0p) - x0 * y10p + x0p * (y1p - y0)) >> 16;
379
+ m[0] = (int) (x0 + (t * x10) / den);
380
+ m[1] = (int) (y0 + (t * y10) / den);
381
+ }
409
382
 
410
- if (lineToOrigin) {
411
- // not closing the path, do the previous lineTo
412
- lineToImpl(sx0, sy0, scolor0, joinToOrigin);
413
- lineToOrigin = false;
414
- }
383
+ private void drawMiter(int px0, int py0, int x0, int y0, int x1, int y1,
384
+ int omx, int omy, int mx, int my, int color,
385
+ boolean rev) {
386
+ if (mx == omx && my == omy) {
387
+ return;
388
+ }
389
+ if (px0 == x0 && py0 == y0) {
390
+ return;
391
+ }
392
+ if (x0 == x1 && y0 == y1) {
393
+ return;
394
+ }
415
395
 
416
- if (prev == LinePath.SEG_LINETO) {
417
- finish();
418
- }
396
+ if (rev) {
397
+ omx = -omx;
398
+ omy = -omy;
399
+ mx = -mx;
400
+ my = -my;
401
+ }
419
402
 
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
- }
403
+ computeMiter(px0 + omx, py0 + omy, x0 + omx, y0 + omy, x0 + mx, y0 + my, x1
404
+ + mx, y1 + my, miter);
456
405
 
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
- }
406
+ // Compute miter length in untransformed coordinates
407
+ long dx = (long) miter[0] - x0;
408
+ long dy = (long) miter[1] - y0;
409
+ long a = (dy * m00 - dx * m10) >> 16;
410
+ long b = (dy * m01 - dx * m11) >> 16;
411
+ long lenSq = a * a + b * b;
490
412
 
491
- emitLineTo(x0 + mx, y0 + my, color0, false);
492
- emitLineTo(x1 + mx, y1 + my, c1, false);
413
+ if (lenSq < miterLimitSq) {
414
+ emitLineTo(miter[0], miter[1], color, rev);
415
+ }
416
+ }
493
417
 
494
- emitLineTo(x0 - mx, y0 - my, color0, true);
495
- emitLineTo(x1 - mx, y1 - my, c1, true);
418
+ public void moveTo(int x0, int y0, int c0) {
419
+ // System.out.println("LineStroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
496
420
 
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;
421
+ if (lineToOrigin) {
422
+ // not closing the path, do the previous lineTo
423
+ lineToImpl(sx0, sy0, scolor0, joinToOrigin);
424
+ lineToOrigin = false;
506
425
  }
507
426
 
508
- public void close() {
509
- if (lineToOrigin) {
510
- // ignore the previous lineTo
511
- lineToOrigin = false;
512
- }
427
+ if (prev == LinePath.SEG_LINETO) {
428
+ finish();
429
+ }
513
430
 
514
- if (!started) {
515
- finish();
516
- return;
517
- }
431
+ this.sx0 = this.x0 = x0;
432
+ this.sy0 = this.y0 = y0;
433
+ this.scolor0 = this.color0 = c0;
434
+ this.rindex = 0;
435
+ this.started = false;
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
+ }
518
467
 
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,
468
+ lineToImpl(x1, y1, c1, joinSegment);
469
+ joinSegment = false;
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,
530
491
  ROUND_JOIN_THRESHOLD);
531
- }
532
- } else {
533
- // Draw internal joins as round
534
- drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
535
- ROUND_JOIN_INTERNAL_THRESHOLD);
536
492
  }
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
+ }
537
498
 
538
- emitLineTo(x0 + mx, y0 + my, color0);
539
- emitLineTo(sx0 + mx, sy0 + my, scolor0);
499
+ emitLineTo(x0, y0, color0, !ccw);
500
+ }
540
501
 
541
- ccw = isCCW(x0, y0, sx0, sy0, sx1, sy1);
502
+ emitLineTo(x0 + mx, y0 + my, color0, false);
503
+ emitLineTo(x1 + mx, y1 + my, c1, false);
504
+
505
+ emitLineTo(x0 - mx, y0 - my, color0, true);
506
+ emitLineTo(x1 - mx, y1 - my, c1, true);
507
+
508
+ this.omx = mx;
509
+ this.omy = my;
510
+ this.px0 = x0;
511
+ this.py0 = y0;
512
+ this.pcolor0 = color0;
513
+ this.x0 = x1;
514
+ this.y0 = y1;
515
+ this.color0 = c1;
516
+ this.prev = LinePath.SEG_LINETO;
517
+ }
518
+
519
+ public void close() {
520
+ if (lineToOrigin) {
521
+ // ignore the previous lineTo
522
+ lineToOrigin = false;
523
+ }
542
524
 
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
- }
525
+ if (!started) {
526
+ finish();
527
+ return;
528
+ }
552
529
 
553
- emitLineTo(sx0 + mx0, sy0 + my0, scolor0);
554
- emitLineTo(sx0 - mx0, sy0 - my0, scolor0); // same as reverse[0], reverse[1]
530
+ computeOffset(x0, y0, sx0, sy0, offset);
531
+ int mx = offset[0];
532
+ int my = offset[1];
533
+
534
+ // Draw penultimate join
535
+ boolean ccw = isCCW(px0, py0, x0, y0, sx0, sy0);
536
+ if (joinSegment) {
537
+ if (joinStyle == LinePath.JOIN_MITER) {
538
+ drawMiter(px0, py0, x0, y0, sx0, sy0, omx, omy, mx, my, pcolor0, ccw);
539
+ } else if (joinStyle == LinePath.JOIN_ROUND) {
540
+ drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
541
+ ROUND_JOIN_THRESHOLD);
542
+ }
543
+ } else {
544
+ // Draw internal joins as round
545
+ drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
546
+ ROUND_JOIN_INTERNAL_THRESHOLD);
547
+ }
555
548
 
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
- }
549
+ emitLineTo(x0 + mx, y0 + my, color0);
550
+ emitLineTo(sx0 + mx, sy0 + my, scolor0);
566
551
 
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
- }
552
+ ccw = isCCW(x0, y0, sx0, sy0, sx1, sy1);
572
553
 
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();
554
+ // Draw final join on the outside
555
+ if (!ccw) {
556
+ if (joinStyle == LinePath.JOIN_MITER) {
557
+ drawMiter(x0, y0, sx0, sy0, sx1, sy1, mx, my, mx0, my0, color0, false);
558
+ } else if (joinStyle == LinePath.JOIN_ROUND) {
559
+ drawRoundJoin(sx0, sy0, mx, my, mx0, my0, 0, scolor0, false, false,
560
+ ROUND_JOIN_THRESHOLD);
561
+ }
580
562
  }
581
563
 
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;
564
+ emitLineTo(sx0 + mx0, sy0 + my0, scolor0);
565
+ emitLineTo(sx0 - mx0, sy0 - my0, scolor0); // same as reverse[0], reverse[1]
566
+
567
+ // Draw final join on the inside
568
+ if (ccw) {
569
+ if (joinStyle == LinePath.JOIN_MITER) {
570
+ drawMiter(x0, y0, sx0, sy0, sx1, sy1, -mx, -my, -mx0, -my0, color0,
571
+ false);
572
+ } else if (joinStyle == LinePath.JOIN_ROUND) {
573
+ drawRoundJoin(sx0, sy0, -mx, -my, -mx0, -my0, 0, scolor0, true, false,
574
+ ROUND_JOIN_THRESHOLD);
575
+ }
596
576
  }
597
577
 
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;
578
+ emitLineTo(sx0 - mx, sy0 - my, scolor0);
579
+ emitLineTo(x0 - mx, y0 - my, color0);
580
+ for (int i = rindex - 3; i >= 0; i -= 3) {
581
+ emitLineTo(reverse[i], reverse[i + 1], reverse[i + 2]);
604
582
  }
605
583
 
606
- private void finish() {
607
- if (capStyle == LinePath.CAP_ROUND) {
608
- drawRoundJoin(x0, y0, omx, omy, -omx, -omy, 1, color0, false, false,
609
- ROUND_JOIN_THRESHOLD);
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
- }
584
+ this.x0 = this.sx0;
585
+ this.y0 = this.sy0;
586
+ this.rindex = 0;
587
+ this.started = false;
588
+ this.joinSegment = false;
589
+ this.prev = LinePath.SEG_CLOSE;
590
+ emitClose();
591
+ }
592
+
593
+ public void end() {
594
+ if (lineToOrigin) {
595
+ // not closing the path, do the previous lineTo
596
+ lineToImpl(sx0, sy0, scolor0, joinToOrigin);
597
+ lineToOrigin = false;
598
+ }
624
599
 
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;
600
+ if (prev == LinePath.SEG_LINETO) {
601
+ finish();
602
+ }
629
603
 
630
- if (capStyle == LinePath.CAP_ROUND) {
631
- drawRoundJoin(sx0, sy0, -mx0, -my0, mx0, my0, 1, scolor0, false, false,
604
+ output.end();
605
+ this.joinSegment = false;
606
+ this.prev = LinePath.SEG_MOVETO;
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,
632
620
  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;
621
+ } else if (capStyle == LinePath.CAP_SQUARE) {
622
+ long ldx = px0 - x0;
623
+ long ldy = py0 - y0;
624
+ long llen = lineLength(ldx, ldy);
625
+ if (0 < llen) {
626
+ long s = (long) lineWidth2 * 65536 / llen;
627
+
628
+ int capx = x0 - (int) (ldx * s >> 16);
629
+ int capy = y0 - (int) (ldy * s >> 16);
630
+
631
+ emitLineTo(capx + omx, capy + omy, color0);
632
+ emitLineTo(capx - omx, capy - omy, color0);
633
+ }
650
634
  }
651
635
 
652
- private void emitMoveTo(int x0, int y0, int c0) {
653
- output.moveTo(x0, y0, c0);
636
+ for (int i = rindex - 3; i >= 0; i -= 3) {
637
+ emitLineTo(reverse[i], reverse[i + 1], reverse[i + 2]);
654
638
  }
639
+ this.rindex = 0;
655
640
 
656
- private void emitLineTo(int x1, int y1, int c1) {
657
- output.lineTo(x1, y1, c1);
641
+ if (capStyle == LinePath.CAP_ROUND) {
642
+ drawRoundJoin(sx0, sy0, -mx0, -my0, mx0, my0, 1, scolor0, false, false,
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
+ }
658
657
  }
659
658
 
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
- }
659
+ emitClose();
660
+ this.joinSegment = false;
661
+ }
662
+
663
+ private void emitMoveTo(int x0, int y0, int c0) {
664
+ output.moveTo(x0, y0, c0);
665
+ }
666
+
667
+ private void emitLineTo(int x1, int y1, int c1) {
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);
669
679
  }
680
+ }
670
681
 
671
- private void emitClose() {
672
- output.close();
673
- }
682
+ private void emitClose() {
683
+ output.close();
684
+ }
674
685
  }