+ if (y1 > y2) { int t = x1; x1 = x2; x2 = t; t = y1; y1 = y2; y2 = t; }
+
+ if (x1 == x2) {
+ fillTrapezoid(x1 - w / 2, x2 + w / 2, y1 - (capped ? w / 2 : 0),
+ x1 - w / 2, x2 + w / 2, y2 + (capped ? w / 2 : 0), color);
+ return;
+ }
+
+ // fastpath for single-pixel width lines
+ if (w == 1) {
+ float slope = (float)(y2 - y1) / (float)(x2 - x1);
+ int last_x = x1;
+ for(int y=y1; y<=y2; y++) {
+ int new_x = (int)((float)(y - y1) / slope) + x1;
+ if (slope >= 0) fillTrapezoid(last_x + 1, y != y2 ? new_x + 1 : new_x, y,
+ last_x + 1, y != y2 ? new_x + 1 : new_x, y + 1, color);
+ else fillTrapezoid(y != y2 ? new_x : new_x + 1, last_x, y,
+ y != y2 ? new_x : new_x + 1, last_x, y + 1, color);
+ last_x = new_x;
+ }
+ return;
+ }
+
+ // actually half-width
+ float width = (float)w / 2;
+ float phi = (float)Math.atan((y2 - y1) / (x2 - x1));
+ if (phi < 0.0) phi += (float)Math.PI * 2;
+ float theta = (float)Math.PI / 2 - phi;
+
+ // dx and dy are the x and y distance between each endpoint and the corner of the stroke
+ int dx = (int)(width * Math.cos(theta));
+ int dy = (int)(width * Math.sin(theta));
+
+ // slice is the longest possible length of a horizontal line across the stroke
+ int slice = (int)(2 * width / Math.cos(theta));
+
+ if (capped) {
+ x1 -= width * Math.cos(phi);
+ x2 += width * Math.cos(phi);
+ y1 -= width * Math.sin(phi);
+ y2 += width * Math.sin(phi);
+ }
+
+ fillTrapezoid(x1 + dx, x1 + dx, y1 - dy, x1 - dx, x1 - dx + slice, y1 + dy, color); // top corner
+ fillTrapezoid(x2 + dx - slice, x2 + dx, y2 - dy, x2 - dx, x2 - dx, y2 + dy, color); // bottom corner
+ fillTrapezoid(x1 - dx, x1 - dx + slice, y1 + dy, x2 + dx - slice, x2 + dx, y2 - dy, color); // middle
+ }