Text Rendering using Type1 Font | .NET

Rendering Text

To render text with the glyph outline renderer, implement the Aspose.Font.Rendering.IGlyphOutlinePainter interface and use it to build paths for individual glyphs.

  1. Create a Type1GlyphOutlinePainter class that accepts a System.Drawing.Drawing2D.GraphicsPath. Its methods translate the font outline commands into lines and Bézier curves in that path.
 1// Implement a painter that builds a graphics path from a glyph outline
 2
 3internal sealed class Type1GlyphOutlinePainter : IGlyphOutlinePainter
 4{
 5    private readonly GraphicsPath path;
 6    private PointF currentPoint;
 7
 8    public Type1GlyphOutlinePainter(GraphicsPath path)
 9    {
10        this.path = path;
11    }
12
13    public void MoveTo(MoveTo moveTo)
14    {
15        path.CloseFigure();
16        currentPoint = new PointF((float)moveTo.X, (float)moveTo.Y);
17    }
18
19    public void LineTo(LineTo lineTo)
20    {
21        PointF nextPoint = new PointF((float)lineTo.X, (float)lineTo.Y);
22        path.AddLine(currentPoint, nextPoint);
23        currentPoint = nextPoint;
24    }
25
26    public void CurveTo(CurveTo curveTo)
27    {
28        PointF nextPoint = new PointF((float)curveTo.X3, (float)curveTo.Y3);
29        path.AddBezier(
30            currentPoint,
31            new PointF((float)curveTo.X1, (float)curveTo.Y1),
32            new PointF((float)curveTo.X2, (float)curveTo.Y2),
33            nextPoint);
34        currentPoint = nextPoint;
35    }
36
37    public void ClosePath()
38    {
39        path.CloseFigure();
40    }
41}
  1. Create a DrawText() method that draws text into a System.Drawing.Bitmap and saves it as a PNG file. The method performs the following operations:

The glyph baseline remains constant in this example. The horizontal coordinate is accumulated from the previous glyph’s advance and kerning. FontWidthToImageWidth() converts font units to bitmap pixels using the source resolution, font size, and DPI.

The implementation of DrawText() is shown below.

 1// Render text into a bitmap with a custom glyph outline painter
 2
 3private static void DrawText(string text, IFont font, double fontSize,
 4    Brush backgroundBrush, Brush textBrush, string outputFile)
 5{
 6    GlyphId[] glyphIds = text
 7        .Select(character => font.Encoding.DecodeToGid(character))
 8        .ToArray();
 9    const double dpi = 300;
10    double resolutionCorrection = dpi / 72;
11
12    using var outputBitmap = new Bitmap(960, 720);
13    outputBitmap.SetResolution((float)dpi, (float)dpi);
14    using Graphics outputGraphics = Graphics.FromImage(outputBitmap);
15    outputGraphics.FillRectangle(backgroundBrush, 0, 0, outputBitmap.Width, outputBitmap.Height);
16    outputGraphics.SmoothingMode = SmoothingMode.HighQuality;
17
18    GlyphId? previousGlyphId = null;
19    double glyphXCoordinate = 0;
20    double glyphYCoordinate = fontSize * resolutionCorrection;
21
22    foreach (GlyphId glyphId in glyphIds)
23    {
24        Glyph glyph = font.GlyphAccessor.GetGlyphById(glyphId);
25        if (glyph == null)
26            continue;
27
28        if (previousGlyphId != null)
29        {
30            double kerning = font.Metrics.GetKerningValue(previousGlyphId, glyphId)
31                / (double)glyph.SourceResolution * fontSize * resolutionCorrection;
32            double advance = FontWidthToImageWidth(
33                font.Metrics.GetGlyphWidth(previousGlyphId),
34                glyph.SourceResolution,
35                fontSize,
36                dpi);
37            glyphXCoordinate += kerning + advance;
38        }
39
40        using var path = new GraphicsPath();
41        var outlinePainter = new Type1GlyphOutlinePainter(path);
42        IGlyphRenderer renderer = new GlyphOutlineRenderer(outlinePainter);
43        var glyphMatrix = new TransformationMatrix(new double[]
44        {
45            fontSize * resolutionCorrection,
46            0,
47            0,
48            -fontSize * resolutionCorrection,
49            glyphXCoordinate,
50            glyphYCoordinate
51        });
52
53        renderer.RenderGlyph(font, glyphId, glyphMatrix);
54        path.FillMode = FillMode.Winding;
55        outputGraphics.FillPath(textBrush, path);
56        previousGlyphId = glyphId;
57    }
58
59    outputBitmap.Save(outputFile, ImageFormat.Png);
60}
  1. Add the utility method that converts a width in font units to image pixels.
1// Convert a width in font units to pixels
2
3private static double FontWidthToImageWidth(double width, int fontSourceResolution,
4    double fontSize, double dpi = 300)
5{
6    double resolutionCorrection = dpi / 72;
7    return width / fontSourceResolution * fontSize * resolutionCorrection;
8}

Calling the Rendering Text functionality

The following example loads Type1/courier.pfb from DataDir, renders the same text with two color schemes, and writes both PNG files to OutputDir.

 1// Load a Type1 font and render text in two color schemes
 2
 3string fileName = Path.Combine(DataDir, "Type1", "courier.pfb");
 4FontDefinition fontDefinition = new FontDefinition(
 5    FontType.Type1,
 6    new FontFileDefinition("pfb", new FileSystemStreamSource(fileName)));
 7
 8Type1Font? font = Aspose.Font.Font.Open(fontDefinition) as Type1Font;
 9if (font == null)
10    throw new InvalidOperationException("Unable to load the Type1 font.");
11
12string firstOutput = Path.Combine(OutputDir, "hello1_type1_out.png");
13string secondOutput = Path.Combine(OutputDir, "hello2_type1_out.png");
14DrawText("Hello world", font, 14, Brushes.White, Brushes.Black, firstOutput);
15DrawText("Hello world", font, 14, Brushes.Yellow, Brushes.Red, secondOutput);