propane 3.4.1-java → 3.7.1-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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/.mvn/extensions.xml +1 -1
  3. data/.mvn/wrapper/MavenWrapperDownloader.java +2 -2
  4. data/.mvn/wrapper/maven-wrapper.properties +2 -2
  5. data/.travis.yml +1 -1
  6. data/CHANGELOG.md +9 -1
  7. data/Gemfile +2 -0
  8. data/README.md +9 -5
  9. data/Rakefile +10 -11
  10. data/bin/propane +3 -1
  11. data/lib/propane.rb +4 -2
  12. data/lib/propane/app.rb +2 -1
  13. data/lib/propane/creators/sketch_class.rb +7 -1
  14. data/lib/propane/creators/sketch_factory.rb +4 -2
  15. data/lib/propane/creators/sketch_writer.rb +1 -0
  16. data/lib/propane/helper_methods.rb +22 -23
  17. data/lib/propane/helpers/numeric.rb +2 -0
  18. data/lib/propane/helpers/version_error.rb +1 -0
  19. data/lib/propane/library.rb +5 -1
  20. data/lib/propane/library_loader.rb +2 -0
  21. data/lib/propane/native_folder.rb +10 -9
  22. data/lib/propane/native_loader.rb +3 -0
  23. data/lib/propane/runner.rb +20 -14
  24. data/lib/propane/version.rb +2 -1
  25. data/library/boids/boids.rb +21 -11
  26. data/library/color_group/color_group.rb +2 -0
  27. data/library/control_panel/control_panel.rb +8 -5
  28. data/library/dxf/dxf.rb +2 -0
  29. data/library/file_chooser/chooser.rb +10 -9
  30. data/library/file_chooser/file_chooser.rb +10 -9
  31. data/library/library_proxy/library_proxy.rb +2 -0
  32. data/library/net/net.rb +2 -0
  33. data/library/simplex_noise/simplex_noise.rb +2 -0
  34. data/library/slider/slider.rb +23 -22
  35. data/library/vector_utils/vector_utils.rb +4 -0
  36. data/library/video_event/video_event.rb +2 -0
  37. data/pom.rb +37 -36
  38. data/pom.xml +6 -6
  39. data/propane.gemspec +12 -10
  40. data/src/main/java/japplemenubar/JAppleMenuBar.java +3 -3
  41. data/src/main/java/monkstone/ColorUtil.java +1 -3
  42. data/src/main/java/monkstone/MathToolModule.java +10 -9
  43. data/src/main/java/monkstone/PropaneLibrary.java +2 -2
  44. data/src/main/java/monkstone/fastmath/Deglut.java +1 -1
  45. data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
  46. data/src/main/java/monkstone/noise/SimplexNoise.java +2 -2
  47. data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
  48. data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
  49. data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +1 -1
  50. data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
  51. data/src/main/java/monkstone/slider/SliderBar.java +1 -1
  52. data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
  53. data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
  54. data/src/main/java/monkstone/vecmath/package-info.java +1 -1
  55. data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
  56. data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -2
  57. data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
  58. data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
  59. data/src/main/java/monkstone/videoevent/package-info.java +1 -1
  60. data/src/main/java/processing/awt/PGraphicsJava2D.java +781 -285
  61. data/src/main/java/processing/awt/PImageAWT.java +377 -0
  62. data/src/main/java/processing/awt/PShapeJava2D.java +56 -52
  63. data/src/main/java/processing/awt/PSurfaceAWT.java +308 -208
  64. data/src/main/java/processing/awt/ShimAWT.java +581 -0
  65. data/src/main/java/processing/core/PApplet.java +4225 -4855
  66. data/src/main/java/processing/core/PConstants.java +477 -447
  67. data/src/main/java/processing/core/PFont.java +914 -880
  68. data/src/main/java/processing/core/PGraphics.java +150 -134
  69. data/src/main/java/processing/core/PImage.java +275 -372
  70. data/src/main/java/processing/core/PMatrix.java +172 -159
  71. data/src/main/java/processing/core/PMatrix2D.java +478 -415
  72. data/src/main/java/processing/core/PMatrix3D.java +762 -735
  73. data/src/main/java/processing/core/PShape.java +2887 -2651
  74. data/src/main/java/processing/core/PShapeOBJ.java +97 -92
  75. data/src/main/java/processing/core/PShapeSVG.java +1705 -1490
  76. data/src/main/java/processing/core/PStyle.java +40 -37
  77. data/src/main/java/processing/core/PSurface.java +139 -97
  78. data/src/main/java/processing/core/PSurfaceNone.java +296 -218
  79. data/src/main/java/processing/core/PVector.java +995 -963
  80. data/src/main/java/processing/core/ThinkDifferent.java +12 -8
  81. data/src/main/java/processing/data/DoubleDict.java +756 -710
  82. data/src/main/java/processing/data/DoubleList.java +749 -696
  83. data/src/main/java/processing/data/FloatDict.java +748 -702
  84. data/src/main/java/processing/data/FloatList.java +751 -697
  85. data/src/main/java/processing/data/IntDict.java +720 -673
  86. data/src/main/java/processing/data/IntList.java +699 -633
  87. data/src/main/java/processing/data/JSONArray.java +931 -873
  88. data/src/main/java/processing/data/JSONObject.java +1262 -1165
  89. data/src/main/java/processing/data/JSONTokener.java +351 -341
  90. data/src/main/java/processing/data/LongDict.java +710 -663
  91. data/src/main/java/processing/data/LongList.java +701 -635
  92. data/src/main/java/processing/data/Sort.java +37 -41
  93. data/src/main/java/processing/data/StringDict.java +525 -486
  94. data/src/main/java/processing/data/StringList.java +626 -580
  95. data/src/main/java/processing/data/Table.java +3690 -3510
  96. data/src/main/java/processing/data/TableRow.java +182 -183
  97. data/src/main/java/processing/data/XML.java +957 -883
  98. data/src/main/java/processing/event/Event.java +87 -67
  99. data/src/main/java/processing/event/KeyEvent.java +48 -41
  100. data/src/main/java/processing/event/MouseEvent.java +88 -113
  101. data/src/main/java/processing/event/TouchEvent.java +10 -6
  102. data/src/main/java/processing/javafx/PGraphicsFX2D.java +20 -345
  103. data/src/main/java/processing/javafx/PSurfaceFX.java +149 -121
  104. data/src/main/java/processing/net/Client.java +20 -20
  105. data/src/main/java/processing/net/Server.java +9 -9
  106. data/src/main/java/processing/opengl/FontTexture.java +286 -266
  107. data/src/main/java/processing/opengl/FrameBuffer.java +389 -377
  108. data/src/main/java/processing/opengl/LinePath.java +132 -89
  109. data/src/main/java/processing/opengl/LineStroker.java +588 -581
  110. data/src/main/java/processing/opengl/PGL.java +660 -567
  111. data/src/main/java/processing/opengl/PGraphics2D.java +408 -315
  112. data/src/main/java/processing/opengl/PGraphics3D.java +107 -72
  113. data/src/main/java/processing/opengl/PGraphicsOpenGL.java +12378 -12075
  114. data/src/main/java/processing/opengl/PJOGL.java +1753 -1670
  115. data/src/main/java/processing/opengl/PShader.java +369 -461
  116. data/src/main/java/processing/opengl/PShapeOpenGL.java +4678 -4580
  117. data/src/main/java/processing/opengl/PSurfaceJOGL.java +1114 -1027
  118. data/src/main/java/processing/opengl/Texture.java +1492 -1401
  119. data/src/main/java/processing/opengl/VertexBuffer.java +57 -55
  120. data/test/create_test.rb +21 -20
  121. data/test/deglut_spec_test.rb +4 -2
  122. data/test/helper_methods_test.rb +49 -20
  123. data/test/math_tool_test.rb +39 -32
  124. data/test/native_folder.rb +47 -0
  125. data/test/respond_to_test.rb +3 -2
  126. data/test/sketches/key_event.rb +2 -2
  127. data/test/sketches/library/my_library/my_library.rb +3 -0
  128. data/test/test_helper.rb +2 -0
  129. data/test/vecmath_spec_test.rb +35 -22
  130. data/vendors/Rakefile +35 -40
  131. metadata +42 -22
  132. data/src/main/java/processing/opengl/shaders/LightVert-brcm.glsl +0 -154
  133. data/src/main/java/processing/opengl/shaders/LightVert-vc4.glsl +0 -154
  134. data/src/main/java/processing/opengl/shaders/TexLightVert-brcm.glsl +0 -160
  135. 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,658 @@
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);
220
262
  }
