Jump to content

Arc Text (May 13, 2022)


Recommended Posts

Draws text along an arc

 

Screenshot-ArcText.thumb.png.95129559871ca56b8d05eada63ffafc7.png

 

This is basically dpy's Circle Text plugin with a different UI and better math for proportional fonts

Also in Effects > Text Formations

 

Versions:

1.0(20220418) - Initial Release

1.1(20220420) - Now works with selection and slightly shorter UI

1.2(20220421) - Update code to make it compatible with CodeLab v6.1 (and below?). Also, detects if user canceled.

1.3(20220428) - Now works faster if there are multiple selections

1.4(20220506) - Fix space character not rendering when Character Spacing is zero and slightly shorter UI

1.5(20220513) - Code Update and slightly shorter UI

 

CodeLab Code

License: LPGL-3.0

 

Spoiler
// Name: Arc Text
// Submenu: Text Formations
// Author: Louie Velarde
// Title: Arc Text
// Version: 1.5
// Desc: Draws text along an arc
// Keywords: arc text|circle text|circular text
// URL: https://forums.getpaint.net/topic/119904-arc-text/
// Help: https://forums.getpaint.net/topic/119904-arc-text/
// Force Single Render Call
#region UICode
TextboxControl text = ""; // [3600]
IntSliderControl repeat = 1; // [1,360] Repeat
FontFamily fontFamily = new FontFamily("Arial"); // 
IntSliderControl fontSize = 12; // [8,288] 
CheckboxControl bold = false; // Bold
PanSliderControl center = Pair.Create(0.000, 0.000); // Center
ListBoxControl alignment = 0; // |Start Position|Center Position|End Position
AngleControl position = 135; // [0,360] 
CheckboxControl clockwise = true; // Clockwise
CheckboxControl useAngle = true; // Calculate character spacing based on arc angle
CheckboxControl endSpace = false; // Append space after last character
IntSliderControl charSpacing = 0; // [0,100] {!useAngle} Character Spacing
IntSliderControl angle = 90; // [0,360] {useAngle} Arc Angle
IntSliderControl radius = 150; // [1,1000] Arc Radius
#endregion

bool rendered;

void PreRender(Surface dst, Surface src)
{
    rendered = false;
}

void Render(Surface dst, Surface src, Rectangle rect)
{
    if (rendered) return;
    rendered = true;

    rect = EnvironmentParameters.SelectionBounds;
    dst.CopySurface(src, rect.Location, rect);

    if (text == string.Empty) return;
    
    StringBuilder line = new StringBuilder(text);
    for (int i = 2; i <= repeat; ++i)
    {
        if (IsCancelRequested) return;
        line.Append(text);
    }
    using (Graphics g = new RenderArgs(dst).Graphics)
    using (Region gClipRegion = new Region(rect))
    using (Font font = new Font(fontFamily, fontSize, bold ? FontStyle.Bold : FontStyle.Regular))
    using (Brush brush = new SolidBrush(EnvironmentParameters.PrimaryColor))
    {
        g.Clip = gClipRegion;
        g.SmoothingMode = SmoothingMode.AntiAlias;
        g.TextRenderingHint = TextRenderingHint.AntiAlias;

        double translateX = rect.Left + (center.First + 1) / 2 * rect.Width;
        double translateY = rect.Top + (center.Second + 1) / 2 * rect.Height;
        g.TranslateTransform((float) translateX, (float) translateY);

        StringFormat format = new StringFormat(StringFormat.GenericTypographic);
        format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
        format.FormatFlags |= StringFormatFlags.NoFontFallback;

        SizeF[] sizes = new SizeF[line.Length];
        double totalWidths = 0;
        double totalHeights = 0;

        for (int i = 0; i < line.Length; ++i)
        {
            if (IsCancelRequested) return;
            sizes[i] = g.MeasureString(line[i].ToString(), font, short.MaxValue, format);
            totalWidths += sizes[i].Width;
            totalHeights += sizes[i].Height;
        }
        double height = totalHeights / line.Length;

        double arcLength;
        if (useAngle)
        {
            arcLength = Math.PI * radius * angle / 180;
        }
        else
        {
            arcLength = totalWidths + charSpacing * (line.Length - 1);
            if (endSpace) arcLength += charSpacing;
        }
        double arcAngle = arcLength * 180 / Math.PI / radius;
        double spaceLength = (arcLength - totalWidths) / (line.Length - (endSpace ? 0 : 1));
        double spaceAngle = spaceLength * 180 / Math.PI / radius;

        int s = clockwise ? 1 : -1;

        switch (alignment)
        {
            case 0: g.RotateTransform((float) (s * 90 - position)); break;
            case 1: g.RotateTransform((float) (s * 90 - position - s * arcAngle / 2)); break;
            case 2: g.RotateTransform((float) (s * 90 - position - s * arcAngle)); break;
        }
        double halfCharAngle = sizes[0].Width * s * 90 / Math.PI / radius;
        g.RotateTransform((float) (halfCharAngle));

        float y = (float) (clockwise ? -radius : radius - height);
        g.DrawString(line[0].ToString(), font, brush, sizes[0].Width / -2, y, format);

        for (int i = 1; i < line.Length; ++i)
        {
            if (IsCancelRequested) return;
            g.RotateTransform((float) (halfCharAngle + s * spaceAngle));
            halfCharAngle = sizes[i].Width * s * 90 / Math.PI / radius;
            g.RotateTransform((float) (halfCharAngle));
            g.DrawString(line[i].ToString(), font, brush, sizes[i].Width / -2, y, format);
        }
    }
}

 

 

ArcText.zip

 

Edited by VeLC
Version 1.5
  • Like 5
  • Upvote 3
Link to comment
Share on other sites

Thanks! Question though. I see that in your ArcText.zip file the velc.ArcText.dll has file size 15872 and the install batch file has size 2842.

 

I copied your code and placed in CodeLab and built the effect to ArcText.zip (on my desktop) and see the file sizes have changed to ArcText.dll == 15360 and the install batch file to 2832.

 

Is there any reason? Is it due to .NET call differences? (version 6.0.3)??

 

Just asking. Works though. 👍

 

edit: figured the batch file sizes (velc.)

Edited by Panchdara
Link to comment
Share on other sites

11 hours ago, Panchdara said:

I copied your code and placed in CodeLab and built the effect to ArcText.zip (on my desktop) and see the file sizes have changed to ArcText.dll == 15360

 

Probably the lack of window icon causes a smaller file.

Link to comment
Share on other sites

  • VeLC changed the title to Arc Text (Apr 20, 2022)

If Repeat>1 the text disappears.

I used another variable (txt) to make it work. (CodeLab v6.1)

 

StringBuilder sb = new StringBuilder(text);
    for (int i = 2; i <= repeat; ++i)
    {
        sb.Append(text);
    }
string txt = sb.ToString();

 

Link to comment
Share on other sites

  • VeLC changed the title to Arc Text (Apr 21, 2022)
  • VeLC changed the title to Arc Text (Apr 28, 2022)
  • VeLC changed the title to Arc Text (May 6, 2022)
  • VeLC changed the title to Arc Text (May 13, 2022)

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...