Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: WPF font drawing
I have a drawingcontrol based on a canvas.
The user is able to draw a rectangle by pressing the mouse button on the topleft position and dragging the mouse to the bottom right position. If the user lets go of the mouse button, the rectangle is drawn on the exact position that the user performed that action.
Now I need to draw text on this drawing control too, and it is the same procedure, the idea is that when the user lets go of the mouse the rectangle is filled in with the tekst "label", and that it exactly fills the surrounding rectangle. If I change the tekst to say "Lgl" the formatting should be reapplied because most likely the 'g' has a negative bottom bearing. How can I make this happen ? (Not the reformatting event, that is happening ok, but the fitting in the surrounding rectangle itself)
If I say the fontsize is 50, the resulting size is most likely bigger.
I used following code to do some investigation already based on what I found on the net :
public class HeightFontSizeConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string text = (string)values[0];
            double desiredHeight = (double)values[1];
            FontFamily family = (FontFamily)values[2];
            FontStyle style = (FontStyle)values[3];
            FontWeight weight = (FontWeight)values[4];
            FontStretch stretch = FontStretches.Normal;
            if (desiredHeight == 0) return (double)0;
            Typeface face = new Typeface(family,style,weight,stretch);
            GlyphTypeface gtf;
            if (face.TryGetGlyphTypeface(out gtf))
            {
                for (int i = 0; i < text.Length; ++i)
                {
                    ushort index = gtf.CharacterToGlyphMap[text[i]];
                    double h = gtf.AdvanceHeights[index];
                    double b = gtf.BottomSideBearings[index];
                    double t = gtf.TopSideBearings[index];
                    double baseline = gtf.Baseline;
                    double height = gtf.Height;
                    Debug.WriteLine("in HeightFontSizeConverter {0} baseline={1} height={2} advh={3} bsb={4} tsb={5}",text[i], baseline, height, h, b,t);
                }
                return desiredHeight;
            }
            else return (double)0;
        }
The problem basically is that I don't seem to find the meaning of the parameters in GlyphTypeface. I am not interested in left side bearing and right side bearing, I have the feeling it has to do with top side bearing and bottom side bearing but where do they start exactly.
I don't want any space above the tekst and I do not want any space below the tekst, it should fit the rectangle exactly.
Posted 15-Sep-12 2:00am
Edited 15-Sep-12 2:04am
v2
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

Just a quick off-the-cuff idea, but have you tried just wrapping a TextBlock inside a ViewBox? I don't have access to VS at the moment to try, but I imagine that would scale it automatically for you with essentially no special code.
 
Apologies if I've missed something.
  Permalink  
Comments
Philip Stuyck at 15-Sep-12 7:55am
   
If I try this :
<viewbox height="100">
<textblock padding="0,0,0,0" removed="Green" fontsize="1" text="HhglW"></textblock>
</viewbox>
You'll see that with the default font even there is no space at the bottom, that is what I want , but there is space at the top that I don't want.
Nice try though because you are right, I did not think of the viewbox ;-)
If I change the font to Gautami then you have space at the top and at the bottom. This font actually has a lot of unused space.
AdamDavidHill at 15-Sep-12 8:51am
   
Hmmm... have you tried setting Stretch="Fill"? It depends whether you don't mind distorting the aspect ratio of the text, but maybe experiment with that property? http://msdn.microsoft.com/en-us/library/system.windows.controls.viewbox.stretch(v=vs.95).aspx
Philip Stuyck at 15-Sep-12 10:08am
   
The unused space is still there, because it is actually part of the font. The viewbox is doing its thing, it just does not know about the unused space.
AdamDavidHill at 15-Sep-12 19:41pm
   
Ah, I see. You could use a Margin with negative values to counteract the spacing in the font. The trouble/risk would be that the word google (lowercase) vs. GOOGLE (uppercase) would need different values due to differing ascenders / descenders.
Philip Stuyck at 16-Sep-12 3:55am
   
That is true, and that is the reason for the code that is showing above. The parameters are somehow different for each charackter, but the problem is interpreting them correctly to make the proper modifications.
I am about to give up on this and stick to your solution, essentially the user will see that the text is smaller than the rectangle he has drawn but he can still select the text and make it bigger in this drawing application. I guess I am a little too perfectionistic about it.
I cannot mark this as a solution but I'll upvote anyway for the effort you put in trying to find a solution.
AdamDavidHill at 16-Sep-12 6:28am
   
Okay, no worries. Just a final couple of ideas. One is to either use all caps or small caps (or maybe Bank Gothic font etc.) to ensure the height of every character is the same (I'm assuming you're using text and not symbols). The other is to write an IValueConverter to calculate the margin by scanning the string and checking for characters like lowercase g, j, p, q or y etc. which have descenders and giving a dynamic margin offset. If using the Bank Gothic font approach check that the capital Q doesn't screw things up. Best of luck with this...!
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Can you use this:
TextBox myText = new TextBox();
Rect textRext = myText.GetRectFromCharacterIndex(myText.Text.Length);
 
http://blogs.microsoft.co.il/blogs/tamir/archive/2007/03/12/Text-length-measurement_3F00_-It_2700_s-really-easy-with-WPF.aspx[^]
  Permalink  
Comments
Philip Stuyck at 16-Sep-12 3:56am
   
Did not work, the space is also counted in the measurement, because it is part of the font itself.
So I cannot mark this as a solution but I'll upvote anyway for the effort you put in trying to find a solution.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 428
1 Maciej Los 249
2 BillWoodruff 199
3 /\jmot 180
4 Suraj Sahoo | Coding Passion 150
0 OriginalGriff 8,484
1 Sergey Alexandrovich Kryukov 7,407
2 DamithSL 5,639
3 Maciej Los 5,159
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web01 | 2.8.1411023.1 | Last Updated 15 Sep 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100