3

I’m running into problems when rendering text on my document. Specifically, the text renders too low. I tried filling a rectangle behind the text to see what happens, and I discovered that they appear to render slightly offset:

Offset text from background using the same rectangle.

Here’s the code I used to render the box and text:

_doc.FillRectangle(Colors.LightGray, 36, 72, 37.344, 9);
_doc.DrawString("Lorem", new Font("Arial", 12), Colors.Black, 
   new Rect(36, 72, 37.344, 9));

I know that the height of the rectangle (9) doesn’t appear to match the height of the font (12), which I thought might have been the problem at first. However, I then did a MeasureString on the font itself and discovered that its height was actually 9 rather than 12 (I used the immediate window for this, which is why it's a pic and not a text block):

Results of the Immediate Window calling MeasureString.

Any ideas as to what could be causing it and how to avoid it?

Thanks!

-Ari

Ari Roth
  • 5,392
  • 2
  • 31
  • 46

3 Answers3

1
  • There are couple of posts that discuss the WPF text rendering inconsistencies.

  • One of the other posts: WPF Text rendering problem, stated that SnapToDevicePixels could ruin text rendering if text has been resized to display across pixels. The suggested answer was to keep,

    SnapToDevicePixels = True on borders/backgrounds but turn it off for text elements.

  • As for the current method your are using. Please take a look at one of my earliers posts: Increase bar chart values with button clicks : I have used DrawString() to add a letter within a rectangle. All drawing is done in a Panel.

code: ...

   panel1.Paint += new PaintEventHandler(panel1_Paint);

        using (Graphics g = this.panel1.CreateGraphics())
        {
            Brush brush = new SolidBrush(Color.Green);
            g.FillRectangle(brush, px, py, 20, 20);                           
            Pen pen = new Pen(new SolidBrush(Color.White));
            g.DrawRectangle(pen, px, py, 20, 20);                    

            //add each total5Click into chart block
            g.DrawString((total5Times).ToString(), new Font("Arial", 7), 
            new SolidBrush(Color.AntiqueWhite),
            px + 1, py+8, StringFormat.GenericDefault);
            pen.Dispose();}
    ...
Community
  • 1
  • 1
bonCodigo
  • 14,268
  • 1
  • 48
  • 91
  • I appreciate the info, but I'm not actually rendering in WPF. I'm using the ComponentOne library to write to PDF, though I'm launching it in a WPF app. – Ari Roth Jan 02 '13 at 20:40
  • @Ari so let me get this straight, 1. your using `WPF` for the initial text. 2. Make a `PDF` 3. Use `CompoenetOne`, then things gets literally screwed up when you are writing the `PDF` back to `WPF`? please clarify out of these 3 stages where things really go astray. – bonCodigo Jan 02 '13 at 20:58
  • @Ari by reading the comment you gave to Sorceri, why not we do the text `font size` to be equivalent to `font height`, will that work? – bonCodigo Jan 02 '13 at 21:03
  • bonCodigo, It's only WPF in the sense that I have to have references to PresentationCore and WindowsBase because of requirements by the C1 component. Other than that the whole thing is in straight C# without any actual WPF controls. I apologize if I wasn't clear on that. As for the other question, that appears to be the problem -- calling C1's MeasureString() on a 12-point font yields a height of 9. What I'm not sure of is whether this is a bug on the part of C1 or if it's some important detail that I'm missing. – Ari Roth Jan 02 '13 at 23:09
  • Have you seen this [post on measuringText() vs gettextbounds](http://stackoverflow.com/questions/7549182/android-paint-measuretext-vs-gettextbounds)? I scanned a bit and looks very promising to get an idea but it's on Android platforms. For `measuringString` have you set your `Boxwidth` right? – bonCodigo Jan 02 '13 at 23:25
0

I would suggest using the method DrawString Method (String, Font, Brush, RectangleF, StringFormat) and supplying the String Format. After reviewing ComponentOne it appears they are putting together several methods so I may be an issue with the StringFormat default set for the method. I am kind of assuming they are calling the main DrawString method and passing in default params if one was not supplied.

Also be sure to check the section for

Use LineAlignment to specify the vertical alignment of the string.

in the link below

Link to Method

Sorceri
  • 7,870
  • 1
  • 29
  • 38
  • I looked into that, and in fact just tried it. It doesn't seem to help. I suspect this is actually a bug on ComponentOne's part -- it looks like (and this is from eyeballing it) the library renders too low by the difference between the actual height of the font (9) and the font size (12) which, as they're both in points, I would have expected to be identical. – Ari Roth Jan 02 '13 at 20:39
0

Well, after further research and experimentation there's definitely a bug in the ComponentOne library. Specifically, the overload I happened to have used here returned the wrong hight. If you specific an available width explicitly, you get the correct height. Specifically, this code generates the correct data:

var resultHeight = _doc.MeasureString(text, pdfFont, double.MaxValue).Height;
var resultWidth = _doc.MeasureString(text, pdfFont).Width;

return new Tuple<double,double>(resultHeight, resultWidth);

Note the addition of the third parameter for the height only -- double.MaxValue. The width is correctly calculated in both cases, but the height is only correctly calculated if you provide that double parameter. I chose double.MaxValue in this case simply because I don't know how wide the string is going to turn out to be so I don't want to risk being given a multi-line height.

Ari Roth
  • 5,392
  • 2
  • 31
  • 46