It is currently April 16th, 2024, 9:10 pm

Dynamically change font size to fit text within skin

Get help with creating, editing & fixing problems with skins
User avatar
Yincognito
Rainmeter Sage
Posts: 7119
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Dynamically change font size to fit text within skin

Post by Yincognito »

I had a similar problem to yours, just the other way around: I needed the (dynamic sized) skin to adapt to a maximum text width and height. What I did (and this could be tweaked to your case as well) was to first draw the text used as a reference for the maximum width and height transparently (in order to get those dimensions), then set the actual (i.e. non-transparent) meters' W and H based on that - obviously the dynamic sized skin did automatically adapt too. This worked well, and I achieved my goal.

Bottom line, you have two options (at least):
1. Do as I did, but adapted to your needs - this isn't as complicated as it looks:
- draw your text transparently using a "standard" size
- use the meter's OnUpdateAction to update some (Calc) measure(s) with the text's dimensions (i.e. [MeterVotDText:W] and [MeterVotDText:H])
- test if the those need to be increased or decreased compared to the size of the skin, using some IfCondition in the (Calc) measure(s)
- use some bangs in the above IfCondition(s) to dynamically modify FontSize in the meter accordingly (e.g. increasing or decreasing by 1)
- repeat the above, but using the updated FontSize and meter dimensions, until you hit the right spot
- once you've done the above, make sure you "exit the loop" (generally, this would be when the text dimensions need to be modified in the opposite direction compared to before)
2. Use TransformationMatrix to "shrink" or "enlarge" the text meter. This will look to be easier to accomplish, but it has two disadvantages:
- the font will obviously look wider or narrower, taller or shorter than its "normal" ratio
- due to the particularities of TransformationMatrix, you need to be aware that the position of the text will also be altered, along with its dimensions, because the reference point when using this is always the (0,0) coordinates. But then, properly setting the TransformationMatrix parameters should correct this, just ask eclectic-tach or balala
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 7119
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Dynamically change font size to fit text within skin

Post by Yincognito »

Just in case that you didn't manage to do it by now (and for other folks who might be looking for a similar thing):

Code: Select all

[Rainmeter]
Update=1000
AccurateText=1

[Variables]
Width=400
Height=((#Width# / 16) * 9)
Adjusted=0
TSize=0
TText=This is a longer, most likely several lines longer, test. It should wrap across several lines and fill a lot of the background box even at smaller font sizes, but it should ultimately be resized to a font size that just fits the fixed area and it should never clip.

[MeasureVotDTextHeight]
Measure=Calc
UpdateDivider=-1
Formula=([MeterVotDText:H])
IfCondition=(([MeasureVotDTextHeight]<=#Height#) && (#Adjusted#=0))
IfTrueAction=[!SetVariable TSize (#TSize#+1)][!UpdateMeter "MeterVotDText"][!Redraw]
IfCondition2=(([MeasureVotDTextHeight]>#Height#) && (#Adjusted#=0))
IfTrueAction2=[!SetVariable Adjusted 1][!SetVariable TSize (#TSize#-1)][!SetOption MeterVotDText FontColor "255,255,255,255"][!UpdateMeter "MeterVotDText"][!Redraw]
IfConditionMode=1
DynamicVariables=1

[Background]
Meter=Image
SolidColor=00000033
W=#Width#
H=#Height#
DynamicVariables=1

[MeterVotDText]
Meter=String
Text=#TText#
AntiAlias=1
ClipString=2
X=[Background:X]
Y=[Background:Y]
W=#Width#
FontColor=255,255,255,0
FontSize=#TSize#
FontFace=Source Sans Pro
OnUpdateAction=[!UpdateMeasure "MeasureVotDTextHeight"]
DynamicVariables=1

; The options below modify this file. They are optional, just for demonstration purposes - they can be removed
MouseScrollDownAction=[!WriteKeyValue Variables Width (#Width#+1)][!Refresh]
MouseScrollUpAction=[!WriteKeyValue Variables Width (#Width#-1)][!Refresh]
This was done by following the steps at option 1 in my previous reply. The last two lines can be deleted - they are just for demonstration purposes (they increase or decrease the width of the background on mouse scrolling down and up, respectively, to show how the text and its size adapts to the new width).
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 7119
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Dynamically change font size to fit text within skin

Post by Yincognito »

simsrw73 wrote: February 26th, 2019, 2:05 am Wow! Thanks for that. I was going to attempt your proposed solution 1 above but hadn’t has time or been by my desktop to try it yet. The support on these forums is amazing, more than I deserve. I’ll give this a try when I’m back by my desktop and report back. Thank you!
You're welcome.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
balala
Rainmeter Sage
Posts: 16142
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Dynamically change font size to fit text within skin

Post by balala »

simsrw73 wrote: February 26th, 2019, 6:47 pm How can I change the flow so that the Meter referring to the text derived from the WebParser is resized after WebParser finishes evaluating its arguments?
I didn't carefully follow this topic, but this question has a simple answer: add a FinishAction option to the parent WebParser measure (in this case [MeasureVotDSite]). The bangs of this option, as its name says, are executed when the WebParser measure finishes parsing the information.
For example you can reduce the FontSize of the String meter, through a !SetOption bang.
User avatar
Yincognito
Rainmeter Sage
Posts: 7119
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Dynamically change font size to fit text within skin

Post by Yincognito »

balala wrote: February 26th, 2019, 7:20 pm I didn't carefully follow this topic, but this question has a simple answer: add a FinishAction option to the parent WebParser measure (in this case [MeasureVotDSite]). The bangs of this option, as its name says, are executed when the WebParser measure finishes parsing the information.
For example you can reduce the FontSize of the String meter, through a !SetOption bang.
Agreed. Thanks for helping out, by the way! :thumbup:
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
Yincognito
Rainmeter Sage
Posts: 7119
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Dynamically change font size to fit text within skin

Post by Yincognito »

Also, simsrw73, be sure to place the bang [!UpdateMeasure "MeasureVotDTextHeight"] (the one that triggers the whole process) not only in a FinishAction option in the WebParser measure, but also after the meter itself "received" the text and drawn itself (since the executed measure needs to know the text height to be able to work out properly, and that is obviously only found out after the text has been drawn).

Basically, I think the bang should be the last one you write in the FinishAction option. I'm not sure if a [!Redraw] will be needed to be sure the meter is drawn before executing the bang, but you can try it if you run into problems.


EDIT: Don't bother reading the above, as you apparently solved the whole thing. Well done! ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth