3

Im drawing Text using the following code onto a Bitmap

GraphicsPath pth = new GraphicsPath();
var style = (int)myfont.Style;
pth.AddString(tcaption.Text, myfont.FontFamily, style, myfont.Size, point, StringFormat.GenericTypographic);
p = new Pen(new SolidBrush(bc), 2f);
mygraphics.DrawPath(p, pth);

I'm using the TextRenderer to measure the size of the string..

int  Width = TextRenderer.MeasureText(tcaption.Text, myfont).Width;

But this does not produce the correct size of the drawn string; there is around 20-30% difference from the actual size of the drawn string?

What im i doing wrong? Please advice.

UPDATE:

I want to draw a Text and an Image onto a Bitmap,so inorder to accommodate both i'm creating an Bitmap like this

intWidth = TextRenderer.MeasureText(tcaption.Text, cfont).Width + image.Width;
intHeight = TextRenderer.MeasureText(tcaption.Text, cfont).Height +image.Height;
tempimage= new Bitmap(intWidth, intHeight);

Then i create Graphics object from the Bitmap like this

 using (Graphics newg = Graphics.FromImage(tempimage))

@Hans Passant

I have also tried the Graphics.MeasureString as an alternative to TextRenderer

Now i set the position of the text and image-I need to draw the image at the top left corner .. so

                imageposy = 0;
                imageposx = 10;                
                textposy = image.Height;                     
                textposx = 0;

Then i draw the text like this

   po=new Point(textposx, textposy);
   newg.SmoothingMode = SmoothingMode.AntiAlias;                                      
   GraphicsPath pth = new GraphicsPath();
   var style = (int)myfont.Style;
   pth.AddString(tcaption.Text, myfont.FontFamily, style, myfont.Size, po, 
   StringFormat.GenericTypographic);
   newg.FillPath(new SolidBrush(fc), pth);

Now i draw the image like this

 Rectangle nrect = new Rectangle(imageposx, imageposy, image.Width, 
 image.Height);
 objGraphics = Graphics.FromImage(tempimage);
 objGraphics.DrawImage(image, nrect);

As you have seen i need to add the offset 10 to imageposition x coordinate to correct the measurement issue.

Hope my update throws more light into the question... what im i doing wrong? Please advice..