263
+ for (int i = 0; i < numPenSegments; i++) {
264
+ px = cx + pen_dx[i];
265
+ py = cy + pen_dy[i];
221
266
 
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;
267
+ boolean penSide = side(px, py, xa, ya, xb, yb);
268
+ penIncluded[i] = penSide != centerSide;
228
269
  }
229
270
 
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;
271
+ int start = -1, end = -1;
272
+ for (int i = 0; i < numPenSegments; i++) {
273
+ if (penIncluded[i]
274
+ && !penIncluded[(i + numPenSegments - 1) % numPenSegments]) {
275
+ start = i;
276
+ }
277
+ if (penIncluded[i] && !penIncluded[(i + 1) % numPenSegments]) {
278
+ end = i;
279
+ }
239
280
  }
240
281
 
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;
282
+ if (end < start) {
283
+ end += numPenSegments;
302
284
  }
303
285
 
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;
308
-
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
- }
286
+ if (start != -1 && end != -1) {
287
+ long dxa = cx + pen_dx[start] - xa;
288
+ long dya = cy + pen_dy[start] - ya;
289
+ long dxb = cx + pen_dx[start] - xb;
290
+ long dyb = cy + pen_dy[start] - yb;
291
+
292
+ boolean rev = (dxa * dxa + dya * dya > dxb * dxb + dyb * dyb);
293
+ int i = rev ? end : start;
294
+ int incr = rev ? -1 : 1;
295
+ while (true) {
296
+ int idx = i % numPenSegments;
297
+ px = cx + pen_dx[idx];
298
+ py = cy + pen_dy[idx];
299
+ join[ncoords++] = px;
300
+ join[ncoords++] = py;
301
+ if (i == (rev ? start : end)) {
302
+ break;
303
+ }
304
+ i += incr;
305
+ }
306
+ }
315
307
 
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
- }
308
+ return ncoords / 2;
309
+ }
322
310
 
