-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Add OpenGL (ES)/GPU rendered rectangle and rectangle with rounded edges #3539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking pretty good. Just a small more cleanup in my opinion. I will try to dedicate some time for testing on mobile and web later this week.
cmd/rect_test/main.go
Outdated
@@ -0,0 +1,79 @@ | |||
package main |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "Tests" checkbox is actually for a test that would pass via go test
, not a binary to manually check the result. Actually what is in this file should likely be included in fyne_demo/canvas section.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. This file would have to be removed (and then have fyne_demo updated instead) as we shouldn't add more applications into the cmd/ directory.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is still an open point. I haven't had time yet.
Next steps will be:
- Test implementation
- Extend fyne_demo
- Delete cmd/rect_test
In the meantime you can use the rect_test for web and mobile testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open points done.
internal/painter/gl/draw.go
Outdated
@@ -83,7 +82,11 @@ func (p *painter) drawObject(o fyne.CanvasObject, pos fyne.Position, frame fyne. | |||
case *canvas.Raster: | |||
p.drawRaster(obj, pos, frame) | |||
case *canvas.Rectangle: | |||
p.drawRectangle(obj, pos, frame) | |||
if o.(*canvas.Rectangle).Radius.Pixel == 0 && o.(*canvas.Rectangle).Radius.Percent == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
internal/painter/gl/draw.go
Outdated
@@ -231,6 +369,66 @@ func (p *painter) lineCoords(pos, pos1, pos2 fyne.Position, lineWidth, feather f | |||
}, halfWidth, featherWidth | |||
} | |||
|
|||
/* | |||
func (p *painter) flexLineCoordsNew(pos, pos1, pos2 fyne.Position, lineWidth, feather float32, frame fyne.Size) ([]float32, float32, float32) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We prefer to not have dead code. Would you mind removing this until it is of use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not used code deleted - done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like how this is shaping up - and agree with the other comments.
However I don't agree with the need for a Radius
type - and I certainly don't think we should use pixel definition in the middle of a vector toolkit.
geometry.go
Outdated
|
||
// RectangleRadius describes a radius in pixel or in percentage | ||
type Radius struct { | ||
Pixel float32 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is a good idea - the toolkit API is all vector and therefore pixel parameters should not be used.
Can we just use float32
instead of Radius
- the Width
and Height
are the same so that will be what developers are expecting. We also don't have percentage based calculations elsewhere so I don't think it's needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from @andydotxyz in #3121.
It may be worth noting that if Radius == Height/2 then the ends of the rectangle should be a semi-circle, but I don't think it is, so when adjusting the scaling calculations maybe check this too?
This statement was for me the wish to have a percentage alternative for radius.
How to solve this? The developer uses a container that changes the size depending on the windows' size. The included rectangle changes the size dynamically too.
- The rectangle should look always the same, eg. semi-circle
In this case it would even be necessary to define the StrokeWidth as percentage to get an identical looking rectangle.
If you don't like the struct it could be named:
Radius float32
RadiusRelation float32 //RadiusDynamic RadiusPercent
StrokeWidth float32
StrokeWidthRelation float32 // StrokeWidthDynamic StrokeWidthPercent
It could be possible to remove the percentage from the rectangle and to define a separate shape eg FlexRectagle
, DynamicRectagle
, where the Radius and SrokeWidth are always handled in percentage. This could be implemented later after this PR. I would prefer the solution with an own Shape-Type. It would be faster and would have less complexity.
Please let me know how to change the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you are putting to much smart into dumb canvas objects.
Something resizing the rectangle can set it's radius to be different if it is trying to maintain a specific shape.
Just like if someone wants a square - they have to ensure that the width and height match even if the container space is rectangular not square.
I don't think it's worth a more complicated API at this level to handle corner cases like that automatically. The canvasobjects are our primitive draw type - widgets using them are where the layout and render details are calculated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I will remove the percentage and the Radius will be Radius float32
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor Radius done.
I have created #3547 for this followup task. If that's good for you @Jacalz, we just need @andydotxyz review before we can merge this. |
Sounds good to me. The only thing is that I think the point from @andydotxyz, about the tests not testing anything, still stands though. If we can't test it without the software render support, I personally think we can just remove the tests here but let's hear what Andy has to say first :) |
Indeed there is a follow up task for the software renderer - but the markup renderer should be updated to understand this new field anyway. Not sure if we can use it in the test depending on circular imports |
What I meant was, should we keep the tests that were added in this PR? They only test that a field is set? |
Apologies, I meant to provide a little more detail but was afk: diff --git a/test/markup_renderer.go b/test/markup_renderer.go
index a47b706f..28e5901e 100644
--- a/test/markup_renderer.go
+++ b/test/markup_renderer.go
@@ -332,6 +332,7 @@ func (r *markupRenderer) writeRectangle(rct *canvas.Rectangle, attrs map[string]
r.setColorAttr(attrs, "fillColor", rct.FillColor)
r.setColorAttr(attrs, "strokeColor", rct.StrokeColor)
r.setFloatAttr(attrs, "strokeWidth", float64(rct.StrokeWidth))
+ r.setFloatAttr(attrs, "radius", float64(rct.Radius))
r.writeTag("rectangle", true, attrs)
}
I think that the tests there should be replaced by something that actually tests - such as: test.AssertObjectRendersToMarkup(t, "rounded_rect.xml", rect) That way we are checking the state passes through - whereas the current tests are literally just checking that a field retains its value. |
For example the test: func TestRectangle_Radius(t *testing.T) {
rect := &canvas.Rectangle{
FillColor: color.NRGBA{R: 255, G: 200, B: 0, A: 180},
StrokeColor: color.NRGBA{R: 255, G: 120, B: 0, A: 255},
StrokeWidth: 2.0,
Radius: 25}
rect.Resize(fyne.NewSize(50, 50))
test.AssertObjectRendersToMarkup(t, "rounded_rect.xml", rect)
} renders <canvas size="50x50">
<content>
<rectangle fillColor="rgba(255,200,0,180)" radius="25" size="50x50" strokeColor="rgba(255,120,0,255)" strokeWidth="2"/>
</content>
</canvas> |
Just to clarify, I too am very happy with what this PR is and it's working well - if we get texts fixed up I'll be happy to approve too. P.S. I know that many of the canvas objects are not very well tested - but mostly they were created before our test helpers! |
I added an example implementation of the software renderer to the issue @Bluebugs created in case anyone was curious / looking to add it. |
I will replace the new test funcs (I created) in canvas/rectangle_test.go with this test func. |
Go test fails but in testadata/failed/rounded_rect.xml is available? Radius is missing in XML. PS C:\_project\renlite\fyne> go test .\canvas\rectangle_test.go
--- FAIL: TestRectangle_Radius (0.00s)
test.go:115: Master not found at C:\_project\renlite\fyne\canvas\testdata\rounded_rect.xml. Markup written to C:\_project\renlite\fyne\canvas\testdata\failed\rounded_rect.xml might be used as master.
FAIL
FAIL command-line-arguments 0.426s
FAIL <canvas size="50x50">
<content>
<rectangle fillColor="rgba(255,200,0,180)" size="50x50" strokeColor="rgba(255,120,0,255)" strokeWidth="2"/>
</content>
</canvas> |
You need to copy the file from "testdata/failed" to "testdata" and commit it. But for the radius to be present you need to include my adjustment to the markup writer: |
@andydotxyz Thank you for the infos. Test is working now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing thanks!
Well done @renlite! 🙂 |
Thanks for the support by @Bluebugs and all the tests and good feedback by @andydotxyz @Jacalz @ErrorNoInternet. |
Description:
This PR replaces the PR #3121. The difference to this PR is the technique how the primitive OpenGL objects are rendered. In the PR #3121 the objects were mainly calculated on the CPU whereas in this PR the objects are primarily calculated on the GPU.
The new OpenGL rendering should bring better performance and the possibility to paint antialized rectangles with rounded edges. With this technology it's possible to paint a circle. In a second step the texture based circle could be switched too.
Thanks to: @Bluebugs for support and @andydotxyz @ErrorNoInternet @Jacalz for tests.
Fixes issue #1090
Checklist: