Jump to content

MadJik

Members
  • Posts

    2,690
  • Joined

  • Last visited

  • Days Won

    68

Posts posted by MadJik

  1. @xod i looked at this code and made some changes to it:

     

    Amount3 is Double for more precision

     

    (Amount4 might be an angle chooser…)

     

    Amount5 added Both

     

    (new)Amount6 to draw the circle

    (may be add the external circle…)

     

    In DrawTextOnCircle:

    Added // Calculate the Start angle to have text centered.

     

    Spoiler
    
    // Name: Circle Text 2
    // Submenu: Text Formations
    // Author: xod
    // Title:
    // Version: 1.1
    // Desc:
    // Keywords:
    // URL:
    // Help:
    
    #region UICode
    TextboxControl Amount1 = "<==  Test  top  text   ==>"; // [0,255] Top text
    TextboxControl Amount2 = "{--   Test  bottom  test   --}"; // [0,255] Bottom text
    DoubleSliderControl Amount3 = 35; // [5,100] Text size
    IntSliderControl Amount4 = 0; // [-1000,1000] Adjust position
    RadioButtonControl Amount5 = 2; // [1] Draw|Top|Bottom|Both
    CheckboxControl Amount6 = false; // [0,1] Draw the circle
    FontFamily Amount7 = new FontFamily("Arial"); // Font
    CheckboxControl Amount8 = false; // [0,1] Bold
    CheckboxControl Amount9 = false; // [0,1] Italic
    ColorWheelControl Amount10 = ColorBgra.FromBgr(0,0,0); //
    #endregion
    
    void Render(Surface dst, Surface src, Rectangle rect)
    {
        Rectangle selection = EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
    
        dst.CopySurface(src, rect.Location, rect);
    
        using (RenderArgs ra = new RenderArgs(dst))
        {
            Graphics g = ra.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.TextRenderingHint = TextRenderingHint.AntiAlias;
            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;
            Font SelectedFont = new Font(Amount7, (float)Amount3);
            FontStyle myStyle = FontStyle.Regular;
            if (Amount8) myStyle |= FontStyle.Bold;
            if (Amount9) myStyle |= FontStyle.Italic;
    
            g.Clip = new Region(rect);
    
            using(SolidBrush sBrush = new SolidBrush(Amount10))
            {
                float font_height = (float)Amount3;
                float radius = Math.Min(selection.Width, selection.Height) / 2 - 2.5f * font_height;
                float diam = 2 * radius;
                float cx = selection.Width / 2;
                float cy = selection.Height / 2;
    
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.TextRenderingHint = TextRenderingHint.AntiAlias;
    
                // Make a font to use.
                using (Font font = new Font(SelectedFont, myStyle))
                {
                    // Draw the circle
                    if (Amount6) g.DrawEllipse(Pens.Red, cx - radius, cy - radius, diam, diam);
    
                    // Draw the text.
                    DrawTextOnCircle(g, font, sBrush, radius, cx, cy, Amount1, Amount2);
                }
            }
        }
    }
    
    private void DrawTextOnCircle(Graphics g, Font font, Brush brush, float radius, float cx, float cy, string top_text, string bottom_text)
    {
        double width_to_angle = 1 / radius;
        using (StringFormat string_format = new StringFormat())
        {
            string_format.Alignment = StringAlignment.Center;
            string_format.LineAlignment = StringAlignment.Far;
            float text_width = Amount4;
            // Used to scale from radians to degrees
            double radians_to_degrees = 180.0 / Math.PI;
    
            if ((Amount5 ==0 || Amount5 ==2) && (top_text.Length>0))
            {//Draw the top text
                List<RectangleF> rects = MeasureCharacters(g, font, top_text);
                // Find the starting angle
                double start_angle = -Math.PI / 2 - text_width / 2 * width_to_angle;
                // Calculate the Start angle to have text centered.
                for (int i = 0; i < top_text.Length; i++)
                {
                    start_angle -= rects[i].Width / 2 * width_to_angle;
                }
    
                double theta = start_angle;
                // Draw the characters.
                for (int i = 0; i < top_text.Length; i++)
                {
                    // See where this character goes
                    theta += rects[i].Width / 2 * width_to_angle;
                    double x = cx + radius * Math.Cos(theta);
                    double y = cy + radius * Math.Sin(theta);
                    // Transform to position the character
                    g.RotateTransform((float)(radians_to_degrees * (theta + Math.PI / 2)));
                    g.TranslateTransform((float)x, (float)y, MatrixOrder.Append);
                    // Draw the character.
                    g.DrawString(top_text[i].ToString(), font, brush, 0, 0, string_format);
                    g.ResetTransform();
                    // Increment theta
                    theta += rects[i].Width / 2 * width_to_angle;
                }
            }
            if ((Amount5 ==1 || Amount5 ==2) && (bottom_text.Length>0))
            {//Draw the bottom text
                List<RectangleF> rects = MeasureCharacters(g, font, bottom_text);
                // Find the starting angle
                double start_angle = Math.PI / 2 - text_width / 2 * width_to_angle;
                //Calculate the Start angle to have text centered.
                for (int i = 0; i < bottom_text.Length; i++)
                {
                    start_angle += rects[i].Width / 2 * width_to_angle;
                }
    
                double theta = start_angle;
                string_format.Alignment = StringAlignment.Center;
                string_format.LineAlignment = StringAlignment.Near;
                // Draw the characters
                for (int i = 0; i < bottom_text.Length; i++)
                {
                    // See where this character goes
                    theta -= rects[i].Width / 2 * width_to_angle;
                    double x = cx + radius * Math.Cos(theta);
                    double y = cy + radius * Math.Sin(theta);
                    // Transform to position the character
                    g.RotateTransform((float)(radians_to_degrees * (theta - Math.PI / 2)));
                    g.TranslateTransform((float)x, (float)y, MatrixOrder.Append);
                    // Draw the character
                    g.DrawString(bottom_text[i].ToString(), font, brush, 0, 0, string_format);
                    g.ResetTransform();
                    // Increment theta
                    theta -= rects[i].Width / 2 * width_to_angle;
                }
            }
        }
    }
    
    private List<RectangleF> MeasureCharacters(Graphics gr, Font font, string text)
    {
        List<RectangleF> results = new List<RectangleF>();
        // The X location for the next character
        float x = 0;
        // Get the character sizes 31 characters at a time
        for (int start = 0; start < text.Length; start += 32)
        {
            // Get the substring.
            int len = 32;
            if (start + len >= text.Length) len = text.Length - start;
            string substring = text.Substring(start, len);
            // Measure the characters.
            List<RectangleF> rects = MeasureCharactersInWord(gr, font, substring);
            // Remove lead-in for the first character
            if (start == 0) x += rects[0].Left;
            // Save all but the last rectangle
            for (int i = 0; i < rects.Count + 1 - 1; i++)
            {
                RectangleF new_rect = new RectangleF(x, rects[i].Top, rects[i].Width, rects[i].Height);
                results.Add(new_rect);
                // Move to the next character's X position
                x += rects[i].Width;
            }
        }
        return results;
    }
    
    // Measure the characters in a string with no more than 32 characters
    private List<RectangleF> MeasureCharactersInWord(Graphics g, Font font, string text)
    {
        List<RectangleF> result = new List<RectangleF>();
    
        using (StringFormat string_format = new StringFormat())
        {
            string_format.Alignment = StringAlignment.Near;
            string_format.LineAlignment = StringAlignment.Near;
            string_format.Trimming = StringTrimming.None;
            string_format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces;
    
            CharacterRange[] ranges = new CharacterRange[text.Length];
            for (int i = 0; i < text.Length; i++)
            {
                ranges[i] = new CharacterRange(i, 1);
            }
            string_format.SetMeasurableCharacterRanges(ranges);
            // Find the character ranges
            RectangleF rect = new RectangleF(0, 0, 10000, 100);
            Region[] regions = g.MeasureCharacterRanges(text, font, rect, string_format);
            // Convert the regions into rectangles
            foreach (Region region in regions) result.Add(region.GetBounds(g));
        }
        return result;
    }

     

     

    Circle_Text_V2.gif

    • Like 2
    • Upvote 3
  2. 12 hours ago, Eli said:

    I just noticed that the world as we know it has an expiration date. :D 

    The dropdown list is populated from the actual year…

    It means next year the last choice in the list will be + 1 (2033).

    edit:Perhaps a slider -100  <--- year ---> +100 would be better for a bigger range and will offer the possibility to key in the year...

    (Birth month of grandpa…)

    • Like 2
    • Upvote 1
  3. @Major Thank you.

    If you mean to have a frame outside the picture with a white gap between, like this:

    frame1.png

     

    You could draw a white frame first and another frame smaller. But they still overlay a part of the original image.

    The idea of @toe_head2001 is the only way to keep the image intact.

     

    @Eli this is an issue I added to my todo list. Thanks for the report (the only one in 10 years!)

    The frame works well with no selection (full canvas).

      

×
×
  • Create New...