Hello everybody,
A few days ago when I wanted to draw a mouth with Shape meters, I faced a problem which I couldn't figure out how to fix. So I came and posted a question into the Help: Rainmeter Skins section. Finally got two smart solutions, one from ikarus1969 and another from Yincognito. There might be a bug, at least this is our opinion, however I'm not sure. Devs should take a look I suppose and tell what's going on.
So I did draw a mouth with Path. But got a line which in my opinion (and others as well) should not be there. Here is the description of the problem: https://forum.rainmeter.net/viewtopic.php?f=5&t=37644#p191410
Am I missing something or there indeed is a little inadvertence?
As usually, thank for the help.
It is currently March 29th, 2024, 7:37 am
Shape meter Path problem
-
- Rainmeter Sage
- Posts: 16110
- Joined: October 11th, 2010, 6:27 pm
- Location: Gheorgheni, Romania
-
- Developer
- Posts: 2674
- Joined: November 24th, 2011, 1:42 am
- Location: Utah
Re: Shape meter Path problem
This is caused by the "miter" corner limit of joined stroke lines. Different types of joined lines can fix this, or just using a "limit" of 0.
https://docs.rainmeter.net/manual-beta/meters/shape/#StrokeLineJoin
Here is some examples:
"Miter" limit is 0:
Using a different line join: (you can use "Bevel" as well)
You can also "force" a round line join within the path:
-Brian
https://docs.rainmeter.net/manual-beta/meters/shape/#StrokeLineJoin
Here is some examples:
"Miter" limit is 0:
Code: Select all
[Rainmeter]
Update=-1
BackgroundMode=2
SolidColor=220,220,220
SkinWidth=140
SkinHeight=200
[MeterMouth1]
Meter=Shape
X=0
Y=0
Shape=Path MyPath | StrokeWidth 2 | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Miter,0
MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
Code: Select all
[Rainmeter]
Update=-1
BackgroundMode=2
SolidColor=220,220,220
SkinWidth=140
SkinHeight=200
[MeterMouth1]
Meter=Shape
X=0
Y=0
Shape=Path MyPath | StrokeWidth 2 | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Round
MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
Code: Select all
[Rainmeter]
Update=-1
BackgroundMode=2
SolidColor=220,220,220
SkinWidth=140
SkinHeight=200
[MeterMouth1]
Meter=Shape
X=0
Y=0
Shape=Path MyPath | StrokeWidth 2 | Stroke Color 0,0,0 | Fill Color 255,255,255
MyPath=10,65 | SetRoundJoin 1 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
-
- Rainmeter Sage
- Posts: 16110
- Joined: October 11th, 2010, 6:27 pm
- Location: Gheorgheni, Romania
Re: Shape meter Path problem
Ok, thanks for the details. This in fact is the same as what ikarus1969 has proposed, so this will I use.Brian wrote: ↑June 9th, 2021, 12:56 pm This is caused by the "miter" corner limit of joined stroke lines. Different types of joined lines can fix this, or just using a "limit" of 0.
https://docs.rainmeter.net/manual-beta/meters/shape/#StrokeLineJoin
Here is some examples:
"Miter" limit is 0:Using a different line join: (you can use "Bevel" as well)Code: Select all
[Rainmeter] Update=-1 BackgroundMode=2 SolidColor=220,220,220 SkinWidth=140 SkinHeight=200 [MeterMouth1] Meter=Shape X=0 Y=0 Shape=Path MyPath | StrokeWidth 2 | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Miter,0 MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
You can also "force" a round line join within the path:Code: Select all
[Rainmeter] Update=-1 BackgroundMode=2 SolidColor=220,220,220 SkinWidth=140 SkinHeight=200 [MeterMouth1] Meter=Shape X=0 Y=0 Shape=Path MyPath | StrokeWidth 2 | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Round MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
-BrianCode: Select all
[Rainmeter] Update=-1 BackgroundMode=2 SolidColor=220,220,220 SkinWidth=140 SkinHeight=200 [MeterMouth1] Meter=Shape X=0 Y=0 Shape=Path MyPath | StrokeWidth 2 | Stroke Color 0,0,0 | Fill Color 255,255,255 MyPath=10,65 | SetRoundJoin 1 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
Thanks again.
-
- Rainmeter Sage
- Posts: 7029
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Shape meter Path problem
EDIT: Disregard the below, closing the paths makes all workarounds (bar my first one) work. The open path was present ever since the initial version of the OP's code.
Sorry, Brian, this is not going to cut it - the issue is not fixed, it's just a workaround that partially alleviates the problem. All workarounds STILL produce artefacts in terms of symmetry, for higher stroke widths (thus, the bug exists, and is NOT fixed). These are the workarounds that have been proposed so far by me, ikarus1969 and you (I drew a line to better see the obvious - scroll to change the stroke width; only the last attempt / meter that I talked about here - check the bold parts - fixes the symmetry issue completely):
Code: Select all
[Variables]
StrokeWidth=10
[Rainmeter]
Update=-1
DynamicWindowSize=1
AccurateText=1
[Background]
Meter=Image
W=1000
H=200
SolidColor=220,220,220
MouseScrollUpAction=[!SetVariable StrokeWidth (#StrokeWidth#+1)][!UpdateMeter *][!Redraw]
MouseScrollDownAction=[!SetVariable StrokeWidth (#StrokeWidth#-1)][!UpdateMeter *][!Redraw]
DynamicVariables=1
[MeterMouth_Yincognito]
Meter=Shape
X=0
Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255
MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | LineTo 130,65 | ArcTo 10,65,60,80,0,0,0
DynamicVariables=1
[MeterMouth_ikarus1969]
Meter=Shape
X=10R
Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Round
MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
DynamicVariables=1
[MeterMouth_Brian_Miter]
Meter=Shape
X=10R
Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Miter,0
MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
DynamicVariables=1
[MeterMouth_Brian_Bevel]
Meter=Shape
X=10R
Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Round
MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
DynamicVariables=1
[MeterMouth_Brian_Round]
Meter=Shape
X=10R
Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255
MyPath=10,65 | SetRoundJoin 1 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0
DynamicVariables=1
[MeterMouth_Yincognito_TrueFix]
Meter=Shape
X=10R
Shape=Ellipse 70,65,60,80 | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Round
Shape2=Ellipse 70,0,100,85
Shape3=Combine Shape | Exclude Shape2
DynamicVariables=1
[Line]
Meter=Shape
Shape=Line 0,65,1000,65 | StrokeWidth 1 | Stroke Color 255,0,0,255
DynamicVariables=1
You do not have the required permissions to view the files attached to this post.
Last edited by Yincognito on June 9th, 2021, 4:13 pm, edited 1 time in total.
-
- Rainmeter Sage
- Posts: 1399
- Joined: April 24th, 2021, 8:13 pm
Re: Shape meter Path problem
You forgot to close the path with ClosePath 1Yincognito wrote: ↑June 9th, 2021, 3:35 pm Sorry, Brian, this is not going to cut it - the issue is not fixed, it's just a workaround that partially alleviates the problem. All workarounds STILL produce artefacts in terms of symmetry, for higher stroke widths (thus, the bug exists, and is NOT fixed). These are the workarounds that have been proposed so far by me, ikarus1969 and you (I drew a line to better see the obvious - scroll to change the stroke width; only the last attempt / meter that I talked about here - check the bold parts - fixes the symmetry issue completely):Comparison.jpgCode: Select all
[Variables] StrokeWidth=10 [Rainmeter] Update=-1 DynamicWindowSize=1 AccurateText=1 [Background] Meter=Image W=1000 H=200 SolidColor=220,220,220 MouseScrollUpAction=[!SetVariable StrokeWidth (#StrokeWidth#+1)][!UpdateMeter *][!Redraw] MouseScrollDownAction=[!SetVariable StrokeWidth (#StrokeWidth#-1)][!UpdateMeter *][!Redraw] DynamicVariables=1 [MeterMouth_Yincognito] Meter=Shape X=0 Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | LineTo 130,65 | ArcTo 10,65,60,80,0,0,0 DynamicVariables=1 [MeterMouth_ikarus1969] Meter=Shape X=10R Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Round MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0 DynamicVariables=1 [MeterMouth_Brian_Miter] Meter=Shape X=10R Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Miter,0 MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0 DynamicVariables=1 [MeterMouth_Brian_Bevel] Meter=Shape X=10R Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Round MyPath=10,65 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0 DynamicVariables=1 [MeterMouth_Brian_Round] Meter=Shape X=10R Shape=Path MyPath | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 MyPath=10,65 | SetRoundJoin 1 | ArcTo 130,65,60,20,0,1,0 | ArcTo 10,65,60,80,1,0,0 DynamicVariables=1 [MeterMouth_Yincognito_TrueFix] Meter=Shape X=10R Shape=Ellipse 70,65,60,80 | StrokeWidth #StrokeWidth# | Stroke Color 0,0,0 | Fill Color 255,255,255 | StrokeLineJoin Round Shape2=Ellipse 70,0,100,85 Shape3=Combine Shape | Exclude Shape2 DynamicVariables=1 [Line] Meter=Shape Shape=Line 0,65,1000,65 | StrokeWidth 1 | Stroke Color 255,0,0,255 DynamicVariables=1
from the Realm of Death
-
- Rainmeter Sage
- Posts: 7029
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Shape meter Path problem
Damn, you're right - now it's all good, only my 1st workaround fails. I take back what I said earlier. That being said, the open path was not my mistake (I actually always look to close paths in my codes) - it was present in the original code and somehow propagated even to Brian's examples...
You do not have the required permissions to view the files attached to this post.
-
- Developer
- Posts: 2674
- Joined: November 24th, 2011, 1:42 am
- Location: Utah
Re: Shape meter Path problem
Another thing to keep in mind is that the Shape meter uses DIP's, or "device independent pixels", rather than exact integer pixel coordinates. Well technically all of D2D uses DIP's, but in Rainmeter, the Shape meter is the only meter that allows the use of fractional DIP's within the meter definition itself.
https://docs.rainmeter.net/manual/meters/shape/#DeviceIndependentPixels
What this means is complex shapes (like the ones using arcs and curves) might not intersect the exact coordinate defined by the Shape. There might be 0.000000001 or more difference to where the line is actually drawn. Most of the time D2D figures it out without help, but in this particular case, changing the miter cornering limit was the key (or just changing the type of line join).
Here is some more information on these stroke properties:
https://docs.microsoft.com/en-us/windows/win32/api/d2d1/ns-d2d1-d2d1_stroke_style_properties - specifically the "miterLimit" parameter.
https://docs.microsoft.com/en-us/windows/win32/api/d2d1/ne-d2d1-d2d1_line_join#remarks
https://docs.microsoft.com/en-us/windows/win32/api/d2d1/nf-d2d1-id2d1strokestyle-getmiterlimit#return-value - specifically the "return" value portion. This is the best description of the miter limit I could find in the official MS docs.
Note: I had a mistake in my example of using a miter limit of 0. The minimum is 1.0. Rainmeter accepts anything over 0, but D2D obviously treats anything between 0 and 1 as 1.
It is also worth noting the using ClosePath 1 changes things as well. Obviously, this closes the path by drawing a line from the last position to the first position, but it also still follows the line joining rules. Hence the sharp corners. Honestly, with a small stroke width, a round line join is probably best to avoid these issues.
I left out the ClosePath 1 option since it wasn't used in the post I was looking at, although I should have read a bit more closely at the other posts. To be honest with you, ClosePath 1 should probably be used every time there is a fill on the shape.
-Brian
https://docs.rainmeter.net/manual/meters/shape/#DeviceIndependentPixels
What this means is complex shapes (like the ones using arcs and curves) might not intersect the exact coordinate defined by the Shape. There might be 0.000000001 or more difference to where the line is actually drawn. Most of the time D2D figures it out without help, but in this particular case, changing the miter cornering limit was the key (or just changing the type of line join).
Here is some more information on these stroke properties:
https://docs.microsoft.com/en-us/windows/win32/api/d2d1/ns-d2d1-d2d1_stroke_style_properties - specifically the "miterLimit" parameter.
https://docs.microsoft.com/en-us/windows/win32/api/d2d1/ne-d2d1-d2d1_line_join#remarks
https://docs.microsoft.com/en-us/windows/win32/api/d2d1/nf-d2d1-id2d1strokestyle-getmiterlimit#return-value - specifically the "return" value portion. This is the best description of the miter limit I could find in the official MS docs.
Note: I had a mistake in my example of using a miter limit of 0. The minimum is 1.0. Rainmeter accepts anything over 0, but D2D obviously treats anything between 0 and 1 as 1.
It is also worth noting the using ClosePath 1 changes things as well. Obviously, this closes the path by drawing a line from the last position to the first position, but it also still follows the line joining rules. Hence the sharp corners. Honestly, with a small stroke width, a round line join is probably best to avoid these issues.
I left out the ClosePath 1 option since it wasn't used in the post I was looking at, although I should have read a bit more closely at the other posts. To be honest with you, ClosePath 1 should probably be used every time there is a fill on the shape.
-Brian
-
- Rainmeter Sage
- Posts: 7029
- Joined: February 27th, 2015, 2:38 pm
- Location: Terra Yincognita
Re: Shape meter Path problem
Yeah, that was the thing I alluded to in my final workaround post as well, albeit not in such a technical and professional way as you did.
Indeed - I surely do, usually. Can't believe I missed it when later working with the code - I guess I was thinking that balala posted the issue and I wouldn't have to double check everything. Fortunately, death.crafter's cool head helped in noticing the missing piece here. All in all, it's both the miter / bevel / round join parameters AND closing the path that fully fix the issue. In the end, it wasn't an actual issue or a bug, but rather some little known detail regarding shape intersections - maybe a small note in the manual about it would be useful.