323
- if (rev) {
324
- omx = -omx;
325
- omy = -omy;
326
- mx = -mx;
327
- my = -my;
328
- }
311
+ //private static final long ROUND_JOIN_THRESHOLD = 1000L;
312
+ private static final long ROUND_JOIN_THRESHOLD = 100000000L;
329
313
 
330
- int bx0 = x + omx;
331
- int by0 = y + omy;
332
- int bx1 = x + mx;
333
- int by1 = y + my;
314
+ private static final long ROUND_JOIN_INTERNAL_THRESHOLD = 1000000000L;
334
315
 
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
- }
316
+ private void drawRoundJoin(int x, int y, int omx, int omy, int mx, int my,
317
+ int side, int color,
318
+ boolean flip, boolean rev, long threshold) {
319
+ if ((omx == 0 && omy == 0) || (mx == 0 && my == 0)) {
320
+ return;
339
321
  }
340
322
 
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);
323
+ long domx = (long) omx - mx;
324
+ long domy = (long) omy - my;
325
+ long len = domx * domx + domy * domy;
326
+ if (len < threshold) {
327
+ return;
370
328
  }
371
329
 
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);
330
+ if (rev) {
331
+ omx = -omx;
332
+ omy = -omy;
333
+ mx = -mx;
334
+ my = -my;
335
+ }
394
336
 
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;
337
+ int bx0 = x + omx;
338
+ int by0 = y + omy;
339
+ int bx1 = x + mx;
340
+ int by1 = y + my;
401
341
 
402
- if (lenSq < miterLimitSq) {
403
- emitLineTo(miter[0], miter[1], color, rev);
404
- }
342
+ int npoints = computeRoundJoin(x, y, bx0, by0, bx1, by1, side, flip, join);
343
+ for (int i = 0; i < npoints; i++) {
344
+ emitLineTo(join[2 * i], join[2 * i + 1], color, rev);
345
+ }
346
+ }
347
+
348
+ // Return the intersection point of the lines (ix0, iy0) -> (ix1, iy1)
349
+ // and (ix0p, iy0p) -> (ix1p, iy1p) in m[0] and m[1]
350
+ private void computeMiter(int ix0, int iy0, int ix1, int iy1, int ix0p,
351
+ int iy0p, int ix1p, int iy1p, int[] m) {
352
+ long x0 = ix0;
353
+ long y0 = iy0;
354
+ long x1 = ix1;
355
+ long y1 = iy1;
356
+
357
+ long x0p = ix0p;
358
+ long y0p = iy0p;
359
+ long x1p = ix1p;
360
+ long y1p = iy1p;
361
+
362
+ long x10 = x1 - x0;
363
+ long y10 = y1 - y0;
364
+ long x10p = x1p - x0p;
365
+ long y10p = y1p - y0p;
366
+
367
+ long den = (x10 * y10p - x10p * y10) >> 16;
368
+ if (den == 0) {
369
+ m[0] = ix0;
370
+ m[1] = iy0;
371
+ return;
405
372
  }
406
373
 
407
- public void moveTo(int x0, int y0, int c0) {
408
- // System.out.println("LineStroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
374
+ long t = (x1p * (y0 - y0p) - x0 * y10p + x0p * (y1p - y0)) >> 16;
375
+ m[0] = (int) (x0 + (t * x10) / den);
376
+ m[1] = (int) (y0 + (t * y10) / den);
377
+ }
409
378
 
410
- if (lineToOrigin) {
411
- // not closing the path, do the previous lineTo
412
- lineToImpl(sx0, sy0, scolor0, joinToOrigin);
413
- lineToOrigin = false;
414
- }
379
+ private void drawMiter(int px0, int py0, int x0, int y0, int x1, int y1,
380
+ int omx, int omy, int mx, int my, int color,
381
+ boolean rev) {
382
+ if (mx == omx && my == omy) {
383
+ return;
384
+ }
385
+ if (px0 == x0 && py0 == y0) {
386
+ return;
387
+ }
388
+ if (x0 == x1 && y0 == y1) {
389
+ return;
390
+ }
415
391
 
416
- if (prev == LinePath.SEG_LINETO) {
417
- finish();
418
- }
392
+ if (rev) {
393
+ omx = -omx;
394
+ omy = -omy;
395
+ mx = -mx;
396
+ my = -my;
397
+ }
419
398
 
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
- }
399
+ computeMiter(px0 + omx, py0 + omy, x0 + omx, y0 + omy, x0 + mx, y0 + my, x1
400
+ + mx, y1 + my, miter);
456
401
 
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
- }
402
+ // Compute miter length in untransformed coordinates
403
+ long dx = (long) miter[0] - x0;
404
+ long dy = (long) miter[1] - y0;
405
+ long a = (dy * m00 - dx * m10) >> 16;
406
+ long b = (dy * m01 - dx * m11) >> 16;
407
+ long lenSq = a * a + b * b;
490
408
 
491
- emitLineTo(x0 + mx, y0 + my, color0, false);
492
- emitLineTo(x1 + mx, y1 + my, c1, false);
409
+ if (lenSq < miterLimitSq) {
410
+ emitLineTo(miter[0], miter[1], color, rev);
411
+ }
412
+ }
493
413
 
