diff --git a/dialog/testdata/color/dialog_expanded_theme_default.png b/dialog/testdata/color/dialog_expanded_theme_default.png index a317e3618c..e1b971b9d8 100644 Binary files a/dialog/testdata/color/dialog_expanded_theme_default.png and b/dialog/testdata/color/dialog_expanded_theme_default.png differ diff --git a/dialog/testdata/color/dialog_expanded_theme_ugly.png b/dialog/testdata/color/dialog_expanded_theme_ugly.png index 87b0a6b034..6aee51f17f 100644 Binary files a/dialog/testdata/color/dialog_expanded_theme_ugly.png and b/dialog/testdata/color/dialog_expanded_theme_ugly.png differ diff --git a/dialog/testdata/color/picker_layout_advanced.png b/dialog/testdata/color/picker_layout_advanced.png index 0e81a1e958..8fbf5a8223 100644 Binary files a/dialog/testdata/color/picker_layout_advanced.png and b/dialog/testdata/color/picker_layout_advanced.png differ diff --git a/dialog/testdata/color/wheel_layout.png b/dialog/testdata/color/wheel_layout.png index fefda5754a..161f04b60e 100644 Binary files a/dialog/testdata/color/wheel_layout.png and b/dialog/testdata/color/wheel_layout.png differ diff --git a/internal/painter/draw.go b/internal/painter/draw.go index 408182c422..3e84ffb5e4 100644 --- a/internal/painter/draw.go +++ b/internal/painter/draw.go @@ -47,6 +47,9 @@ func DrawLine(line *canvas.Line, vectorPad float32, scale func(float32) float32) width := int(scale(line.Size().Width + vectorPad*2)) height := int(scale(line.Size().Height + vectorPad*2)) stroke := scale(line.StrokeWidth) + if stroke < 1 { // software painter doesn't fade lines to compensate + stroke = 1 + } raw := image.NewRGBA(image.Rect(0, 0, width, height)) scanner := rasterx.NewScannerGV(int(line.Size().Width), int(line.Size().Height), raw, raw.Bounds()) @@ -56,6 +59,17 @@ func DrawLine(line *canvas.Line, vectorPad float32, scale func(float32) float32) p1x, p1y := scale(line.Position1.X-line.Position().X+vectorPad), scale(line.Position1.Y-line.Position().Y+vectorPad) p2x, p2y := scale(line.Position2.X-line.Position().X+vectorPad), scale(line.Position2.Y-line.Position().Y+vectorPad) + if stroke <= 1.5 { // adjust to support 1px + if p1x == p2x { + p1x -= 0.5 + p2x -= 0.5 + } + if p1y == p2y { + p1y -= 0.5 + p2y -= 0.5 + } + } + dasher.Start(rasterx.ToFixedP(float64(p1x), float64(p1y))) dasher.Line(rasterx.ToFixedP(float64(p2x), float64(p2y))) dasher.Stop(true) diff --git a/internal/painter/gl/draw.go b/internal/painter/gl/draw.go index 6a0dab95ed..6a4be0c7ad 100644 --- a/internal/painter/gl/draw.go +++ b/internal/painter/gl/draw.go @@ -113,6 +113,17 @@ func (p *glPainter) lineCoords(pos, pos1, pos2 fyne.Position, lineWidth, feather pos2.X = roundToPixel(pos2.X+xPosDiff, p.pixScale) pos2.Y = roundToPixel(pos2.Y+yPosDiff, p.pixScale) + if lineWidth <= 0.5 && p.pixScale > 1 { // adjust to support 1px drawing on HiDPI (width 0.5) + if pos1.X == pos2.X { + pos1.X -= 0.25 + pos2.X -= 0.25 + } + if pos1.Y == pos2.Y { + pos1.Y -= 0.25 + pos2.Y -= 0.25 + } + } + x1Pos := pos1.X / frame.Width x1 := -1 + x1Pos*2 y1Pos := pos1.Y / frame.Height @@ -131,7 +142,7 @@ func (p *glPainter) lineCoords(pos, pos1, pos2 fyne.Position, lineWidth, feather normalObjX := normalX * 0.5 * frame.Width normalObjY := normalY * 0.5 * frame.Height widthMultiplier := float32(math.Sqrt(float64(normalObjX*normalObjX + normalObjY*normalObjY))) - halfWidth := (lineWidth*0.5 + feather) / widthMultiplier + halfWidth := (roundToPixel(lineWidth+feather, p.pixScale) * 0.5) / widthMultiplier featherWidth := feather / widthMultiplier return []float32{ diff --git a/internal/painter/software/painter_test.go b/internal/painter/software/painter_test.go index c87f7a5aab..c442b9e433 100644 --- a/internal/painter/software/painter_test.go +++ b/internal/painter/software/painter_test.go @@ -222,6 +222,24 @@ func TestPainter_paintLine(t *testing.T) { test.AssertImageMatches(t, "draw_line.png", p.Paint(c)) } +func TestPainter_paintLine_thin(t *testing.T) { + c := test.NewCanvas() + lines := [5]*canvas.Line{} + sws := []float32{4, 2, 1, 0.5, 0.3} + for i, sw := range sws { + lines[i] = canvas.NewLine(color.RGBA{255, 0, 0, 255}) + lines[i].StrokeWidth = sw + x := float32(i * 20) + lines[i].Position1 = fyne.NewPos(x, 10) + lines[i].Position2 = fyne.NewPos(x+15, 10) + } + c.SetContent(container.NewWithoutLayout(lines[0], lines[1], lines[2], lines[3], lines[4])) + c.Resize(fyne.NewSize(109, 28)) + + p := software.NewPainter() + test.AssertImageMatches(t, "draw_line_thin.png", p.Paint(c)) +} + func TestPainter_paintRaster(t *testing.T) { img := canvas.NewRasterWithPixels(func(x, y, w, h int) color.Color { x = x / 5 diff --git a/internal/painter/software/testdata/draw_line_thin.png b/internal/painter/software/testdata/draw_line_thin.png new file mode 100644 index 0000000000..71d491bea6 Binary files /dev/null and b/internal/painter/software/testdata/draw_line_thin.png differ