Drawing text using the GraphicsPath

NosherRees

Member
Joined
Sep 4, 2007
Messages
6
Programming Experience
5-10
I'm using the GraphicsPath to draw text onto a graphics object (PictureBox). Initially the view is zoomed out and the text is very small. When I zoom in the quality of the text is shown to be very poor. If I draw the text directly on the graphics object using DrawString then the quality is good.
Check out Figure1, The black and the red text are drawn using the same method but the black text is very poor in quality.
 

Attachments

  • Figure1.jpg
    Figure1.jpg
    27.4 KB · Views: 60
Have you tried modifying the Graphics instance? There are 6 or so properties that affect quality of the graphics, one of them TextRenderingHint might help, I can't recall if I tried it with text through graphicspath or just DrawString method. You can experiment with this. For example you can also apply transformations to the graphics instance and use the regular Draw... methods so they all will appear in same transformed view.
 
Thanks for the reply JohnH. I've tried setting the TextRenderingHint to the highest quality (ClearTypeGridFit) but it made no difference. I've also set the graphics SmoothingMode = SmoothingMode.HighQuality, still no diffence. The text that comes out poorly has a size of 7 whereas the text that comes out OK is size 30 so this is a size issue I just don't understand why I can plot the text using graphics.drawstring and it is fine but if I add the text to a graphicsPath then draw this on the graphics object it looses and clarity. I use the GraphicsPath so that I can flip and rotate my text. As you have suggested, I may have to look into applying the transformation directly to the graphics object and see what I get.
 
If you change the font size of your text instead of scaling the image, parametrizing every drawn shape to show the right size, it should output at a higher resolution.

It is as if you said that all draw methods were vectorial and the graphics object was bitmap. Resizing every call to the draw methods will allow you to generate a bitmap of higher resolution, but generating it the same way and stretching the bitmap into a new resolution will not do so well. The key is to set the resolution of the bitmap before you draw anything on it...

Could you show us the code that create the GraphicPath and draws it?

VB.NET:
        Dim path As New GraphicsPath()

        path.AddString("sometext", FontFamily.GenericMonospace, FontStyle.Regular, 50, New Point(0, 0), New StringFormat(StringFormatFlags.DirectionVertical))

        path.CloseAllFigures()
        e.Graphics.SmoothingMode = SmoothingMode.HighQuality

        e.Graphics.FillPath(Brushes.Black, path)

Maybe you can base yourself on this...
 
Hi, I have to rescale my graphics object as I'm displaying a 'map' in real world coordinates. So I may be displaying a set of targets (points) off the coast of the UK into which I need to zoom in and out off. I've attached the scale routine and the label plotting code.


VB.NET:
Public Shared Function SetScale(ByVal g As Graphics, ByVal gWidth As Single, ByVal gHeight As Single, _
ByVal Left As Double, ByVal Right As Double, ByVal Top As Double, ByVal Bottom As Double) As Double

        g.ResetTransform()

        ' Scale so the viewport's width and height
        ' map to the Graphics object's width and height.        
        g.ScaleTransform(gWidth / (Right - Left), gHeight / (Bottom - Top))

        ' Translate (left_x, top_y) to the Graphics
        ' object's origin.
        g.TranslateTransform(-Left, -Top)

        'return the scale factor 
        m_ScaleFactor = (gWidth / (Right - Left))
        Return m_ScaleFactor

    End Function


    Public Sub PlotText(ByRef g As Graphics, ByVal Label As String, ByVal Pos As PointF, _
ByVal Bearing As Single, ByVal TextLoc As TextLocationType)
        Dim TextPos As PointF
        Dim TextSize As SizeF = g.MeasureString(Label, LabelFont)
        Dim MyFontFamily As New FontFamily(LabelFont.Name)
        Dim MyGP As GraphicsPath
        Dim Angle As Double
        Dim NegTextWidth As Double = TextSize.Width * -1
        Dim NegTextHeight As Double = TextSize.Height * -1
        Dim OldSmoothingMode As SmoothingMode = g.SmoothingMode

        Bearing = CorrectBearing(Bearing)

        If LabelFont.Size < 5 Then Exit Sub

        Angle = AngleToBearing(Bearing * DEGTORAD, vbRadOrDegsType.vbABTRadians) * m_RADTODEG

        MyGP = New GraphicsPath(FillMode.Winding)

        g.SmoothingMode = SmoothingMode.HighQuality

        Dim MyRM As New Matrix(1, 0, 0, -1, 0, TextPos.Y * 2)
       
        MyGP.AddString(Label, MyFontFamily, FontStyle.Regular, LabelFont.Size, TextPos, StringFormat.GenericDefault)

        MyRM.RotateAt(-Angle, TextPos)
        MyGP.Transform(MyRM)

        g.FillPath(New SolidBrush(m_FontColour), MyGP)
        g.SmoothingMode = OldSmoothingMode

    End Sub
I use the rotation matirix to flip the text as I've scaled the picturebox so that values increase upwards.
 
Last edited by a moderator:
I have not used most of these functions, but I would say the problem comes from the g.scaletransform which simply says "make every pixel in me 1.3 pixels wide and high" and rounding errors cause your display glitches.

Instead of using it, I would suggest you to try to set an instance variable to the scale ratio and modify the font accordingly. Then you would have to do the same for every single shape you draw on you graph, making sure all texts are scaled by font and not by scaling.
 
Back
Top