494
- emitLineTo(x0 - mx, y0 - my, color0, true);
495
- emitLineTo(x1 - mx, y1 - my, c1, true);
414
+ public void moveTo(int x0, int y0, int c0) {
415
+ // System.out.println("LineStroker.moveTo(" + x0/65536.0 + ", " + y0/65536.0 + ")");
496
416
 
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;
417
+ if (lineToOrigin) {
418
+ // not closing the path, do the previous lineTo
419
+ lineToImpl(sx0, sy0, scolor0, joinToOrigin);
420
+ lineToOrigin = false;
506
421
  }
507
422
 
508
- public void close() {
509
- if (lineToOrigin) {
510
- // ignore the previous lineTo
511
- lineToOrigin = false;
512
- }
423
+ if (prev == LinePath.SEG_LINETO) {
424
+ finish();
425
+ }
513
426
 
514
- if (!started) {
515
- finish();
516
- return;
517
- }
427
+ this.sx0 = this.x0 = x0;
428
+ this.sy0 = this.y0 = y0;
429
+ this.scolor0 = this.color0 = c0;
430
+ this.rindex = 0;
431
+ this.started = false;
432
+ this.joinSegment = false;
433
+ this.prev = LinePath.SEG_MOVETO;
434
+ }
435
+
436
+ boolean joinSegment = false;
437
+
438
+ public void lineJoin() {
439
+ // System.out.println("LineStroker.lineJoin()");
440
+ this.joinSegment = true;
441
+ }
442
+
443
+ public void lineTo(int x1, int y1, int c1) {
444
+ // System.out.println("LineStroker.lineTo(" + x1/65536.0 + ", " + y1/65536.0 + ")");
445
+
446
+ if (lineToOrigin) {
447
+ if (x1 == sx0 && y1 == sy0) {
448
+ // staying in the starting point
449
+ return;
450
+ }
451
+
452
+ // not closing the path, do the previous lineTo
453
+ lineToImpl(sx0, sy0, scolor0, joinToOrigin);
454
+ lineToOrigin = false;
455
+ } else if (x1 == x0 && y1 == y0) {
456
+ return;
457
+ } else if (x1 == sx0 && y1 == sy0) {
458
+ lineToOrigin = true;
459
+ joinToOrigin = joinSegment;
460
+ joinSegment = false;
461
+ return;
462
+ }
518
463
 
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,
464
+ lineToImpl(x1, y1, c1, joinSegment);
465
+ joinSegment = false;
466
+ }
467
+
468
+ private void lineToImpl(int x1, int y1, int c1, boolean joinSegment) {
469
+ computeOffset(x0, y0, x1, y1, offset);
470
+ int mx = offset[0];
471
+ int my = offset[1];
472
+
473
+ if (!started) {
474
+ emitMoveTo(x0 + mx, y0 + my, color0);
475
+ this.sx1 = x1;
476
+ this.sy1 = y1;
477
+ this.mx0 = mx;
478
+ this.my0 = my;
479
+ started = true;
480
+ } else {
481
+ boolean ccw = isCCW(px0, py0, x0, y0, x1, y1);
482
+ if (joinSegment) {
483
+ if (joinStyle == LinePath.JOIN_MITER) {
484
+ drawMiter(px0, py0, x0, y0, x1, y1, omx, omy, mx, my, color0, ccw);
485
+ } else if (joinStyle == LinePath.JOIN_ROUND) {
486
+ drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
530
487
  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
488
  }
489
+ } else {
490
+ // Draw internal joins as round
491
+ drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
492
+ ROUND_JOIN_INTERNAL_THRESHOLD);
493
+ }
537
494
 
538
- emitLineTo(x0 + mx, y0 + my, color0);
539
- emitLineTo(sx0 + mx, sy0 + my, scolor0);
495
+ emitLineTo(x0, y0, color0, !ccw);
496
+ }
540
497
 
541
- ccw = isCCW(x0, y0, sx0, sy0, sx1, sy1);
498
+ emitLineTo(x0 + mx, y0 + my, color0, false);
499
+ emitLineTo(x1 + mx, y1 + my, c1, false);
500
+
501
+ emitLineTo(x0 - mx, y0 - my, color0, true);
502
+ emitLineTo(x1 - mx, y1 - my, c1, true);
503
+
504
+ this.omx = mx;
505
+ this.omy = my;
506
+ this.px0 = x0;
507
+ this.py0 = y0;
508
+ this.pcolor0 = color0;
509
+ this.x0 = x1;
510
+ this.y0 = y1;
511
+ this.color0 = c1;
512
+ this.prev = LinePath.SEG_LINETO;
513
+ }
514
+
515
+ public void close() {
516
+ if (lineToOrigin) {
517
+ // ignore the previous lineTo
518
+ lineToOrigin = false;
519
+ }
542
520
 
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
- }
521
+ if (!started) {
522
+ finish();
523
+ return;
524
+ }
552
525
 
