Auto Scale text to fit the screen in mono - c#

I'm trying to scale a given text, e.g "123\nV.1-4", to fit the screen in mono.
I tried increasing the font size till the screen is not bigger.
My main problem is that I cannot retrieve the size of the label with a new font quickly?
(I'm retrieving with label.GetSizeRequest(out width, out height);)
So any solutions on how to scale the font/text?
Thanks

When the label is resized as you change the font size, the SizeRequest and SizeAllocated events will fire. What you could do is set the font size, then in the SizeAllocated event for the label, set the font size again. You will clearly have to stop the loop at some point, I assume you would cease increasing the font size when your label dimensions outstrip those of the window or screen etc.
However, have you considering using Pango and a drawing area instead?

Related

C# - How to maximise the font size of a label that can wrap inside a container?

Say you have a label. This label sits inside a container, lets say a TableLayoutPanel for argument. You dont always know the amount of text that the label will hold. It can be a few words or it can be a whole paragraph. You cant resize the TableLayoutPanel cell because its already at the perfect size.
You need a Big Font size for few words but a smaller Font size for larger pieces of text.
One problem though, the text can wrap.
How would one find the largest font size that would make the text fit snugly in the provided container?
I had to deactivate the text wrapping for starters.
I then got the size of the container in pixels. With that, i have the bounding box the font must fit in.
I then got the label size.
If the label is biger than the container, i incrementally made the font smaller.
If the label is smaller than the container, i incrementally made the font bigger.
I did this until the label fit inside the container. One issue though, the label can get very small if there are lots of text.
It took ages but I managed to figure out an elegant solution (kinda) and I wanted to share my "discoveries"
For starters, I re-enabled wrapping via the AutoSize (property this is important).
Then I got the height of the container, the width is no longer important.
I set the Anchor property to Top | Left | Right, meaning that the label will sit at the top and flow downwards.
Then I made the font size waaaaay too big for the text provided - it must overflow and hide text.
A sneaky quirk of this arrangement is that the label will overflow to outside the container but the overflowed text won't be visible. The size of the label will be exactly the height of the container, despite overflowing and having text missing. This same height can be used to our advantage.
If you then make the text smaller bit by bit, there will come to a point where the label height will no longer match its original height and get smaller. At that moment, you can stop because you have the perfect font size. The label will no longer overflow and the text will comfortably sit in the container.
Some code:
//get the height of the tabeLayoutPanel cell that serves as the container
float maxHeightClearance = tableLayoutPanelMain.RowStyles[4].Height;
//get the height of the label and save it for comparison later
float labelHeight = labelCourseName.Size.Height;
//for as long as the label height remains unchanged, it means that it is still too big
while(labelCourseName.Size.Height == labelHeight)
{
//slowly decrease the font size
labelCourseName.Font = new Font(labelCourseName.Font.Name, labelCourseName.Font.Size - 0.2f, labelCourseName.Font.Style, labelCourseName.Font.Unit);
//refresh the GUI to see if anything changed. This is nearly instantaneous
Application.DoEvents();
}

Trouble understanding render targets and back buffers in monogame

My graphics device is set up as follows:
GraphicsDeviceManager = new GraphicsDeviceManager(GameBase.GameRef);
GraphicsDeviceManager.PreferredBackBufferWidth = 640;
GraphicsDeviceManager.PreferredBackBufferHeight = 480;
GraphicsDeviceManager.ApplyChanges();
I can't find anywhere on google explaining exactly what the preferred back buffer width means.
I set up a render target like this:
RenderTarget = new RenderTarget2D(
GraphicsDeviceManager.GraphicsDevice,
640,
480,
false,
GraphicsDeviceManager.GraphicsDevice.PresentationParameters.BackBufferFormat,
DepthFormat.Depth24);
I can't find anything on google about what the 640 and 480 actually mean with respect to how the render target is drawn.
The problem I have is that if I resize the window, everything stretches. I'm trying to understand what monogame is doing to cause this, and then finally figure out a solution.
At the start my window is 640x480 and the PreferredBackBufferWidth and height are 640/480 and the render target is 640/480
If I resize the window to 1920x1080 for example, everything stretches, so somehow monogame no longer rendering the 640x480 texture onto a 640x480 part of the screen, but I haven't changed any of the values or done any code for this.
If I resize the screen, should the render target be destroyed and recreated at the new size of the window, or should the back buffer width and height be changed, or both, or something else?
I am very confused and there isn't any documentation online technical enough to answer in detail. Once I understand it I should be able to write some code so that when you resize the screen nothing happens, everything stay the same size, and there is a black area around the right/bottom edge because the window is larger than what i'm rendering to.
The back buffer is a special render target that is displayed on the screen. It is stretched to fill the window, which results in scaling if the window size does not match.
You can resize the back buffer when the window size changes. The Game.Window.ClientSizeChanged event is fired when that happens (note that it may be fired multiple times if the user is resizing the window by dragging). Then resizing the back buffer is simply
GraphicsDeviceManager.PreferredBackBufferWidth = Window.ClientBounds.Width;
GraphicsDeviceManager.PreferredBackBufferHeight = Window.ClientBounds.Height;
GraphicsDeviceManager.ApplyChanges();
Whether you should recreate the RenderTarget depends on what you're using it for.

Change Label Font Size Dynamically Not Updating On Screen

Am trying to change a label font size depending on screen resolution. Have tried when the form is loading, shown and also in the form constructor, but on screen the font size is the same as design time.
Rectangle resolution = Screen.PrimaryScreen.Bounds;
if (resolution.Width == 1024 && resolution.Height == 768)
{
this.labelEnterRegistration.Font = new Font(this.labelEnterRegistration.Font.FontFamily, 40f);
}
I've added a double click event to the label to check the font size, and it says it's 40 in a message box (MessageBox.Show(this.labelEnterRegistration.Font.ToString());), so why doesn't the form display reflect this?
I have tried the label Invalidate()but that didn't work either.
Have fixed it. As it was done before it was setting the fonts emSize, I did the following so it changes the pixel size:
FontStyle style = this.labelEnterRegistration.Font.Style;
this.labelEnterRegistration.Font = new Font(this.labelEnterRegistration.Font.FontFamily, 40f, style, GraphicsUnit.Pixe
And now keeps the same font style as well!!
Thanks for the comments #HEPÄ°MÄ°ZYARBAYMEHMETALKANIZ, made me think about it some more.

When building to mobile the size of fonts reduce and became very small

Like I said in the title when i built to mobile the letter became too small. I think it is because phone has more pixel for his little screen.
Well I tried to fix text by simply making text to images in photoshop. But how can I make InputFields text (not the placeholder).
At a guess, your Canvas' CanvasScaler's UI Scale Mode is probably set to Constant Pixel Size, and if your mobile device's resolution is too high, text will appear small.
Try changing the UI Scale Mode to Scale With Screen Size and change the properties it provides as needed.
(if your Canvas doesn't have a CanvasScaler component, click the Add Component button and add it)

How to Adjust the Text Size according to image size while Drawing String on an Image in C#

I'm using the Drawstring method of the Graphics Class to Draw a Text on an Image.The Font is Specified before drawing.
G.DrawString(mytext, font, brush, 0, 0)
The Problem arises when the same text is drawn on an image with smaller size.The Text drawn appears to be larger.I'm looking for a solution to alter the font size according to the image size so that the text don't appear larger or smaller when drawn on images of different sizes.
I'm attaching the images with different sizes with the text of same font size drawn on it.
http://i.stack.imgur.com/ZShUI.jpg
http://i.stack.imgur.com/GUfbM.jpg
I can't directly post the image because I'm not allowed.
You would get most precise scaling by drawing on separate image and then slapping that image onto original one. You'd do that as follows:
Create in-memory Bitmap with enough space
Draw text on that bitmap in your default font
Draw image containing the text onto original image by scaling it to size you need
Code:
Bitmap textBmp = new Bitmap(100, 100);
Graphics textBmpG = Graphics.FromImage(textBmp);
textBmpG .DrawString("test 1", new Font(FontFamily.GenericSansSerif, 16), Brushes.Red, new PointF(0, 0));
Graphics origImgG = Graphics.FromImage(originalImg);
origImgG.DrawImage(textBmpG, new Rectangle(50, 50, 50, 50), new Rectangle(0, 0, 100, 100), GraphicsUnit.Pixel);
Take notice of last line and Rectangle parameters. Use them to scale your text bitmap onto original image. Alternatively, you can also choose Graphics.MeasureString method to determine how wide your text would be and make attempts until you get best one you can.
Use Graphics.MeasureString() to measure how big your string would be on the image
Decrease/increase font step by step accordingly
As you requested in comment I'll give you more detailed suggestion here. Say your original image width is WI1, and width of text on it using Graphics.MeasureString is WT1. If you resize your image to width WI2, then your perfect text width would be WT2 = WT1 * WI2 / WI1. Using DrawText method you may not be able to get this exact width because when you increase font by 1 it may jump over that value. So you have to make several attempts and find best. Pick a size of font, if resulting text width is smaller (measure with MeasureString), increase it until it becomes bigger than target and you've got about closest match. Same thing goes if it's too big. Decrease font step by step.
This is quick and dirty as you see, because you have many draws, but I can't think of better solution, unless you're using monospaced fonts.
Difference between those solutions would be that in first you can get text to fit EXACT size you need, but you probably would loose some font readability due to scaling. Second solution would give good readability, but you can't get pixel perfect size of text.
In my opinion you have two ways:
Draw text on original image and then resize resulting image (so, even text included in it)
Scale font size by a factor newImageWidth/originalImageWidth.
It's not perfect because you could have some problem with text height (if new image is not just scaled but with different aspect ratio), but it's an idea

Categories