Document Solutions for Imaging
Features / Work with Text / Draw Rotated Text
In This Topic
    Draw Rotated Text
    In This Topic

    DsImaging allows you to draw rotated text in unrotated rectangular bounds using DrawRotatedText and MeasureRotatedText methods of GcGraphics class. DrawRotatedText draws text at an angle in a specified rectangle, whereas MeasureRotatedText calculates the bounds where to draw the text.

    Both methods accept the same parameters despite their different functioning. The following table lists the parameters these methods accept:

    Parameters Description
    textLayout

    TextLayout to draw. This includes one or multiple text lines with various text formats. TextAlignment property specifies the alignment of text in each text line. It is important to draw a rotated text.

    Note: A few other properties of TextLayout have no effect when drawing a rotated text: MaxWidth, MaxHeight, FlowDirection, CanSkipFirstLineWithIndentation, ObjectRects, ParagraphAlignment, MarginLeft, MargingRight, MarginTop, MarginBottom, ColumnWidth, and RowHeight.
    angle Text rotation angle in degrees. The expected range is -90 and +90, specifying an angle in degrees. Positive angles refer to clockwise rotation. Angles less than -90 are treated as -90 degrees, and angles greater than +90 are treated as +90 degrees.
    verticalStacking Stacks text lines either horizontally (along the top and bottom sides of the rectangle) or vertically (along the left and right sides of the rectangle).
    rect Target rectangle for the text.
    alignment Alignment of the whole text rectangle within the target rectangle using RotatedTextAlignment enumeration to: Top Left, Top Right, Top Center, Bottom Left, Bottom Right, Bottom Center, Middle Left, Middle Right, and Middle Center.
    Note: The methods may change or split the original TextLayout into multiple parts. Hence, if necessary, create a clone of the TextLayout in advance.

    Refer to the example code to draw multiple rotated texts in different settings:

    C#
    Copy Code
    // Initialize GcWicBitmap.
    using var bmp = new GcWicBitmap(1050, 310, true);
    
    // Draw rotated text with specified angle and alignment.
    using (var g = bmp.CreateGraphics(Color.White))
    {
        Draw(g, 10, angle: -90, false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
        Draw(g, 240, angle: -60, false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
        Draw(g, 480, angle: -45, false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
        Draw(g, 720, angle: -30, false, RotatedTextAlignment.BottomLeft, TextAlignment.Leading);
    }
    
    // Save the image.
    bmp.SaveAsPng("RotatedText.png");
    
    // Define Draw method.
    static void Draw(GcGraphics g, int x, int angle, bool verticalStacking,
        RotatedTextAlignment rotatedAlign, TextAlignment textAlign)
    {
        // Initialize RectangleF.
        var rect = new RectangleF(x, 100, 200, 200);
    
        // Draw rectangle.
        g.DrawRectangle(rect, new Pen(Color.Green, 1));
    
        // Initialize TextLayout.
        var tl = g.CreateTextLayout();
    
        // Set text format.
        var fmt = new TextFormat
        {
            FontName = "Calibri",
            FontSize = 18,
        };
    
        // Add the text.
        tl.Append("This is long text, very long text, very long long.", fmt);
        
        // Set text alignment.
        tl.TextAlignment = textAlign;
    
        // Clone TextLayout.
        var tlCopy = tl.Clone(true);
    
        // Calculate bounds of rotated text inside a rectangle.
        var tlRect = g.MeasureRotatedText(tlCopy, angle, verticalStacking, rect, rotatedAlign);
        
        // Draw rectangle with text.
        g.DrawRectangle(tlRect, new Pen(Color.Red, 1));
    
        // Draw rotated text.
        g.DrawRotatedText(tl, angle, verticalStacking, rect, rotatedAlign);
    
        // Draw strings with all text fromat details.
        fmt.FontSize = 12;
        g.DrawString($"angle = {angle}°", fmt, new PointF(x, 10));
        g.DrawString($"TextAlignment = {tl.TextAlignment}", fmt, new PointF(x, 30));
        g.DrawString($"alignment = {rotatedAlign}", fmt, new PointF(x, 50));
        g.DrawString($"verticalStacking = {verticalStacking}", fmt, new PointF(x, 70));
    }
    

    Draw Excel Like Rotated Text

    With DrawRotatedText method, DsImaging allows you to define DrawExcelText method, which simulates the Excel renderer used for drawing rotated text. This method will differ from the DrawRotatedText method, as it considers the positive angles to render the text in a counterclockwise direction.

    Refer to the example code to draw rotated text in specified unrotated rectangular bounds similar to Excel:

    C#
    Copy Code
    namespace ExcelTextSimulator
    {
        // Define enums.
        enum HorizontalAlignment
        {
            Left,
            Right,
            Center
        }
    
        enum VerticalAlignment
        {
            Top,
            Bottom,
            Center
        }
    
        internal class Program
        {
            static void Main(string[] _)
            {
                // Initialize GcBitmap.
                using (var bmp = new GcBitmap(700, 450, true))
                {
                    // Draw rotated text.
                    using (var g = bmp.CreateGraphics(Color.White))
                    {
                        Draw(g, new RectangleF(100, 100, 500, 250));
                    }
                    bmp.SaveAsPng("ExcelLikeRotatedText.png");
                }
            }
    
            // Define Draw method.
            static void Draw(GcGraphics g, RectangleF rect)
            {
                // Draw rectangle.
                g.DrawRectangle(rect, new Pen(Color.Green, 1));
    
                // Initialize TextLayout.
                var tl = g.CreateTextLayout();
    
                // Set text format.
                var fmt = new TextFormat
                {
                    FontName = "Calibri",
                    FontSize = 30,
                    FontSizeInGraphicUnits = true
                };
    
                // Add the text.
                tl.Append("Quick brown", fmt);
                fmt.FontSize = 60;
                tl.Append(" fox", fmt);
                fmt.FontSize = 30;
                tl.Append(" jumps over the lazy dog.", fmt);
                fmt.FontSize = 50;
                tl.Append(" Quick brown fox jumps", fmt);
                fmt.FontSize = 20;
                tl.Append(" over the lazy dog.", fmt);
    
                int angle = 45;
    
                // Draw text.
                DrawExcelText(g, tl, angle, rect, HorizontalAlignment.Right, VerticalAlignment.Top);
            }
    
            // Define DrawExcelText method.
            static void DrawExcelText(GcGraphics g, TextLayout tl, int degrees, RectangleF rect, HorizontalAlignment hAlign, VerticalAlignment vAlign)
            {
                if (degrees == 90)
                {
                    if (vAlign == VerticalAlignment.Bottom)
                        tl.TextAlignment = TextAlignment.Leading;
                    else if (vAlign == VerticalAlignment.Top)
                        tl.TextAlignment = TextAlignment.Trailing;
                    else
                        tl.TextAlignment = TextAlignment.Center;
                }
                else if (degrees == -90)
                {
                    if (vAlign == VerticalAlignment.Top)
                        tl.TextAlignment = TextAlignment.Leading;
                    else if (vAlign == VerticalAlignment.Bottom)
                        tl.TextAlignment = TextAlignment.Trailing;
                    else
                        tl.TextAlignment = TextAlignment.Center;
                }
                else
                {
                    if (hAlign == HorizontalAlignment.Left)
                        tl.TextAlignment = TextAlignment.Leading;
                    else if (hAlign == HorizontalAlignment.Right)
                        tl.TextAlignment = TextAlignment.Trailing;
                    else
                        tl.TextAlignment = TextAlignment.Center;
                }
    
                RotatedTextAlignment align;
                if (vAlign == VerticalAlignment.Top)
                {
                    if (hAlign == HorizontalAlignment.Left)
                        align = RotatedTextAlignment.TopLeft;
                    else if (hAlign == HorizontalAlignment.Right)
                        align = RotatedTextAlignment.TopRight;
                    else
                        align = RotatedTextAlignment.TopCenter;
                }
                else if (vAlign == VerticalAlignment.Bottom)
                {
                    if (hAlign == HorizontalAlignment.Left)
                        align = RotatedTextAlignment.BottomLeft;
                    else if (hAlign == HorizontalAlignment.Right)
                        align = RotatedTextAlignment.BottomRight;
                    else
                        align = RotatedTextAlignment.BottomCenter;
                }
                else
                {
                    if (hAlign == HorizontalAlignment.Left)
                        align = RotatedTextAlignment.MiddleLeft;
                    else if (hAlign == HorizontalAlignment.Right)
                        align = RotatedTextAlignment.MiddleRight;
                    else
                        align = RotatedTextAlignment.MiddleCenter;
                }
    
                // Draw rotated text inside a specific rectangle.
                g.DrawRotatedText(tl, -degrees, false, rect, align);
            }
        }
    }
    

    Draw Text in Slanted Rectangles

    With DrawSlantedText method of GcGraphics class, DsImaging also allows you to draw rotated text in specified slanted rectangular bounds, similar to Excel. This method is similar to DrawRotatedText method except for the parameter of SlantedTextAlignment type.

    SlantedTextAlignment enumeration provides the following six different modes for the slanted rectangles:

    Modes Description
    BelowRotatedInside The text appears below the rectangle side, rotated to the same angle as text. The side above the text is rotated inside the rectangle.
    BelowRotatedOutside The text appears below the rectangle side, rotated to the same angle as text. The side above the text is rotated outside the rectangle.
    AboveRotatedInside The text appears above the rectangle side, rotated to the same angle as text. The side below the text is rotated inside the rectangle.
    AboveRotatedOutside The text appears above the rectangle side, rotated to the same angle as text. The side below the text is rotated outside the rectangle.
    CenterInsideOutside The text appears at the center between the rectangle sides, rotated to the same angle as text. The side above the text is rotated inside the rectangle.
    CenterOutsideInside The text appears at the center between the rectangle sides, rotated to the same angle as text. The side above the text is rotated outside the rectangle.

    Refer to the example code to draw rotated text in specified slanted rectangular bounds in different modes similar to Excel:

    C#
    Copy Code
    // Initialize GcWicBitmap.
    using var bmp = new GcWicBitmap(940, 640, true);
    
    // Draw rotated text in slanted rectangles.
    using (var g = bmp.CreateGraphics(Color.White))
    {
        int angle = -70;
        var slantedAlign1 = SlantedTextAlignment.BelowRotatedInside;
        var slantedAlign2 = SlantedTextAlignment.BelowRotatedOutside;
        var slantedAlign3 = SlantedTextAlignment.AboveRotatedInside;
        var slantedAlign4 = SlantedTextAlignment.AboveRotatedOutside;
        var slantedAlign5 = SlantedTextAlignment.CenterInsideOutside;
        var slantedAlign6 = SlantedTextAlignment.CenterOutsideInside;
        bool verticalStacking = false;
    
        int x1 = 100;
        int y1Head = 10;
        int y1 = 100;
        int y2Head = 320;
        int y2 = 410;
    
        // Draw text and rectangle with specified angle and alignment.
        Draw(g, x1, y1Head, y1, angle, verticalStacking, slantedAlign1, TextAlignment.Leading);
        Draw(g, x1 + 270, y1Head, y1, angle, verticalStacking, slantedAlign2, TextAlignment.Trailing);
        Draw(g, x1 + 540, y1Head, y1, angle, verticalStacking, slantedAlign3, TextAlignment.Center);
    
        Draw(g, x1, y2Head, y2, angle, verticalStacking, slantedAlign4, TextAlignment.Leading);
        Draw(g, x1 + 270, y2Head, y2, angle, verticalStacking, slantedAlign5, TextAlignment.Trailing);
        Draw(g, x1 + 540, y2Head, y2, angle, verticalStacking, slantedAlign6, TextAlignment.Center);
    }
    
    // Save the image.
    bmp.SaveAsPng("TextinSlantedRectangle.png");
    
    // Define Draw method.
    static void Draw(GcGraphics g, int x, int yHead, int y, int angle, bool verticalStacking, SlantedTextAlignment slantedAlign, TextAlignment textAlign)
    {
        RectangleF rect;
        if (!verticalStacking)
        {
            // Initialize RectangleF.
            rect = new RectangleF(x, y, 160, 200);
            float dx = (float)(200.0 / Math.Tan(Math.PI * angle / -180.0));
            
            // Set switch cases for different slanted text alignments.
            switch (slantedAlign)
            {
                case SlantedTextAlignment.BelowRotatedInside:
                case SlantedTextAlignment.AboveRotatedOutside:
                case SlantedTextAlignment.CenterInsideOutside:
                    
                    // Draw the polygon.
                    g.DrawPolygon([
                        new PointF(x + dx, y),
                        new PointF(x + dx + 160, y),
                        new PointF(x + 160, y + 200),
                        new PointF(x, y + 200)],
                        new Pen(Color.Red, 1));
                    break;
                case SlantedTextAlignment.BelowRotatedOutside:
                case SlantedTextAlignment.AboveRotatedInside:
                case SlantedTextAlignment.CenterOutsideInside:
                    
                    // Draw the polygon.
                    g.DrawPolygon([
                        new PointF(x, y),
                        new PointF(x + 160, y),
                        new PointF(x - dx + 160, y + 200),
                        new PointF(x - dx, y + 200)],
                        new Pen(Color.Red, 1));
                    break;
            }
        }
        else
        {
            // Initialize RectangleF.
            rect = new RectangleF(x, y, 200, 160);
            float dy = (float)(200.0 * Math.Tan(Math.PI * angle / 180.0));
    
            // Set switch cases for different slanted text alignments.
            switch (slantedAlign)
            {
                case SlantedTextAlignment.BelowRotatedInside:
                case SlantedTextAlignment.AboveRotatedOutside:
                case SlantedTextAlignment.CenterInsideOutside:
                    if (angle >= 0)
    
                        // Draw the polygon.
                        g.DrawPolygon([
                            new PointF(x, y),
                            new PointF(x + 200, y + dy),
                            new PointF(x + 200, y + dy + 160),
                            new PointF(x, y + 160)],
                            new Pen(Color.Red, 1));
                    else
    
                        // Draw the polygon.
                        g.DrawPolygon([
                            new PointF(x, y - dy),
                            new PointF(x + 200, y),
                            new PointF(x + 200, y + 160),
                            new PointF(x, y - dy + 160)],
                            new Pen(Color.Red, 1));
                    break;
                case SlantedTextAlignment.BelowRotatedOutside:
                case SlantedTextAlignment.AboveRotatedInside:
                case SlantedTextAlignment.CenterOutsideInside:
                    if (angle >= 0)
    
                        // Draw the polygon.
                        g.DrawPolygon([
                            new PointF(x, y - dy),
                            new PointF(x + 200, y),
                            new PointF(x + 200, y + 160),
                            new PointF(x, y - dy + 160)],
                            new Pen(Color.Red, 1));
                    else
    
                        // Draw the polygon.
                        g.DrawPolygon([
                            new PointF(x, y),
                            new PointF(x + 200, y + dy),
                            new PointF(x + 200, y + dy + 160),
                            new PointF(x, y + 160)],
                            new Pen(Color.Red, 1));
                    break;
            }
        }
        
        // Draw the rectangle.
        g.DrawRectangle(rect, new Pen(Color.Blue, 0.5f) { DashStyle = DashStyle.Dash });
    
        // Initialize TextLayout.
        var tl = g.CreateTextLayout();
    
        // Set text format.
        var fmt = new TextFormat
        {
            FontName = "Calibri",
            FontSize = 18,
        };
    
        // Add the text.
        tl.Append("Working of different slanted text alignments.", fmt);
    
        // Set text alignment.
        tl.TextAlignment = textAlign;
    
        // Draw text in slanted rectangle.
        g.DrawSlantedText(tl, angle, verticalStacking, rect, slantedAlign);
    
        // Draw strings with all details.
        fmt.FontSize = 12;
        g.DrawString($"angle = {angle}°", fmt, new PointF(x, yHead));
        g.DrawString($"TextAlignment = {tl.TextAlignment}", fmt, new PointF(x, yHead + 20));
        g.DrawString($"alignment = {slantedAlign}", fmt, new PointF(x, yHead + 40));
        g.DrawString($"verticalStacking = {verticalStacking}", fmt, new PointF(x, yHead + 60));
    }