553
- emitLineTo(sx0 + mx0, sy0 + my0, scolor0);
554
- emitLineTo(sx0 - mx0, sy0 - my0, scolor0); // same as reverse[0], reverse[1]
526
+ computeOffset(x0, y0, sx0, sy0, offset);
527
+ int mx = offset[0];
528
+ int my = offset[1];
529
+
530
+ // Draw penultimate join
531
+ boolean ccw = isCCW(px0, py0, x0, y0, sx0, sy0);
532
+ if (joinSegment) {
533
+ if (joinStyle == LinePath.JOIN_MITER) {
534
+ drawMiter(px0, py0, x0, y0, sx0, sy0, omx, omy, mx, my, pcolor0, ccw);
535
+ } else if (joinStyle == LinePath.JOIN_ROUND) {
536
+ drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
537
+ ROUND_JOIN_THRESHOLD);
538
+ }
539
+ } else {
540
+ // Draw internal joins as round
541
+ drawRoundJoin(x0, y0, omx, omy, mx, my, 0, color0, false, ccw,
542
+ ROUND_JOIN_INTERNAL_THRESHOLD);
543
+ }
555
544
 
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
- }
545
+ emitLineTo(x0 + mx, y0 + my, color0);
546
+ emitLineTo(sx0 + mx, sy0 + my, scolor0);
566
547
 
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
- }
548
+ ccw = isCCW(x0, y0, sx0, sy0, sx1, sy1);
572
549
 
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();
550
+ // Draw final join on the outside
551
+ if (!ccw) {
552
+ if (joinStyle == LinePath.JOIN_MITER) {
553
+ drawMiter(x0, y0, sx0, sy0, sx1, sy1, mx, my, mx0, my0, color0, false);
554
+ } else if (joinStyle == LinePath.JOIN_ROUND) {
555
+ drawRoundJoin(sx0, sy0, mx, my, mx0, my0, 0, scolor0, false, false,
556
+ ROUND_JOIN_THRESHOLD);
557
+ }
580
558
  }
581
559
 
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;
560
+ emitLineTo(sx0 + mx0, sy0 + my0, scolor0);
561
+ emitLineTo(sx0 - mx0, sy0 - my0, scolor0); // same as reverse[0], reverse[1]
562
+
563
+ // Draw final join on the inside
564
+ if (ccw) {
565
+ if (joinStyle == LinePath.JOIN_MITER) {
566
+ drawMiter(x0, y0, sx0, sy0, sx1, sy1, -mx, -my, -mx0, -my0, color0,
567
+ false);
568
+ } else if (joinStyle == LinePath.JOIN_ROUND) {
569
+ drawRoundJoin(sx0, sy0, -mx, -my, -mx0, -my0, 0, scolor0, true, false,
570
+ ROUND_JOIN_THRESHOLD);
571
+ }
596
572
  }
597
573
 
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;
574
+ emitLineTo(sx0 - mx, sy0 - my, scolor0);
575
+ emitLineTo(x0 - mx, y0 - my, color0);
576
+ for (int i = rindex - 3; i >= 0; i -= 3) {
577
+ emitLineTo(reverse[i], reverse[i + 1], reverse[i + 2]);
604
578
  }
