diff --git a/internal/painter/gl/draw.go b/internal/painter/gl/draw.go index 96e1e5bd7e..807c8f6b02 100644 --- a/internal/painter/gl/draw.go +++ b/internal/painter/gl/draw.go @@ -29,6 +29,64 @@ func (p *painter) defineVertexArray(prog Program, name string, size, stride, off func (p *painter) drawCircle(circle *canvas.Circle, pos fyne.Position, frame fyne.Size) { p.drawTextureWithDetails(circle, p.newGlCircleTexture, pos, circle.Size(), frame, canvas.ImageFillStretch, 1.0, paint.VectorPad(circle)) + + radius := circle.Size().Width / 2 + if circle.Size().Height < circle.Size().Width { + radius = circle.Size().Height / 2 + } + program := p.roundRectangleProgram + + // Vertex: BEG + bounds, points := p.vecSquareCoords(pos, circle, frame) + p.ctx.UseProgram(program) + vbo := p.createBuffer(points) + p.defineVertexArray(program, "vert", 2, 4, 0) + p.defineVertexArray(program, "normal", 2, 4, 2) + + p.ctx.BlendFunc(srcAlpha, oneMinusSrcAlpha) + p.logError() + // Vertex: END + + // Fragment: BEG + frameSizeUniform := p.ctx.GetUniformLocation(program, "frame_size") + frameWidthScaled, frameHeightScaled := p.scaleFrameSize(frame) + p.ctx.Uniform2f(frameSizeUniform, frameWidthScaled, frameHeightScaled) + + rectCoordsUniform := p.ctx.GetUniformLocation(program, "rect_coords") + x1Scaled, x2Scaled, y1Scaled, y2Scaled := p.scaleRectCoords(bounds[0], bounds[2], bounds[1], bounds[3]) + p.ctx.Uniform4f(rectCoordsUniform, x1Scaled, x2Scaled, y1Scaled, y2Scaled) + + strokeWidthScaled := roundToPixel(circle.StrokeWidth*p.pixScale, 1.0) + strokeUniform := p.ctx.GetUniformLocation(program, "stroke_width_half") + p.ctx.Uniform1f(strokeUniform, strokeWidthScaled*0.5) + + rectSizeUniform := p.ctx.GetUniformLocation(program, "rect_size_half") + rectSizeWidthScaled := x2Scaled - x1Scaled - strokeWidthScaled + rectSizeHeightScaled := y2Scaled - y1Scaled - strokeWidthScaled + p.ctx.Uniform2f(rectSizeUniform, rectSizeWidthScaled*0.5, rectSizeHeightScaled*0.5) + + radiusUniform := p.ctx.GetUniformLocation(program, "radius") + radiusScaled := roundToPixel(radius*p.pixScale, 1.0) + p.ctx.Uniform1f(radiusUniform, radiusScaled) + + var r, g, b, a float32 + fillColorUniform := p.ctx.GetUniformLocation(program, "fill_color") + r, g, b, a = getFragmentColor(circle.FillColor) + p.ctx.Uniform4f(fillColorUniform, r, g, b, a) + + strokeColorUniform := p.ctx.GetUniformLocation(program, "stroke_color") + strokeColor := circle.StrokeColor + if strokeColor == nil { + strokeColor = color.Transparent + } + r, g, b, a = getFragmentColor(strokeColor) + p.ctx.Uniform4f(strokeColorUniform, r, g, b, a) + p.logError() + // Fragment: END + + p.ctx.DrawArrays(triangleStrip, 0, 4) + p.logError() + p.freeBuffer(vbo) } func (p *painter) drawGradient(o fyne.CanvasObject, texCreator func(fyne.CanvasObject) Texture, pos fyne.Position, frame fyne.Size) { @@ -338,15 +396,19 @@ func rectInnerCoords(size fyne.Size, pos fyne.Position, fill canvas.ImageFill, a } func (p *painter) vecRectCoords(pos fyne.Position, rect *canvas.Rectangle, frame fyne.Size) ([4]float32, []float32) { + return p.vecRectCoordsWithPad(pos, rect, frame, 0, 0) +} + +func (p *painter) vecRectCoordsWithPad(pos fyne.Position, rect fyne.CanvasObject, frame fyne.Size, xPad, yPad float32) ([4]float32, []float32) { size := rect.Size() pos1 := rect.Position() - xPosDiff := pos.X - pos1.X - yPosDiff := pos.Y - pos1.Y + xPosDiff := pos.X - pos1.X + xPad + yPosDiff := pos.Y - pos1.Y + yPad pos1.X = roundToPixel(pos1.X+xPosDiff, p.pixScale) pos1.Y = roundToPixel(pos1.Y+yPosDiff, p.pixScale) - size.Width = roundToPixel(size.Width, p.pixScale) - size.Height = roundToPixel(size.Height, p.pixScale) + size.Width = roundToPixel(size.Width-2*xPad, p.pixScale) + size.Height = roundToPixel(size.Height-2*yPad, p.pixScale) x1Pos := pos1.X x1Norm := -1 + x1Pos*2/frame.Width @@ -367,6 +429,17 @@ func (p *painter) vecRectCoords(pos fyne.Position, rect *canvas.Rectangle, frame return [4]float32{x1Pos, y1Pos, x2Pos, y2Pos}, coords } +func (p *painter) vecSquareCoords(pos fyne.Position, rect fyne.CanvasObject, frame fyne.Size) ([4]float32, []float32) { + xPad, yPad := float32(0), float32(0) + if rect.Size().Width > rect.Size().Height { + xPad = (rect.Size().Width - rect.Size().Height) / 2 + } else { + yPad = (rect.Size().Height - rect.Size().Width) / 2 + } + + return p.vecRectCoordsWithPad(pos, rect, frame, xPad, yPad) +} + func roundToPixel(v float32, pixScale float32) float32 { if pixScale == 1.0 { return float32(math.Round(float64(v)))