techno
  • 6,100
  • 16
  • 86
  • 192
  • Have you read the [TextRenderer.MeasureText()](https://msdn.microsoft.com/en-us/library/y4xdbe66(v=vs.110).aspx) MSDN doc already? It notes `The MeasureText method requires that the text is drawn on a single line.` so if `tcaption.Text` is multi-line that might be related? I'm not well versed in the `TextRenderer` object though – sab669 Apr 06 '17 at 12:52
  • What is mygraphics? read this: http://stackoverflow.com/a/6705023/891715, or there may be wrong TextFormatFlags. Alternatively, you may want to try this method instead: https://msdn.microsoft.com/en-us/library/h60yx8s5%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 – Arie Apr 06 '17 at 12:53
  • this may also be of interest to you, it's about padding in textrenderer: http://stackoverflow.com/q/4428335/891715 – Arie Apr 06 '17 at 13:01
  • @sab669 it's not multiline – techno Apr 06 '17 at 15:03
  • @Arie mygraphics is created from a bitmap whose width and size =TextRenderer.MeasureText.... – techno Apr 06 '17 at 15:04
  • How are you determining that the size is wrong? What are you comparing it to? – Chris Dunaway Apr 06 '17 at 15:29
  • 1
    Wrong text rendering engine, you must use Graphics.MeasureString() to get in the ballpark. – Hans Passant Apr 06 '17 at 15:34
  • @HansPassant I have also tried using graphics.MeasureString ... I get the same results. – techno Apr 06 '17 at 15:36
  • @ChrisDunaway Actually I need a bitmap drawn at a location ..e.g.:after this text ... but when calling say -draw at position x,y .. where x=textwidth +offset and say y= textheight+10 .. I don't get the desired results – techno Apr 06 '17 at 15:40
  • 1
    You should mention that in the question of course. You are not using the same font height, use FontFamily.GetEmHeight(). – Hans Passant Apr 06 '17 at 15:42
  • 30% ?? Really? How long or short is the Text? Are you sure it isn't simply giving some white space around the text, as it will unless you use the Typographical param..? gp.GetBound doesn't do that but will not get the top left right.. – TaW Apr 06 '17 at 16:05
  • @HansPassant Please see the update... – techno Apr 07 '17 at 08:33
  • @TaW Not 30% .. just a rough figure.. please see my update... – techno Apr 07 '17 at 08:34
  • 10 pixel is not a lot. You may have to live with it unless you want to invesigate the pixels. - You could try to optimize even more by factoring in the GetBounds of a GraphicsPath the holds the same text. It will be smaller as it will not include any leeway around the text but it will give you a hint on how large the difference still is.. – TaW Apr 07 '17 at 08:38
  • @TaW i can only use getbounds after drawing the text right? – techno Apr 08 '17 at 03:32
  • No. You can get it at any time after creating the GraphicsPath. You could get it before and after adding characters for exmple.. – TaW Apr 08 '17 at 06:53
  • @TaW Tried that.. its not producing the correct results... – techno Apr 08 '17 at 08:51
  • Correct they are but not necessarily what you want. You can prove by drawing the resulting bounding rectangle. Now you see they are correct but the location is not at 0,0 but somewhat to the lower/right.. – TaW Apr 08 '17 at 09:03
  • [Also see here!](http://stackoverflow.com/questions/33148543/how-to-draw-a-string-at-a-pixel-perfection-position/33152250?s=10|0.0000#33152250) - And even [here](http://stackoverflow.com/questions/29018430/custom-richtextbox-control-kerning-issues/29037028#29037028) for a discussion of kerning actually but with nice images.. - If you still have problems maybe posting an image would help. – TaW Apr 08 '17 at 12:03
  • @TaW Actually i need to draw an image at a particular location of a string... so i need the correct dimension of the string to place the image.. how can i do this correctly? – techno Apr 08 '17 at 16:41
  • But the path.GetBounds() rectangle __does__ give you the location and size of the string, when drawn with the same parameters or directly with the path! Did you try to draw the Rectangle?? Still an image showing what goes wrong and what you want would be useful. – TaW Apr 08 '17 at 17:01
  • @TaW i will try that.. and get back..btw as far as my old approach is concerned .. this minor difference 10Pixels or something ... is that normal...? i was wondering if there is something wrong with my code.. – techno Apr 08 '17 at 17:06
  • The purpose of MeasureString/Text are not a pixel-perfect measurement but results that make sure the consecutive strings place by that measurement to not touch or even overlap. This important when creating multiformat text. So, yes a few pixels whitespace around the text are indeed normal. – TaW Apr 08 '17 at 17:09
  • @TaW Alright thanks...... – techno Apr 08 '17 at 17:22
  • Please look at: http://stackoverflow.com/a/8436484/965722 so instead of using TextRenderer use GraphicsPath. This solved my issue: http://stackoverflow.com/questions/25891547/draw-character-in-center-of-custom-control-font-awesome-glyph – Misiu Apr 10 '17 at 11:14
  • @Misiu okay... thanks – techno Apr 13 '17 at 12:43
  • @techno if this works please ark my answer as solution. Thanks – Misiu Apr 13 '17 at 12:54

1 Answers1

2

instead of using TextRenderer use GraphicsPath:

var path = new GraphicsPath();
path.AddString(text, font.FontFamily, (int)font.Style, size, new Point(0, 0), StringFormat.GenericTypographic);
var area = Rectangle.Round(path.GetBounds());

Here is sample code that generates image with size of text:

private Image DrawText(String text, Font font, int size, Color textColor, Color backColor)
{
    var path = new GraphicsPath();
    path.AddString(text, font.FontFamily, (int)font.Style, size, new Point(0, 0), StringFormat.GenericTypographic);
    var area = Rectangle.Round(path.GetBounds());

    Rectangle br = Rectangle.Round(path.GetBounds());
    var img = new Bitmap(br.Width, br.Height);

    var drawing = Graphics.FromImage(img);
    drawing.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
    drawing.SmoothingMode = SmoothingMode.HighSpeed;
    drawing.Clear(backColor);

    drawing.TranslateTransform((img.Width - br.Width) / 2 - br.X, (img.Height - br.Height) / 2 - br.Y);
    drawing.FillPath(Brushes.Black, path);
    Brush textBrush = new SolidBrush(textColor);

    drawing.Save();

    textBrush.Dispose();
    drawing.Dispose();

    return img;
}

Here are sample results:

enter image description here enter image description here enter image description here

Misiu
  • 4,738
  • 21
  • 94
  • 198
  • I had tried this .. But it does not work for the intended purpose. – techno Apr 13 '17 at 17:00
  • @techno please take a look at my updated answer. I was able to get exact size of my text and create image containing that text. You can change `SmoothingMode` to get different result, but this should be a good start. If something isn't working please post some more code in Your question and maybe illustrate desired result. – Misiu Apr 13 '17 at 21:21
  • Your answer is correct .. but i changed my approach.I trimmed the whitespace off the drawn bitmap and thus converted the text to image.. – techno Apr 17 '17 at 17:40
  • @techno good to hear You were able to solve Your problem :) If You want You can share Your code as answer so that anyone that has similar problem will have working solution. – Misiu Apr 17 '17 at 17:44