A few notes on the matter:
When you draw the outline of a shape, GraphicsPath adds the outline, using the width of the Pen specified, to the outside of the shape.
The outline begins at the external margin of the shape and proceeds outwards.
This applies while the Pen width specified is withing twice the minimum dimension of the shape.
When the Pen is wider than this measure, the Pen width is clipped and moved towards the outside by a measure equal to the difference between the width specified and the shape min dimension x2.
E.g., if you have a shape (say, an ellipse) with a size of 20x30
, the Pen width can reach 40.0f
before it's moved to the outside of the shorter dimension.
The size of the ellipse in the image below is (20x30
).
The outline Pen is set, respectively, to 40.0f
, 46.0f
, 52.0f
and 65.0f
:

This is what happens when you add your text to a GraphicsPath and it's converted to curves. The shapes parts that have a size smaller than the Pen width, when outlined, cause the outline to move to the outside. You can see it first in all dots in the text.
You can solve the problem (just a perceived problem, what you see is actually what you asked to draw), you can widen the Path, so it will expand in-wards, not just out-wards.
You can widen the Path using its Widen() method, specifying a Pen used to expand the Path (a Pen width of 1.0f
is enough).
Define the drawing properties:
Imports System.Drawing
Imports System.Drawing.Drawing2D
Private drawText As String = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
Private drawFont As New Font("Times New Roman", 60, FontStyle.Regular)
Private textBounds As RectangleF = RectangleF.Empty
Private outlineWidth As Single = 20.0F
Private outlineColor As Color = Color.Black
Private fillColor As Color = Color.Yellow
Draw the outline first, inside the specified bounds, then fill the Path using the same exact bounds and StringFormat properties.
Here, I'm using StringFormat.GenericTypographic: it's a pre-set of some standard settings that is often used as base for drawing. You can initialize this pre-set, then add/change specific properties when needed (e.g, you need to center the text vertically or horizontally or both).
See also the notes in:
Properly draw text using GraphicsPath
Flip the GraphicsPath that draws the text/string
I'm using a PictureBox as canvas here. It's the same thing (but it's double-buffered by default).
Private Sub PictureBox1_Paint(sender As Object, e As PaintEventArgs) Handles PictureBox1.Paint
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
' Add composition if you have a composited background
'e.Graphics.CompositingQuality = CompositingQuality.HighQuality
textBounds = RectangleF.Inflate(PictureBox1.ClientRectangle, -5, -5)
textBounds.Offset(10, 10)
DrawTextOutline(e.Graphics, textBounds, drawText, drawFont, outlineColor, outlineWidth, LineCap.Round)
FillTextSolid(e.Graphics, textBounds, drawText, drawFont, fillColor)
End Sub
Private Sub DrawTextOutline(g As Graphics, bounds As RectangleF, text As String, font As Font, penColor As Color, penSize As Single, cap As LineCap)
Dim lJoin As LineJoin = If(cap = LineCap.Round, LineJoin.Round, LineJoin.Bevel)
Using gp As GraphicsPath = New GraphicsPath(FillMode.Winding),
pen As New Pen(penColor, penSize) With {.LineJoin = lJoin, .StartCap = cap, .EndCap = cap},
widenPen As New Pen(Color.Black, 1.0F)
gp.AddString(text, font.FontFamily, font.Style, font.Size, bounds, StringFormat.GenericTypographic)
gp.Widen(widenPen)
g.DrawPath(pen, gp)
End Using
End Sub
Private Sub FillTextSolid(g As Graphics, bounds As RectangleF, text As String, font As Font, fillColor As Color)
Using gp As GraphicsPath = New GraphicsPath(),
brush As New SolidBrush(fillColor)
gp.AddString(text, font.FontFamily, font.Style, font.Size, bounds, StringFormat.GenericTypographic)
g.FillPath(brush, gp)
End Using
End Sub
Sample results:

C# Version:
General settings:
using System.Drawing;
using System.Drawing.Drawing2D;
private static string drawText = "Lorem Ipsum is simply dummy text of the printing and typesetting industry";
private static Font drawFont = new Font("Times New Roman", 60, FontStyle.Regular);
private static RectangleF textBounds = RectangleF.Empty;
private static float outlineWidth = 20f;
private static Color outlineColor = Color.Black;
private static Color fillColor = Color.Yellow;
Drawing methods:
private void PictureBox1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
textBounds = RectangleF.Inflate(pictureBox1.ClientRectangle, -5, -5);
textBounds.Offset(10, 10);
DrawTextOutline(e.Graphics, textBounds, drawText, drawFont, outlineColor, outlineWidth, LineCap.Round);
FillTextSolid(e.Graphics, textBounds, drawText, drawFont, fillColor);
}
private void DrawTextOutline(Graphics g, RectangleF bounds, string text, Font font, Color penColor, float penSize, LineCap cap)
{
LineJoin lJoin = cap == LineCap.Round ? LineJoin.Round : LineJoin.Bevel;
using (var gp = new GraphicsPath(FillMode.Winding))
using (Pen pen = new Pen(penColor, penSize) { LineJoin = lJoin, StartCap = cap, EndCap = cap })
using (Pen widenPen = new Pen(Color.Black, 1.0f)) {
gp.AddString(text, font.FontFamily, (int)font.Style, font.Size, bounds, StringFormat.GenericTypographic);
gp.Widen(widenPen);
g.DrawPath(pen, gp);
};
}
private void FillTextSolid(Graphics g, RectangleF bounds, string text, Font font, Color fillColor)
{
using (var gp = new GraphicsPath())
using (var brush = new SolidBrush(fillColor)) {
gp.AddString(text, font.FontFamily, (int)font.Style, font.Size, bounds, StringFormat.GenericTypographic);
g.FillPath(brush, gp);
}
}