Jump to content

Arc Text (May 13, 2022)


VeLC
 Share

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

  • 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)
  • 1 month later...

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...