• 0

[C#] Drawing outline text


Question

Recommended Posts

  • 0

It's pretty easy.

From Windows Forms Programming in C# by Chris Sells

GraphicsPath GetStringPath( string s, float dpi, RectangleF rect, Font font, StringFormat format)
{
    GraphicsPath path = new GraphicsPath();
    // Convert font size into appropriate coordinates
    float emSize = dpi * font.SizeInPoints / 72;
    path.AddString(s, font.FontFamily, (int)font.Style, emSize, rect, format);

    return path;
}

void Form_Paint(object sender, PaintEventArgs e)
{
    Graphics g = e.Graphics;
    string s = "Outline";
    RectangleF rect = this.ClientRectangle;
    Font font = this.Font;
    StringFormat format = StringFormat.GenericTypographic;
    float dpi = g.DpiY;
    using( GraphicsPath = GetStringPath(s, dpi, rect, font, format) )
    {
        g.DrawPath(Pens.Black, path);
    }
}

  • 0
  yyy said:
I want it to have an inner white color and a shadow. Do you think it is possible ?

It's possible.

In the paint event.

  	Graphics g = e.Graphics;
  	string s = "Outline";
  	RectangleF rect = this.ClientRectangle;
  	Font font = this.Font;
  	StringFormat format = StringFormat.GenericTypographic;
  	float dpi = g.DpiY;
  	using( GraphicsPath path = GetStringPath(s, dpi, rect, font, format) )
  	{	
    g.SmoothingMode = SmoothingMode.AntiAlias;
    RectangleF off = rect;
    off.Offset( 5, 5 );
    using( GraphicsPath offPath = GetStringPath(s, dpi, off, font, format) )
    {
    	Brush b = new SolidBrush(Color.FromArgb(100, 0, 0, 0));
    	g.FillPath(b, offPath);
    	b.Dispose();
    }
    g.FillPath(Brushes.White, path);
    g.DrawPath(Pens.Black, path);
  	}

Edited by weenur
  • 0
  yyy said:
:laugh: Thanks a lot weenur - that's really close  :D Can I make the shadow even more smooth? Is there a way I can control the shadow width?

585273695[/snapback]

You want that with ice cream? :p

You basically want a blur on the shadow, no?

Edited by weenur
  • 0
  yyy said:
Yes - I'm really sorry that I bother you  :blush:  :rolleyes: I didn't mean to do it. I was too rude  :unsure:  it's not urgent so if you have time I'll apprreciate your answer.

585274184[/snapback]

No sweat. I'm just giving you grief. ;)

I should be able to have an example for you as soon as I get some time. I also need to figure out how to convert a region to a bitmap. <anyone?>

  • 0

I'm converting the GraphicsPath to a Region, and then from a Region to a Bitmap to perform raster operations on it. I see what Bob is doing. That's cool. The guy is a guru. I was actually going to do a gaussian blur on the shadow and make it adjustable. I'm just drawing a blank on how to make a Bitmap from a Region.

Region class

  • 0
  weenur said:
I'm converting the GraphicsPath to a Region, and then from a Region to a Bitmap to perform raster operations on it. I see what Bob is doing. That's cool. The guy is a guru. I was actually going to do a gaussian blur on the shadow and make it adjustable. I'm just drawing a blank on how to make a Bitmap from a Region.

Region class

585276170[/snapback]

Yes but a Region is simply that - a region. So to turn it into a Bitmap you need to use the region on a Bitmap e.g. Create a new Bitmap of the appropriate dimensions then use Graphics.FillRegion with a suitable Brush. Or am I missing something?

  • 0
  _Pablo said:
Yes but a Region is simply that - a region. So to turn it into a Bitmap you need to use the region on a Bitmap e.g. Create a new Bitmap of the appropriate dimensions then use Graphics.FillRegion with a suitable Brush. Or am I missing something?

585276240[/snapback]

See... that's what I couldn't remember. :D Thanks. It's been a while since I've done any GDI/+ to any extent.

  • 0
  weenur said:
See... that's what I couldn't remember. :D Thanks. It's been a while since I've done any GDI/+ to any extent.

585276814[/snapback]

Funny...you virtually answered your own question with your previous post when you said "I'm just drawing a blank on how to make a Bitmap from a Region."! :p

  • 0
  _Pablo said:
Funny...you virtually answered your own question with your previous post when you said "I'm just drawing a blank on how to make a Bitmap from a Region."!  :p

585276872[/snapback]

lmao! I didn't even catch that. I've been staying up too late playing World of Warcraft. :)

  • 0

OK, yyy. If this doesn't do it for you, use Bob Powell's version. You can, of course, modify it to your liking, and set it up to be configurable.

First, add the Filters.cs file to your project. ( get it here )

