Determine largest font for given rectangle height (WinForms) - winforms

This is the inverse of Determine Label Size based upon amount of text and font size in Winforms/C#.
Given a rectangle of fixed height but variable width, is there an efficient way to determine the largest size of a given font that will fit in the rectangle (height-wise) without risk of losing ascenders/descenders?
I'm currently considering iterative use of MeasureString() to find the best font size but wonder if there's a better way.

I've never found a better way to do it than using MeasureString iteratively.
You can optimise by jumping in increments.
WPF has some nicer text sizing options, though it feels like rubbing salt in the wound.

You don't really need iterations. Since the total width is also proportional to the font size, you only have to measure the string once with any reasonable sized font.
Afterwards, you can calculate your required font size:
fontSizeUsedToMeasure*(RectangleWidth/MeasuredWidth)(*0.8 for a nicer fit)

Related

Draw text and make it fit inside a rectangle in GDI?

Is there's a function that can draw text and fit it inside a rectangle (the function will make the size of the text smaller as appropriate to make it fit or something).
I checked the parameters for DrawText() but I don't think it supports such a feature.
Maybe you can use GetTextMetrics to check if the text fits inside the rectangle, and if it doesn't, reduce the current font size and repeat the measurement.
GetTextMetrics:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd144941%28v=vs.85%29.aspx
There is no function doing it right away, but your can write your own using DrawText with DT_CALCRECT parameter. This parameter will only calculate size of your text and return it to you. It allows also multi line text and also checks provided maximal width you can allow text to be. So if the output rectangle - as calculated by DrawText is too large, then you must calculate it again but with smaller font, you can speed up calculations by using binary method to find the most appropriate font size.

Distribute text top-to-bottom instead of left-to-right

I'm working on a view that's implementing a multi-column text layout using CoreText (using CTFramesetter).
CoreText usually fills each frame completely, so when I call CTFramesetterCreateFrame with three rects that make up my columns, I get a layout that's similar to the following image:
So the left column is filled completely, the middle column partially and the right column is empty. But instead, I'd like the text to distribute over the three columns so that they take up the least vertical space possible, like in this image:
How to achieve this with CoreText?
I don't mind going low-level here, even drawing each CTRun by hand is an option if necessary.
One idea I came up with would be to create a large frame with the width of a column and then figure out which CTLine to draw in which column. But this has a few limitations:
It would only work if all columns had the same width.
It does not work with clipping paths.
Unfortunately, I'll need to use clipping paths (as in kCTFrameClippingPathsAttributeName) so this idea is out. I could live the fixed column width limitation, though.
Another idea would be to reduce the height until the last frame overflows but that's a pretty brute-force way that surely wastes resources.
(BTW, due to compability requirements the use of TextKit classes like NSTextStorage isn't possible; the resulting view is intended to be used on Mac and iOS, but it needs to work on iOS < 7)
Since there doesn't seem to be a non-expensive way to solve this, here's how I've done it:
I did go with the "reduce the height until the last frame overflows" approach. To reduce the height, I simply have another clipping path (kCTFrameClippingPathsAttributeName) which is a rectangle that fills the bottom of the view to the required height.
The probably most expensive but simple way would have been to increase the rectangle height until finally the text doesn't fit inside the last frame any more.
Instead I've implemented a binary search for that. For my demo app, I usually find the correct height after 8-10 recursions which still is expensive but at least it's pixel-perfect and doesn't rely on any other information other than "did the last frame overflow".

How to set the PREFERRED size of a WPF control

Is there a way to set the preferred size of a WPF control without setting its maximum size?
I normally set all of my WPF controls to have have automatic height and width, and I set the alignment to stretch. That works great in a lot of cases. My windows come up in a reasonable size by default. If the user stretches the window, the extra space will go where I think it should.
This broke when I set the width of a DataGridTextColumn to "*". Now suddenly the preferred size for my table is several times bigger than my screen! The initial size for my window is exactly the size of my screen.
Of course, I could set the MaxWidth of my table (or my column), but I don't want to do that. The max width was fine at infinity.
I tried changing the Width property to a fixed number of pixels. That seems to change the maximum width. Even though I set HorizontalContentAlignment="Stretch" in the table, the table is centered and the width does not change.
Is there a way around this? I like auto-sizes most of the time. And I like setting the width of a column to "*". Is there a way to make them work together?
It seems like there's a property somewhere that I can't find. At some point the container has to ask my table what size it wants to be. That answer might be ignored or adjusted, but the table had to answer that question. It seems like I should be able to change that value, without changing the max size. (And it seems like if I say "stretch" and there is extra space, my table should be stretched.)
Thank you.

Scale text in WPF

How can I automatically scale text inside a control based on the control's size but always make sure it's readable (that is, I want the font size stays between 9pt and 30pt)
The ViewBox can help with this, but I'm not sure about keeping the font size within a range. You can probably accomplish this roughly with MinHeight and MinWidth.
Try to use ScaleTransform.
In order to understand how to calculate the scale size you may refer to http://social.msdn.microsoft.com/forums/en-US/wpf/thread/d73c9eb2-9c68-428d-b99b-d23d0c62c095/

Resizing a button with higher values of Height and Width is less smooth than with lower values in WPF

I have a button which Max and Min height X width are 1024X1360 and 72X95 pixels. I am resizing this button by handling DragDelta events of Thumbs present in button's Template. The problem is the updation of height and width at lower levels, i.e upto 210X280, gives out a smooth operation which is not the case with greater sizes. Anybody out here has faced the issue? Any suggestion to improve the user experience in this situation.
The easiest fix here is to make the contents of your button less complex. In general, the more stuff there is to draw inside of it (i.e. larger size) the longer it is going to take to draw it. This can become even more problematic when you consider that hardware will play an (unpredictable) role in the performance as well.
So a couple of easy options: Mix and match for best results.
1. Make your button less complex.
2. Limit its maximum size. (To something smaller)
3. Accept the choppiness.

Resources