Text 형태를 멋지게 표현한 소스가 있어서 올려 놓는다
인터넷에서 검색한 소스인데 나중에 쉽게 찾기 위해 내블로그에 올려 놓는다.
I was fascinated by the outline text. I searched on the web for an outline text library which allows me to do outline text. Sadly I found none. Those that I found, are too difficult for me to retrofit to my general purpose and I do not fully understand their sparsely commented codes. I decided to roll up my sleeves to write my own outline text library. In my previous article, How to Use a Font Without Installing it, a reader, knoami, commented and requested about using C# to do the same thing. Now this time taking C# users into account, every C++ code example in this article is accompanied by a C# code example. Without further ado, let us begin now!
Initializing and Uninitializing GDI+
Gdiplus::GdiplusStartupInput m_gdiplusStartupInput;
CTestOutlineTextApp::CTestOutlineTextApp()
Gdiplus::GdiplusStartup(&m_gdiplusToken, &m_gdiplusStartupInput, NULL);
CTestOutlineTextApp::~CTestOutlineTextApp()
Gdiplus::GdiplusShutdown(m_gdiplusToken);
Drawing Single Outline Text with Generic GDI+
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial");
wchar_t pszbuf[] = L"Text Designer";
path.AddString(pszbuf, wcslen(pszbuf), &fontFamily,
FontStyleRegular, 48, Gdiplus::Point(10,10), &strformat );
graphics.DrawPath(&pen, &path);
SolidBrush brush(Color(128,0,255));
graphics.FillPath(&brush, &path);
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
SolidBrush brushWhite = new SolidBrush(Color.White);
e.Graphics.FillRectangle(brushWhite, 0, 0,
this.ClientSize.Width, this.ClientSize.Height);
FontFamily fontFamily = new FontFamily("Arial");
StringFormat strformat = new StringFormat();
string szbuf = "Text Designer";
GraphicsPath path = new GraphicsPath();
path.AddString(szbuf, fontFamily,
(int)FontStyle.Regular, 48.0f, new Point(10, 10), strformat);
Pen pen = new Pen(Color.FromArgb(234, 137, 6), 6);
e.Graphics.DrawPath(pen, path);
SolidBrush brush = new SolidBrush(Color.FromArgb(128, 0, 255));
e.Graphics.FillPath(brush, path);
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial");
path.AddString(pszbuf, wcslen(pszbuf), &fontFamily,
FontStyleRegular, 48, Gdiplus::Point(10,10), &strformat );
graphics.DrawPath(&pen, &path);
SolidBrush brush(Color(128,0,255));
graphics.FillPath(&brush, &path);
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
SolidBrush brushWhite = new SolidBrush(Color.White);
e.Graphics.FillRectangle(brushWhite, 0, 0,
this.ClientSize.Width, this.ClientSize.Height);
FontFamily fontFamily = new FontFamily("Arial");
StringFormat strformat = new StringFormat();
GraphicsPath path = new GraphicsPath();
path.AddString(szbuf, fontFamily,
(int)FontStyle.Regular, 48.0f, new Point(10, 10), strformat);
Pen pen = new Pen(Color.FromArgb(234, 137, 6), 6);
e.Graphics.DrawPath(pen, path);
SolidBrush brush = new SolidBrush(Color.FromArgb(128, 0, 255));
e.Graphics.FillPath(brush, path);
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial");
path.AddString(pszbuf, wcslen(pszbuf), &fontFamily,
FontStyleRegular, 48, Gdiplus::Point(10,10), &strformat );
pen.SetLineJoin(LineJoinRound);
graphics.DrawPath(&pen, &path);
SolidBrush brush(Color(128,0,255));
graphics.FillPath(&brush, &path);
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
SolidBrush brushWhite = new SolidBrush(Color.White);
e.Graphics.FillRectangle(brushWhite, 0, 0,
this.ClientSize.Width, this.ClientSize.Height);
FontFamily fontFamily = new FontFamily("Arial");
StringFormat strformat = new StringFormat();
GraphicsPath path = new GraphicsPath();
path.AddString(szbuf, fontFamily,
(int)FontStyle.Regular, 48.0f, new Point(10, 10), strformat);
Pen pen = new Pen(Color.FromArgb(234, 137, 6), 6);
pen.LineJoin = LineJoin.Round;
e.Graphics.DrawPath(pen, path);
SolidBrush brush = new SolidBrush(Color.FromArgb(128, 0, 255));
e.Graphics.FillPath(brush, path);
Drawing Single Outline Text with Gradient Color
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial");
wchar_t pszbuf[] = L"Text Designer";
path.AddString(pszbuf, wcslen(pszbuf), &fontFamily,
FontStyleBold, 48, Gdiplus::Point(10,10), &strformat );
pen.SetLineJoin(LineJoinRound);
graphics.DrawPath(&pen, &path);
LinearGradientBrush brush(Gdiplus::Rect(10, 10, 30, 60),
Color(132,200,251), Color(0,0,160), LinearGradientModeVertical);
graphics.FillPath(&brush, &path);
Below is C# example that shows how to select a gradient brush.
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
SolidBrush brushWhite = new SolidBrush(Color.White);
e.Graphics.FillRectangle(brushWhite, 0, 0,
this.ClientSize.Width, this.ClientSize.Height);
FontFamily fontFamily = new FontFamily("Arial");
StringFormat strformat = new StringFormat();
string szbuf = "Text Designer";
GraphicsPath path = new GraphicsPath();
path.AddString(szbuf, fontFamily,
(int)FontStyle.Bold, 48.0f, new Point(10, 10), strformat);
Pen pen = new Pen(Color.FromArgb( 0, 0, 160), 5);
pen.LineJoin = LineJoin.Round;
e.Graphics.DrawPath(pen, path);
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(10,10,30,70),
Color.FromArgb(0,0,160), LinearGradientMode.Vertical);
e.Graphics.FillPath(brush, path);
Drawing Double Outline Text with Generic GDI+
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial");
wchar_t pszbuf[] = L"Text Designer";
path.AddString(pszbuf, wcslen(pszbuf),
&fontFamily, FontStyleRegular, 48, Gdiplus::Point(10,10), &strformat );
Pen penOut(Color(32, 117, 81), 12);
penOut.SetLineJoin(LineJoinRound);
graphics.DrawPath(&penOut, &path);
pen.SetLineJoin(LineJoinRound);
graphics.DrawPath(&pen, &path);
SolidBrush brush(Color(128,0,255));
graphics.FillPath(&brush, &path);
This is the equivalent C# code to draw double outline text:
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
SolidBrush brushWhite = new SolidBrush(Color.White);
e.Graphics.FillRectangle(brushWhite, 0, 0,
this.ClientSize.Width, this.ClientSize.Height);
FontFamily fontFamily = new FontFamily("Arial");
StringFormat strformat = new StringFormat();
string szbuf = "Text Designer";
GraphicsPath path = new GraphicsPath();
path.AddString(szbuf, fontFamily,
(int)FontStyle.Regular, 48.0f, new Point(10, 10), strformat);
Pen penOut = new Pen(Color.FromArgb(32, 117, 81), 12);
penOut.LineJoin = LineJoin.Round;
e.Graphics.DrawPath(penOut, path);
Pen pen = new Pen(Color.FromArgb(234, 137, 6), 6);
pen.LineJoin = LineJoin.Round;
e.Graphics.DrawPath(pen, path);
SolidBrush brush = new SolidBrush(Color.FromArgb(128, 0, 255));
e.Graphics.FillPath(brush, path);
Drawing Text Glow with Generic GDI+
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial");
wchar_t pszbuf[] = L"Text Designer";
path.AddString(pszbuf, wcslen(pszbuf), &fontFamily,
FontStyleRegular, 48, Gdiplus::Point(10,10), &strformat );
Pen pen(Color(32, 0, 128, 192), i);
pen.SetLineJoin(LineJoinRound);
graphics.DrawPath(&pen, &path);
SolidBrush brush(Color(255,255,255));
graphics.FillPath(&brush, &path);
This is the equivalent C# code to draw text glow:
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
SolidBrush brushWhite = new SolidBrush(Color.White);
e.Graphics.FillRectangle(brushWhite, 0, 0,
this.ClientSize.Width, this.ClientSize.Height);
FontFamily fontFamily = new FontFamily("Arial");
StringFormat strformat = new StringFormat();
string szbuf = "Text Designer";
GraphicsPath path = new GraphicsPath();
path.AddString(szbuf, fontFamily,
(int)FontStyle.Regular, 48.0f, new Point(10, 10), strformat);
Pen pen = new Pen(Color.FromArgb(32, 0, 128, 192), i);
pen.LineJoin = LineJoin.Round;
e.Graphics.DrawPath(pen, path);
SolidBrush brush = new SolidBrush(Color.FromArgb(255, 255, 255));
e.Graphics.FillPath(brush, path);
Before you rush to make your own outline library, I have to tell you one pitfall of GDI+. GDI+ cannot handle Postscript OpenType fonts; GDI+ can only handle TrueType fonts. I have searched for a solution and found Sjaak Priester's Make GDI+ Less Finicky About Fonts. His approach is to parse the font file for its glyphs and draw its outline. Sadly, I cannot use his code as his library is using the restrictive GNU license as I want to make my code free for all to use. Note: This is the reason why Winform developers use the TextRenderer class, to display the text, not GDI+ classes. I racked my brains for a solution. Since GDI (not GDI+) can display Postscript OpenType fonts and GDI supports path extraction through BeginPath/EndPath/GetPath, I decided to use just that to get my path into GDI+. Below is the comparison of the GDI+ path and GDI path. Note: Both are rendered by GDI+, it is just that their path extraction is different; one is using GDI+ while the other is using GDI to get the text path.
The top one is using GDI+ path and the bottom one is using GDI path. Looks like GDI path text is bigger and a bit inaccurate (not obvious here because it depends on the font). (Note: I realised that if you use Graphics::DrawString to draw the text, they are roughly the same size as the GDI path text; it is the GDI+ path text which is smaller!) However, GDI paths can do rotated italic text trick, like below, which GDI+ cannot do because GDI GraphicsPaths AddString takes in a FontFamily object, not a Font object. My OutlineText class provides the GdiDrawString method if you have the need to use PostScript OpenType fonts. The effect below is a Franklin Gothic Demi font, size 36, Italic text rotated 10 degrees anti-clockwise.
Drawing Outline Text using DirectWrite
As you all know, Direct2D and DirectWrite are the next graphics and text APIs for Vista and Windows 7. I have emailed Tom Mulcahy (Microsoft's developer of Direct2D for Windows 7). Below is Tom Mulcahy's email reply to me.
(Courtesy of Tom Mulcahy) The way to do this is to get the text contents as an ID2D1GeometrySink (See IDwriteFontFace::GetGlyphRunOutline). You can then call ID2D1RenderTarget::DrawGeometry to draw the outline of the text (specifying any color and width you want). Next call ID2D1RenderTarget::FillGeometry to fill the text (again you can specify any color you want).
Note: Text Designer Outline Text Library which is mentioned in the latter part of the article, will be updated with DirectWrite when Windows 7 is out.
Drawing Single Outline using OutlineText
#include "TextDesigner/OutlineText.h"
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial Black");
wchar_t pszbuf[] = L"Text Designer";
text.TextOutline(Color(255,128,64),Color(200,0,0),8);
text.SetShadowBkgd(Color(255,255,0),rect.Width(),rect.Height());
text.Shadow(Color(128,0,0,0), 4, Point(4,8));
text.DrawString(&graphics,&fontFamily,FontStyleItalic,
48, pszbuf, Gdiplus::Point(10,10), &strformat);
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
FontFamily fontFamily = new FontFamily("Arial Black");
StringFormat strformat = new StringFormat();
string szbuf = "Text Designer";
OutlineText text = new OutlineText();
text.TextOutline(Color.FromArgb(255, 128, 64), Color.FromArgb(200, 0, 0), 8);
text.SetShadowBkgd(Color.FromArgb(255, 255, 0), this.Size.Width, this.Size.Height);
text.Shadow(Color.FromArgb(128, 0, 0, 0), 4, new Point(4, 8));
text.DrawString(e.Graphics, fontFamily,
FontStyle.Italic, 48, szbuf, new Point(10, 10), strformat);
Drawing Single Outline Text with Gradient Color using OutlineText
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial Black");
wchar_t pszbuf[] = L"Text Designer";
text.SetShadowBkgd(Color(255,255,0),rect.Width(),rect.Height());
text.Shadow(Color(128,0,0,0), 4, Point(4,8));
text.TextOutline(Color(0,0,0), Color(0,0,160),5);
LinearGradientBrush brush(Gdiplus::Rect(10, 10, fDestWidth, fDestHeight),
Color(132,200,251), Color(0,0,160), LinearGradientModeVertical);
text.TextOutline(&brush, Color(0,0,160),5);
text.DrawString(&graphics,&fontFamily,FontStyleItalic,
48, pszbuf, Gdiplus::Point(10,10), &strformat);
Below is a C# example that shows how to select a gradient brush with OutlineText.
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
OutlineText outlineText = new OutlineText();
Color.FromArgb(255, 128, 192),
Color.FromArgb(255, 0, 0, 160),
outlineText.EnableShadow(true);
//Rem to SetNullShadow() to release memory if a previous shadow has been set.
outlineText.Shadow(Color.FromArgb(128, 0, 0, 0), 4, new Point(4, 8));
Color m_clrBkgd = Color.FromArgb(255, 255, 255);
outlineText.SetShadowBkgd(m_clrBkgd, this.ClientSize.Width, this.ClientSize.Height);
FontFamily fontFamily = new FontFamily("Arial Black");
StringFormat strFormat = new StringFormat();
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(10, 10,
(int)fDestWidth, (int)fDestHeight),
Color.FromArgb(132,200,251), Color.FromArgb(0,0,160),
System.Drawing.Drawing2D.LinearGradientMode.Vertical);
Color.FromArgb(255, 0, 0, 160),
outlineText.DrawString(e.Graphics, fontFamily,
FontStyle.Italic, 48, "Text Designer",
new Point(10, 10), strFormat);
Drawing Double Outline using OutlineText
#include "TextDesigner/OutlineText.h"
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial Black");
wchar_t pszbuf[] = L"Text Designer";
text.TextDblOutline(Color(255,255,255),Color(0,128,128),Color(0,255,0),4,4);
text.SetShadowBkgd(Color(255,128,192),rect.Width(),rect.Height());
text.Shadow(Color(128,0,0,0), 4, Point(4,8));
text.DrawString(&graphics,&fontFamily,FontStyleRegular,
48, pszbuf, Gdiplus::Point(10,10), &strformat);
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
FontFamily fontFamily = new FontFamily("Arial Black");
StringFormat strformat = new StringFormat();
string szbuf = "Text Designer";
OutlineText text = new OutlineText();
text.TextDblOutline(Color.FromArgb(255, 255, 255),
Color.FromArgb(0, 128, 128), Color.FromArgb(0, 255, 0), 4, 4);
text.SetShadowBkgd(Color.FromArgb(255, 128, 192), this.Size.Width, this.Size.Height);
text.Shadow(Color.FromArgb(128, 0, 0, 0), 4, new Point(4, 8));
text.DrawString(e.Graphics, fontFamily,
FontStyle.Bold, 48, szbuf, new Point(10, 10), strformat);
These are the settings to display the double outline text:
Drawing Text Glow using OutlineText
#include "TextDesigner/OutlineText.h"
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
FontFamily fontFamily(L"Arial Black");
wchar_t pszbuf[] = L"Text Designer";
text.TextGlow(Color(191,255,255),Color(24,0,128,128),14);
text.DrawString(&graphics,&fontFamily,FontStyleRegular,
48, pszbuf, Gdiplus::Point(10,10), &strformat);
This is the similar C# code to display the text glow using the TextGlow and DrawString methods:
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
FontFamily fontFamily = new FontFamily("Arial Black");
StringFormat strformat = new StringFormat();
string szbuf = "Text Designer";
OutlineText text = new OutlineText();
text.TextGlow(Color.FromArgb(191, 255, 255), Color.FromArgb(24, 0, 128, 128), 14);
text.DrawString(e.Graphics, fontFamily, FontStyle.Bold,
48, szbuf, new Point(10, 10), strformat);
These are the settings to display the text glow:
This is text glow with shadow if you are curious:
#include "../TextDesigner/PngOutlineText.h"
Gdiplus::Bitmap m_bitmap(420,100,PixelFormat32bppARGB);
BOOL CScratchPadDlg::OnInitDialog()
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
PngOutlineText pngOutlineText;
DrawDiagonal(graphics, pngOutlineText, 6);
DrawActualText(graphics, pngOutlineText);
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
// Fill background with white colour.
SolidBrush brushWhite(Color(255,255,255));
graphics.FillRectangle(&brushWhite, 0, 0, rect.Width(), rect.Height());
graphics.DrawImage(&m_bitmap, 10, 10, m_bitmap.GetWidth(), m_bitmap.GetHeight());
void CScratchPadDlg::DrawDiagonal(Gdiplus::Graphics& graphics,
PngOutlineText& pngOutlineText, int nDiagonal)
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
pngOutlineText.EnableShadow(false);
FontFamily fontFamily(L"Arial Black");
Bitmap* pPngImage = new Gdiplus::Bitmap(m_bitmap.GetWidth(),
m_bitmap.GetHeight(),PixelFormat32bppARGB);
pngOutlineText.SetPngImage(pPngImage);
pngOutlineText.DrawString(&graphics,&fontFamily,
FontStyleRegular, 48, L"Text Designer",
Gdiplus::Point(10,10), &strFormat);
for(int i=0; i<nDiagonal; ++i)
graphics.DrawImage(pPngImage, i, i, pPngImage->GetWidth(),
void CScratchPadDlg::DrawActualText(Gdiplus::Graphics& graphics,
PngOutlineText& pngOutlineText)
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
pngOutlineText.EnableShadow(false);
FontFamily fontFamily(L"Arial Black");
Bitmap* pPngImage = new Gdiplus::Bitmap(m_bitmap.GetWidth(),
m_bitmap.GetHeight(),PixelFormat32bppARGB);
pngOutlineText.SetPngImage(pPngImage);
pngOutlineText.DrawString(&graphics,&fontFamily,
FontStyleRegular, 48, L"Text Designer",
Gdiplus::Point(10,10), &strFormat);
graphics.DrawImage(pPngImage, 0, 0, pPngImage->GetWidth(), pPngImage->GetHeight());
#include "TextDesigner/OutlineText.h"
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
m_OutlineText.EnableShadow(true);
//Rem to SetNullShadow() to release memory if a previous shadow has been set.
m_OutlineText.SetNullShadow();
Color m_clrBkgd(255, 255, 255);
m_OutlineText.SetShadowBkgd(m_clrBkgd,rect.Width(),rect.Height());
FontFamily fontFamily(L"Arial Black");
m_OutlineText.DrawString(&graphics,&fontFamily,
FontStyleRegular, 48, L"Text Designer",
Gdiplus::Point(10, 10), &strFormat);
Here is the equivalent C# code to call Extrude achieve 3D extruded text.
private void OnPaint(object sender, PaintEventArgs e)
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
OutlineText outlineText = new OutlineText();
Color.FromArgb(255, 128, 192),
Color.FromArgb(255, 128, 0, 0),
outlineText.EnableShadow(true);
//Rem to SetNullShadow() to release memory if a previous shadow has been set.
Color.FromArgb(255, 128, 0, 0),
Color m_clrBkgd = Color.FromArgb(255, 255, 255);
outlineText.SetShadowBkgd(m_clrBkgd, this.ClientSize.Width, this.ClientSize.Height);
FontFamily fontFamily = new FontFamily("Arial Black");
StringFormat strFormat = new StringFormat();
outlineText.DrawString(e.Graphics, fontFamily,
FontStyle.Regular, 48, "Text Designer",
new Point(10, 10), strFormat);
#include "TextDesigner/OutlineText.h"
void CScratchPadDlg::OnPaint()
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
wchar_t pszbuf[] = L"Text Designer";
memset(&logfont, 0, sizeof(logfont));
wcscpy_s(logfont.lfFaceName, L"Arial Black");
logfont.lfHeight = -MulDiv(48, dc.GetDeviceCaps(LOGPIXELSY), 72);
text.TextOutline(Color(64,193,255),Color(0,0,0),8);
text.SetShadowBkgd(Color(255,255,255),rect.Width(),rect.Height());
text.Shadow(Color(128,0,0,0), 8, Point(4,4));
text.GdiDrawString(&graphics, &logfont, pszbuf, Gdiplus::Point(10,100));
These are the settings to display the rotated text:
Diffused Shadow and Sample Code
I have written a PngOutlineText class which renders the text and shadow to a Bitmap object with an alpha channel (PixelFormat32bppARGB format), so that you need not re-generate the text whenever you need to render the text again because outline text generation typically takes a long time, especially for text with shadow. Using PngOutlineText, you must call the SetPngImage method to set the PixelFormat32bppARGB format image for the PngOutlineText to render to. After the first DrawString or GdiDrawString, you need just to blit this image to your graphics object, instead of generating the same outline text through DrawString or GdiDrawString again. I create PngOutlineText class for use in video rendering which is typically about 30fps or 60fps. If you use a big image background in the TestOutlineText application, you will find resizing the application and scrolling the image is not smooth. If you check "Enable PNG Rendering" checkbox (See the highlighted red rectangle below), resizing and scrolling becomes smooth because the TestOutlineText application detects if the settings have not been modified, it will just blit the transparent text image instead. You can use the SavePngImage method to save the image to PNG image. If you open the image in any image editor, like Paint.Net or Adobe Photoshop, you will see the checkered boxes which is the transparent part of the PNG image.
Version 2 Preview 6 has added GDI path to C# library. Below is the C++ and C# code using GDI (instead of GDI+) to do the gradient text. The sample code is put here because the auto C# code generation for GDI is not correct.
Hide Shrink Copy Code
void CScratchPadDlg::OnPaint()
{
//CDialog::OnPaint();
using namespace Gdiplus;
using namespace TextDesigner;
CPaintDC dc(this);
Graphics graphics(dc.GetSafeHdc());
graphics.SetSmoothingMode(SmoothingModeAntiAlias);
graphics.SetInterpolationMode(InterpolationModeHighQualityBicubic);
OutlineText m_OutlineText;
m_OutlineText.TextGradOutline(
Color(255,128,64),
Color(255,64,0,64),
Color(255,255,128,255),
10);
m_OutlineText.EnableShadow(true);
//Rem to SetNullShadow() to release memory if a previous shadow has been set.
m_OutlineText.SetNullShadow();
m_OutlineText.Shadow(
Gdiplus::Color(128,0,0,0), 8,
Gdiplus::Point(4,4));
FontFamily fontFamily(L"Arial Black");
StringFormat strFormat;
float fStartX = 0.0f;
float fStartY = 0.0f;
float fDestWidth = 0.0f;
float fDestHeight = 0.0f;
m_OutlineText.MeasureString(
&graphics,
&fontFamily,
FontStyleRegular,
48,
L"TEXT DESIGNER",
Gdiplus::Point(10, 10),
&strFormat,
&fStartX,
&fStartY,
&fDestWidth,
&fDestHeight);
CRect rect;
this->GetClientRect(&rect);
Color m_clrBkgd(255, 255, 255);
m_OutlineText.SetShadowBkgd(m_clrBkgd,fDestWidth,fDestHeight);
FontFamily fontFamily(L"Arial Black");
StringFormat strFormat;
LinearGradientBrush gradientBrush(Gdiplus::Rect(fStartX, fStartY, fDestWidth-(fStartX-10), fDestHeight-(fStartY-10)),
Color(255, 128, 64), Color(255, 0, 0), LinearGradientModeVertical );
m_OutlineText.TextGradOutline(
&gradientBrush,
Color(255,64,0,64),
Color(255,255,128,255),
10);
m_OutlineText.DrawString(&graphics,&fontFamily,
FontStyleRegular, 48, L"TEXT DESIGNER",
Gdiplus::Point(10, 10), &strFormat);
}
Here follows the C# code.
Hide Shrink Copy Code
private void OnPaint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
//Drawing the back ground color
Color m_clrBkgd = Color.FromArgb(255, 255, 255);
SolidBrush brushBkgnd = new SolidBrush(m_clrBkgd);
e.Graphics.FillRectangle(brushBkgnd, 0, 0, this.ClientSize.Width, this.ClientSize.Width);
PngOutlineText m_PngOutlineText = new PngOutlineText();
m_PngOutlineText.SetPngImage(new Bitmap(ClientSize.Width, ClientSize.Height));
m_PngOutlineText.TextGradOutline(
Color.FromArgb(255, 128, 64),
Color.FromArgb(255, 64, 0, 64),
Color.FromArgb(255, 255, 128, 255),
10);
m_PngOutlineText.EnableReflection(false);
m_PngOutlineText.EnableShadow(true);
//Rem to SetNullShadow() to release memory if a previous shadow has been set.
m_PngOutlineText.SetNullShadow();
m_PngOutlineText.Shadow(
Color.FromArgb(128, 0, 0, 0), 8,
new Point(4, 4));
LOGFONT m_LogFont = new LOGFONT();
m_LogFont.lfFaceName = "Arial Black";
m_LogFont.lfHeight = -48;
m_LogFont.lfOrientation = 0;
m_LogFont.lfEscapement = 0;
m_LogFont.lfItalic = false;
float fStartX = 0.0f;
float fStartY = 0.0f;
float fDestWidth = 0.0f;
float fDestHeight = 0.0f;
m_PngOutlineText.GdiMeasureString(
e.Graphics,
m_LogFont,
"TEXT DESIGNER",
new Point(10, 10),
ref fStartX,
ref fStartY,
ref fDestWidth,
ref fDestHeight);
m_PngOutlineText.SetShadowBkgd(m_clrBkgd, (int)fDestWidth+10, (int)fDestHeight+10);
LinearGradientBrush gradientBrush = new LinearGradientBrush(new RectangleF(fStartX, fStartY, fDestWidth - (fStartX - 10), fDestHeight - (fStartY - 10)),
Color.FromArgb(255, 128, 64), Color.FromArgb(255, 0, 0), LinearGradientMode.Vertical);
m_PngOutlineText.TextGradOutline(
gradientBrush,
Color.FromArgb(255, 64, 0, 64),
Color.FromArgb(255, 255, 128, 255),
10);
m_PngOutlineText.GdiDrawString(
e.Graphics,
m_LogFont,
"TEXT DESIGNER",
new Point(10, 10));
e.Graphics.DrawImage(m_PngOutlineText.GetPngImage(), new Point(0, 0));
brushBkgnd.Dispose();
e.Graphics.Dispose();
}
MeasureString and GdiMeasureString
m_PngOutlineText.MeasureString(&graphics,&fontFamily,FontStyleBold,
72, m_szText, Gdiplus::Point(0,0), &strFormat,
m_pPngImage = new Bitmap(fWidth+5.0f, fHeight+5.0f, PixelFormat32bppARGB);
m_PngOutlineText.SetPngImage(m_pPngImage);
m_PngOutlineText.SetNullShadow();
m_PngOutlineText.SetShadowBkgd(
Gdiplus::Color(GetRValue(m_clrBkgd),GetGValue(m_clrBkgd),GetBValue(m_clrBkgd)),
m_pPngImage->GetWidth(), m_pPngImage->GetHeight());
&graphics,&fontFamily,fontStyle,m_nFontSize,
m_szText,Gdiplus::Point(0,0), &strFormat);
graphics.DrawImage(m_pPngImage, (float)m_nTextPosX, (float)m_nTextPosY,
(float)m_pPngImage->GetWidth(), (float)m_pPngImage->GetHeight());
nShadowOffsetX = -m_nShadowOffsetX;
nShadowOffsetY = -m_nShadowOffsetY;
m_PngOutlineText.DrawString(&graphics,&fontFamily,
fontStyle,m_nFontSize,m_szText,Gdiplus::Point
(nShadowOffsetX,nShadowOffsetY), &strFormat);
graphics.DrawImage(m_pPngImage, (float)
(m_nTextPosX-nShadowOffsetX), (float)(m_nTextPosY-nShadowOffsetY),
(float)m_pPngImage->GetWidth(), (float)m_pPngImage->GetHeight());
'개발언어 > c++' 카테고리의 다른 글
namespace (0) | 2016.07.18 |
---|---|
MS Winows 계열 의 버전 정보를 알아내는 함수 (0) | 2016.07.18 |
Use Direct3D 8 To Fly Through the Munsell Color Solid (0) | 2016.07.17 |
마우스 클릭으로 색상추출 하는 코드 (0) | 2016.07.16 |
Smooth color transition algorithm (0) | 2016.07.16 |