<edit> you should dispose of the Regions when you're done, as well as the Bitmap.

// In the paint handler
  	Graphics g = e.Graphics;
  	string s = "Outline";
  	Font font = this.Font;
  	RectangleF rect = this.ClientRectangle;
  	StringFormat format = StringFormat.GenericTypographic;
  	float dpi = g.DpiY;
  	using( GraphicsPath path = GetStringPath(s, dpi, rect, font, format) )
  	{	
    g.SmoothingMode = SmoothingMode.AntiAlias;
    RectangleF off = rect;
    off.Offset( 2, 2 );
    Bitmap bmp = null;
    using( GraphicsPath offPath = GetStringPath(s, dpi, off, font, format) )
    {
    	bmp = new Bitmap((int)rect.Width, (int)rect.Height);
    	Graphics g2 = Graphics.FromImage(bmp);
    	g2.CompositingMode = CompositingMode.SourceOver;
    	g2.CompositingQuality = CompositingQuality.HighQuality;
    	g2.SmoothingMode = SmoothingMode.AntiAlias;
    	Brush b = new SolidBrush(Color.FromArgb(200, 0, 0, 0));
    	Region r = new Region(offPath);
    	Region rxor = new Region(rect);
    	g2.FillRegion(SystemBrushes.Control, rxor);
    	rxor.Xor(r);
    	g2.FillRegion(b, r);
    	BitmapFilter.GaussianBlur(bmp, 4);
    	BitmapFilter.GaussianBlur(bmp, 4);
    	BitmapFilter.GaussianBlur(bmp, 4);
    	BitmapFilter.GaussianBlur(bmp, 4);
    	BitmapFilter.GaussianBlur(bmp, 4);
    	b.Dispose();
    	g2.Dispose();
    }
    if( bmp != null )
    {
    	// draw the image
    	g.DrawImage(bmp, off);
    }
    g.FillPath(Brushes.White, path);
    g.DrawPath(Pens.Black, path);
  	}
  }

  • 0
  yyy said:
Thank you very very much Weenur and _Pablo  :laugh: I really appreciate yout help  :D I'lll try that later.

And weenur - sorry again for nagging you  :blush:

585278078[/snapback]

I don't consider it nagging. It's a good way to learn for both of us.

  • 0

Wow :laugh: it works great :cool:

I just have 2 questions:

1. Are you sure that this source code (and the filters.cs file) are free to use and ditrobute ? I need this code for a freeware application which I plan to distrobute freely with the source code so I need to be sure.

2. This is not so important but I was wondering if there's a way to reduce the Memory usage of that code - it raises the application's Memory usage by about 3 MB I think. It's not that bad but I just wonder.

Thanks again for helping me :)

  • 0

1. Ask the author. I'm sure that as long as you give credit where credit is due, you'll be fine. He is posting it for teaching purposes.

2. I'd have to look more closely at his code. I'm fairly certain that he's managed his memory properly. You could try doing a GC.Collect() at the end of the Paint event. I kind of doubt it'll help, but you never know. Is that memory footprint in release mode, or debug?

  • 0
  weenur said:
1. Ask the author. I'm sure that as long as you give credit where credit is due, you'll be fine. He is posting it for teaching purposes.

2. I'd have to look more closely at his code. I'm fairly certain that he's managed his memory properly. You could try doing a GC.Collect() at the end of the Paint event. I kind of doubt it'll help, but you never know. Is that memory footprint in release mode, or debug?

585281673[/snapback]

Ok, I'll ask him.

You don't need to look at the code - that's Ok. I was just wondering if there's a fast way to do it but you are right - probably the code's writer already thought of the memory issue. It isn't that bad after all. I think it is in the release mode.

  • 0
  yyy said:
I can't ask the "Windows Forms Programming in C#"  book's author - I don't have his E-mail and I don't think he'll allow me to use that code since it was written in a book. Nevermind - I'll do something else.

585285520[/snapback]

Uh... use it.

  Quote
Permission is granted to anyone to use this software for any purpose, including commercial applications, subject to the following restrictions

1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is requested, as shown here:

Portions copyright ? 2003 Chris Sells (http://www.sellsbrothers.com/).

 

2. No substantial portion of this source code may be redistributed without the express written permission of the copyright holders, where "substantial" is defined as enough code to be recognizably from this code.

  • 0
  Quote
2. No substantial portion of this source code may be redistributed without the express written permission of the copyright holders, where "substantial" is defined as enough code to be recognizably from this code.

It's pretty explicit - if you are going to distribute the source of your project and it contains a "recognisable portion" of the books sample source code, then you will need to obtain permission from Chris Sells. So just drop him a mail at csells@sellsbrothers.com - he may even give you some advice on the memory footprint.

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.