void (final @NotNull Graphics2D g, double x1, double y1, double x2, double y2, @NotNull StrokeType strokeType, double strokeWidth, @NotNull Object valueAA) { boolean horizontal = y1 == y2; boolean vertical = x1 == x2; boolean straight = horizontal || vertical; boolean centered = strokeType == StrokeType.CENTERED || strokeType == StrokeType.CENTERED_CAPS_SQUARE; boolean thickStroke = PaintUtil.devValue(strokeWidth, g) > 1; if (g.getStroke() instanceof BasicStroke && (straight || thickStroke)) { double sw = PaintUtil.alignToInt(strokeWidth, g); boolean dot = horizontal && vertical; if (dot) y2 += strokeWidth - 1; // draw a dot as [strokeWidth x strokeWidth] vertical line double angle = dot ? 0 : Math.atan2(y1 - y2, x2 - x1); // invert the sign of Y-axis, directing it bottom to top double sin = dot ? 1 : Math.sin(angle); double cos = dot ? 0 : Math.cos(angle); if (straight && !dot) { sin = Math.abs(sin); cos = Math.abs(cos); } // caps offsets double capy_1 = 0; double capy_2 = 0; double capx_1 = 0; double capx_2 = 0; if (strokeType == StrokeType.CENTERED_CAPS_SQUARE) { // the caps repeat the stroke split logic double[] strokeSplit = getStrokeSplit(ScaleContext.create(g), strokeType, sw, false); double cap_1 = strokeSplit[0]; double cap_2 = strokeSplit[1]; double y_sign = straight ? 1 : -1; // cap_1 >= cap_2 for x1/y1 < x2/y2, otherwise swap for diagonal line capx_1 = (straight || x1 <= x2 ? cap_1 : cap_2) * cos; capx_2 = (straight || x1 <= x2 ? cap_2 : cap_1) * cos; capy_1 = (straight || y1 <= y2 ? cap_1 : cap_2) * sin * y_sign; capy_2 = (straight || y1 <= y2 ? cap_2 : cap_1) * sin * y_sign; } // below x/y are aligned to int dev pixels to conform to RectanglePainter2D edges painting if (vertical/*|| dot*/) { double y_min = Math.min(y1, y2); double y_max = Math.max(y1, y2); y1 = PaintUtil.alignToInt(y_min, g); y2 = y1 + y_max - y1 + 1; x1 = x2 = PaintUtil.alignToInt(x2, g); } else if (horizontal) { double x_min = Math.min(x1, x2); double x_max = Math.max(x1, x2); x1 = PaintUtil.alignToInt(x_min, g); x2 = x1 + x_max - x1 + 1; y1 = y2 = PaintUtil.alignToInt(y2, g); } else { x1 = PaintUtil.alignToInt(x1, g); x2 = PaintUtil.alignToInt(x2, g); y1 = PaintUtil.alignToInt(y1, g); y2 = PaintUtil.alignToInt(y2, g); if (Math.abs(angle) > Math.PI / 2) { sin *= -1; cos *= -1; } } // stroke offsets double swx_2 = 0; double swx_1 = 0; double swy_2 = 0; double swy_1 = 0; if (strokeType == StrokeType.OUTSIDE) { swx_1 = sw * sin; swy_1 = sw * cos; } else if (strokeType == StrokeType.INSIDE) { swx_2 = sw * sin; swy_2 = sw * cos; } else if (centered) { double sw_1; double sw_2; if (straight) { // stroke is painted around the center of the line pixel (or within the line pixel, when the stroke is smaller) double[] strokeSplit = getStrokeSplit(ScaleContext.create(g), strokeType, sw); sw_1 = strokeSplit[0]; sw_2 = strokeSplit[1]; } else { // stroke is painted around the line sw_1 = PaintUtil.alignToInt(Math.max(sw / 2, 0), g); sw_2 = Math.max(sw - sw_1, 0); } swx_1 = sw_1 * sin; swx_2 = sw_2 * sin; swy_1 = sw_1 * cos; swy_2 = sw_2 * cos; } final Path2D path = new Path2D.Double(Path2D.WIND_EVEN_ODD); path.moveTo(x1 - swx_1 - capx_1, y1 - swy_1 - capy_1); path.lineTo(x2 - swx_1 + capx_2, y2 - swy_1 + capy_2); path.lineTo(x2 + swx_2 + capx_2, y2 + swy_2 + capy_2); path.lineTo(x1 + swx_2 - capx_1, y1 + swy_2 - capy_1); path.closePath(); PaintUtil.paintWithAA(g, valueAA, () -> g.fill(path)); } else { final Line2D line = new Line2D.Double(x1, y1, x2, y2); PaintUtil.paintWithAA(g, valueAA, () -> g.draw(line)); } }