605
579
 
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
- }
580
+ this.x0 = this.sx0;
581
+ this.y0 = this.sy0;
582
+ this.rindex = 0;
583
+ this.started = false;
584
+ this.joinSegment = false;
585
+ this.prev = LinePath.SEG_CLOSE;
586
+ emitClose();
587
+ }
588
+
589
+ public void end() {
590
+ if (lineToOrigin) {
591
+ // not closing the path, do the previous lineTo
592
+ lineToImpl(sx0, sy0, scolor0, joinToOrigin);
593
+ lineToOrigin = false;
594
+ }
624
595
 
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;
596
+ if (prev == LinePath.SEG_LINETO) {
597
+ finish();
598
+ }
629
599
 
630
- if (capStyle == LinePath.CAP_ROUND) {
631
- drawRoundJoin(sx0, sy0, -mx0, -my0, mx0, my0, 1, scolor0, false, false,
600
+ output.end();
601
+ this.joinSegment = false;
602
+ this.prev = LinePath.SEG_MOVETO;
603
+ }
604
+
605
+ long lineLength(long ldx, long ldy) {
606
+ long ldet = ((long) m00 * m11 - (long) m01 * m10) >> 16;
607
+ long la = (ldy * m00 - ldx * m10) / ldet;
608
+ long lb = (ldy * m01 - ldx * m11) / ldet;
609
+ long llen = (int) LinePath.hypot(la, lb);
610
+ return llen;
611
+ }
612
+
613
+ private void finish() {
614
+ if (capStyle == LinePath.CAP_ROUND) {
615
+ drawRoundJoin(x0, y0, omx, omy, -omx, -omy, 1, color0, false, false,
632
616
  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;
617
+ } else if (capStyle == LinePath.CAP_SQUARE) {
618
+ long ldx = px0 - x0;
619
+ long ldy = py0 - y0;
620
+ long llen = lineLength(ldx, ldy);
621
+ if (0 < llen) {
622
+ long s = (long) lineWidth2 * 65536 / llen;
623
+
624
+ int capx = x0 - (int) (ldx * s >> 16);
625
+ int capy = y0 - (int) (ldy * s >> 16);
626
+
627
+ emitLineTo(capx + omx, capy + omy, color0);
628
+ emitLineTo(capx - omx, capy - omy, color0);
629
+ }
650
630
  }
651
631
 
652
- private void emitMoveTo(int x0, int y0, int c0) {
653
- output.moveTo(x0, y0, c0);
632
+ for (int i = rindex - 3; i >= 0; i -= 3) {
633
+ emitLineTo(reverse[i], reverse[i + 1], reverse[i + 2]);
654
634
  }
635
+ this.rindex = 0;
655
636
 
656
- private void emitLineTo(int x1, int y1, int c1) {
657
- output.lineTo(x1, y1, c1);
637
+ if (capStyle == LinePath.CAP_ROUND) {
638
+ drawRoundJoin(sx0, sy0, -mx0, -my0, mx0, my0, 1, scolor0, false, false,
639
+ ROUND_JOIN_THRESHOLD);
640
+ } else if (capStyle == LinePath.CAP_SQUARE) {
641
+ long ldx = sx1 - sx0;
642
+ long ldy = sy1 - sy0;
643
+ long llen = lineLength(ldx, ldy);
644
+ if (0 < llen) {
645
+ long s = (long) lineWidth2 * 65536 / llen;
646
+
647
+ int capx = sx0 - (int) (ldx * s >> 16);
648
+ int capy = sy0 - (int) (ldy * s >> 16);
649
+
650
+ emitLineTo(capx - mx0, capy - my0, scolor0);
651
+ emitLineTo(capx + mx0, capy + my0, scolor0);
652
+ }
658
653
  }
659
654
 
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
- }
655
+ emitClose();
656
+ this.joinSegment = false;
657
+ }
658
+
659
+ private void emitMoveTo(int x0, int y0, int c0) {
660
+ output.moveTo(x0, y0, c0);
661
+ }
662
+
663
+ private void emitLineTo(int x1, int y1, int c1) {
664
+ output.lineTo(x1, y1, c1);
665
+ }
666
+
667
+ private void emitLineTo(int x1, int y1, int c1, boolean rev) {
668
+ if (rev) {
669
+ ensureCapacity(rindex + 3);
670
+ reverse[rindex++] = x1;
671
+ reverse[rindex++] = y1;
672
+ reverse[rindex++] = c1;
673
+ } else {
674
+ emitLineTo(x1, y1, c1);
669
675
  }
676
+ }
670
677
 
671
- private void emitClose() {
672
- output.close();
673
- }
678
+ private void emitClose() {
679
+ output.close();
680
+ }
674
681
  }