첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
본 블로그는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 블로그 콘텐츠 향상을 위해 쓰여집니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ VerticalAlignment.cs

namespace TestProject
{
    /// <summary>
    /// 수직 정렬
    /// </summary>
    public enum VerticalAlignment
    {
        /// <summary>
        /// 상단
        /// </summary>
        Top,

        /// <summary>
        /// 중단
        /// </summary>
        Middle,

        /// <summary>
        /// 하단
        /// </summary>
        Bottom,
    }
}

 

728x90

 

▶ DrawingContextExtension.cs

using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace TestProject
{
    /// <summary>
    /// 그리기 컨텍스트 확장
    /// </summary>
    public static class DrawingContextExtension
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 문자열 그리기 - DrawString(drawingContext, text, fontName, emSize, brush, originPoint, verticalAlignment, horizontalAlignment)

        /// <summary>
        /// 문자열 그리기
        /// </summary>
        /// <param name="drawingContext">그리기 컨텍스트</param>
        /// <param name="text">텍스트</param>
        /// <param name="fontName">폰트명</param>
        /// <param name="emSize">EM 크기</param>
        /// <param name="brush">브러시</param>
        /// <param name="originPoint">원점 포인트</param>
        /// <param name="verticalAlignment">수직 정렬</param>
        /// <param name="horizontalAlignment">수평 정렬</param>
        public static void DrawString(this DrawingContext drawingContext, string text, string fontName, double emSize, Brush brush,
            Point originPoint, VerticalAlignment verticalAlignment, TextAlignment horizontalAlignment)
        {
            Typeface typeface = new Typeface(fontName);

            FormattedText formattedText = new FormattedText
            (
                text,
                CultureInfo.CurrentUICulture,
                FlowDirection.LeftToRight,
                typeface,
                emSize,
                brush
            );

            formattedText.TextAlignment = horizontalAlignment;

            if(verticalAlignment == VerticalAlignment.Middle)
            {
                originPoint.Y -= formattedText.Height / 2;
            }
            else if(verticalAlignment == VerticalAlignment.Bottom)
            {
                originPoint.Y -= formattedText.Height;
            }

            drawingContext.DrawText(formattedText, originPoint);
        }

        #endregion
        #region 문자열 그리기 - DrawString(drawingContext, text, rotateAngle, fontName, emSize, brush, originPoint, textAlignment,
            verticalAlignment, horizontalAlignment)

        /// <summary>
        /// 문자열 그리기
        /// </summary>
        /// <param name="drawingContext">그리기 컨텍스트</param>
        /// <param name="text">텍스트</param>
        /// <param name="rotateAngle">회전 각도</param>
        /// <param name="fontName">폰트명</param>
        /// <param name="emSize">EM 크기</param>
        /// <param name="brush">브러시</param>
        /// <param name="originPoint">원점 포인트</param>
        /// <param name="textAlignment">텍스트 정렬</param>
        /// <param name="verticalAlignment">수직 정렬</param>
        /// <param name="horizontalAlignment">수평 정렬</param>
        public static void DrawString(this DrawingContext drawingContext, string text, double rotateAngle, string fontName, double emSize,
            Brush brush, Point originPoint, TextAlignment textAlignment, VerticalAlignment verticalAlignment, TextAlignment horizontalAlignment)
        {
            Typeface typeface = new Typeface(fontName);

            FormattedText formattedText = new FormattedText
            (
                text,
                CultureInfo.CurrentUICulture,
                FlowDirection.LeftToRight,
                typeface,
                emSize,
                brush
            );

            formattedText.TextAlignment = textAlignment;

            double width  = formattedText.Width - formattedText.OverhangLeading;
            double height = formattedText.Height;

            TranslateTransform translateTransform1 = new TranslateTransform();

            translateTransform1.Y = -height / 2;

            if((textAlignment == TextAlignment.Left) || (textAlignment == TextAlignment.Justify))
            {
                translateTransform1.X = -width / 2;
            }
            else if(textAlignment == TextAlignment.Right)
            {
                translateTransform1.X = width / 2;
            }
            else
            {
                translateTransform1.X = 0;
            }

            RotateTransform rotateTransform = new RotateTransform(rotateAngle);

            Rect rectangle = new Rect(0, 0, width, height);

            if(textAlignment == TextAlignment.Center)
            {
                rectangle.X -= width / 2;
            }
            else if(textAlignment == TextAlignment.Right)
            {
                rectangle.X -= width;
            }

            Rect rotateRectangle = rotateTransform.TransformBounds(rectangle);

            TranslateTransform translateTransform2 = new TranslateTransform(originPoint.X, originPoint.Y);

            if(horizontalAlignment == TextAlignment.Left)
            {
                translateTransform2.X += rotateRectangle.Width / 2;
            }
            else if(horizontalAlignment == TextAlignment.Right)
            {
                translateTransform2.X -= rotateRectangle.Width / 2;
            }

            if(verticalAlignment == VerticalAlignment.Top)
            {
                translateTransform2.Y += rotateRectangle.Height / 2;
            }
            else if(verticalAlignment == VerticalAlignment.Bottom)
            {
                translateTransform2.Y -= rotateRectangle.Height / 2;
            }

            drawingContext.PushTransform(translateTransform2);
            drawingContext.PushTransform(rotateTransform);
            drawingContext.PushTransform(translateTransform1);

            drawingContext.DrawText(formattedText, new Point(0, 0));

            drawingContext.DrawRectangle(null, new Pen(Brushes.Red, 1), rectangle);

            drawingContext.Pop();
            drawingContext.Pop();
            drawingContext.Pop();

            Rect transformRectangle = translateTransform2.TransformBounds
            (
                rotateTransform.TransformBounds
                (
                    translateTransform1.TransformBounds(rectangle)
                )
            );

            Pen customPen = new Pen(Brushes.Blue, 1);

            customPen.DashStyle = new DashStyle(new double[] { 5, 5 }, 0);

            drawingContext.DrawRectangle(null, customPen, transformRectangle);
        }

        #endregion
        #region 다각형 그리기 - DrawPolygon(drawingContext, brush, pen, pointArray, fillRule)

        /// <summary>
        /// 다각형 그리기
        /// </summary>
        /// <param name="drawingContext">그리기 컨텍스트</param>
        /// <param name="brush">브러시</param>
        /// <param name="pen">펜</param>
        /// <param name="pointArray">포인트 배열</param>
        /// <param name="fillRule">채우기 규칙</param>
        public static void DrawPolygon(this DrawingContext drawingContext, Brush brush, Pen pen, Point[] pointArray, FillRule fillRule)
        {
            drawingContext.DrawPolygonOrPolyline(brush, pen, pointArray, fillRule, true);
        }

        #endregion
        #region 다각선 그리기 - DrawPolyline(drawingContext, brush, pen, pointArray, fillRule)

        /// <summary>
        /// 다각선 그리기
        /// </summary>
        /// <param name="drawingContext">그리기 컨텍스트</param>
        /// <param name="brush">브러시</param>
        /// <param name="pen">펜</param>
        /// <param name="pointArray">포인트 배열</param>
        /// <param name="fillRule">채우기 규칙</param>
        public static void DrawPolyline(this DrawingContext drawingContext, Brush brush, Pen pen, Point[] pointArray, FillRule fillRule)
        {
            drawingContext.DrawPolygonOrPolyline(brush, pen, pointArray, fillRule, false);
        }

        #endregion
        #region 렌더 타겟 비트맵 구하기 - GetRenderTargetBitmap(text, dpiX, dpiY, fontName, emSize, textAlignment, backgroundBrush,
            rectanglePen, textBrush, margin)

        /// <summary>
        /// 렌더 타겟 비트맵 구하기
        /// </summary>
        /// <param name="text">텍스트</param>
        /// <param name="dpiX">DPI X</param>
        /// <param name="dpiY">DPI Y</param>
        /// <param name="fontName">폰트명</param>
        /// <param name="emSize">EM 크기</param>
        /// <param name="textAlignment">텍스트 정렬</param>
        /// <param name="backgroundBrush">배경 브러시</param>
        /// <param name="rectanglePen">사각형 펜</param>
        /// <param name="textBrush">텍스트 브러시</param>
        /// <param name="margin">마진</param>
        /// <returns>렌더 타겟 비트맵</returns>
        public static RenderTargetBitmap GetRenderTargetBitmap(string text, double dpiX, double dpiY, string fontName, double emSize,
            TextAlignment textAlignment, Brush backgroundBrush, Pen rectanglePen, Brush textBrush, Thickness margin)
        {
            Typeface typeface = new Typeface(fontName);

            FormattedText formattedText = new FormattedText
            (
                text,
                CultureInfo.CurrentUICulture,
                FlowDirection.LeftToRight,
                typeface,
                emSize,
                textBrush
            );

            formattedText.TextAlignment = textAlignment;

            double width  = formattedText.Width - formattedText.OverhangLeading;
            double height = formattedText.Height;

            Point textOriginPoint = new Point(0, 0);

            if(textAlignment == TextAlignment.Center)
            {
                textOriginPoint.X = width / 2;
            }
            else if(textAlignment == TextAlignment.Right)
            {
                textOriginPoint.X = width;
            }

            if(rectanglePen != null)
            {
                width  += rectanglePen.Thickness;
                height += rectanglePen.Thickness;

                textOriginPoint.X += rectanglePen.Thickness / 2;
                textOriginPoint.Y += rectanglePen.Thickness / 2;
            }

            width  += margin.Left + margin.Right;
            height += margin.Top  + margin.Bottom;

            textOriginPoint.X += margin.Left;
            textOriginPoint.Y += margin.Top;

            int widthInteger  = (int)(width + 1);
            int heightInteger = (int)(height + 1);

            DrawingVisual  drawingVisual  = new DrawingVisual();
            DrawingContext drawingContext = drawingVisual.RenderOpen();

            drawingContext.DrawRectangle(backgroundBrush, rectanglePen, new Rect(0, 0, widthInteger, heightInteger));

            drawingContext.DrawText(formattedText, textOriginPoint);

            drawingContext.Close();

            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap
            (
                widthInteger,
                heightInteger,
                dpiX,
                dpiY,
                PixelFormats.Pbgra32
            );

            renderTargetBitmap.Render(drawingVisual);

            return renderTargetBitmap;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Private

        #region 다각형 또는 다각선 그리기 - DrawPolygonOrPolyline(drawingContext, brush, pen, pointArray, fillRule, drawPolygon)

        /// <summary>
        /// 다각형 또는 다각선 그리기
        /// </summary>
        /// <param name="drawingContext">그리기 컨텍스트</param>
        /// <param name="brush">브러시</param>
        /// <param name="pen">펜</param>
        /// <param name="pointArray">포인트 배열</param>
        /// <param name="fillRule">채우기 규칙</param>
        /// <param name="drawPolygon">다각형 그리기 여부</param>
        private static void DrawPolygonOrPolyline(this DrawingContext drawingContext, Brush brush, Pen pen, Point[] pointArray,
            FillRule fillRule, bool drawPolygon)
        {
            StreamGeometry streamGeometry = new StreamGeometry();

            streamGeometry.FillRule = fillRule;

            using(StreamGeometryContext context = streamGeometry.Open())
            {
                context.BeginFigure(pointArray[0], true, drawPolygon);

                context.PolyLineTo(pointArray.Skip(1).ToArray(), true, false);
            }

            drawingContext.DrawGeometry(brush, pen, streamGeometry);
        }

        #endregion
    }
}

 

300x250

 

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="800"
    Height="600"
    Title="RenderTargetBitmap 클래스 : 텍스트 그리기"
    Loaded="Window_Loaded">
    <Grid>
        <WrapPanel>
            <WrapPanel.Resources>
                <Style TargetType="Image">
                    <Setter Property="Stretch" Value="None" />
                    <Setter Property="Margin" Value="4" />
                </Style> 
            </WrapPanel.Resources>
            <Image Name="img1"/>
            <Image Name="img2"/>
            <Image Name="img3"/>
            <Image Name="img4"/>
            <Image Name="img5"/>
            <Image Name="img6"/>
        </WrapPanel>
    </Grid>
</Window>

 

▶ MainWindow.xaml.cs

using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 윈도우 로드시 처리하기 - Window_Loaded(sender, e)

        /// <summary>
        /// 윈도우 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            const string FONT_NAME = "Times New Roman";
            const double EM_SIZE   = 40;

            LinearGradientBrush brush = new LinearGradientBrush();

            brush.GradientStops.Add(new GradientStop(Colors.Red   , 0.0      ));
            brush.GradientStops.Add(new GradientStop(Colors.Orange, 1.0 / 6.0));
            brush.GradientStops.Add(new GradientStop(Colors.Yellow, 2.0 / 6.0));
            brush.GradientStops.Add(new GradientStop(Colors.Lime  , 3.0 / 6.0));
            brush.GradientStops.Add(new GradientStop(Colors.Blue  , 4.0 / 6.0));
            brush.GradientStops.Add(new GradientStop(Colors.Indigo, 5.0 / 6.0));
            brush.GradientStops.Add(new GradientStop(Colors.Violet, 1.0      ));

            Pen rectanglePen = new Pen(brush, 20);

            Brush backgroundBrush = new SolidColorBrush(Color.FromArgb(255, 240, 240, 240));

            RenderTargetBitmap bitmap1 = DrawingContextExtension.GetRenderTargetBitmap
            (
                "Left\nJustified",
                96,
                96,
                FONT_NAME,
                EM_SIZE,
                TextAlignment.Left,
                backgroundBrush,
                rectanglePen,
                brush,
                new Thickness(0)
            );

            image1.Source = bitmap1;

            RenderTargetBitmap bitmap2 = DrawingContextExtension.GetRenderTargetBitmap
            (
                "Center\nJustified",
                96,
                96,
                FONT_NAME,
                EM_SIZE,
                TextAlignment.Center,
                backgroundBrush,
                rectanglePen,
                brush,
                new Thickness(0)
            );

            image2.Source = bitmap2;

            RenderTargetBitmap bitmap3 = DrawingContextExtension.GetRenderTargetBitmap
            (
                "Right\nJustified",
                96,
                96,
                FONT_NAME,
                EM_SIZE,
                TextAlignment.Right,
                backgroundBrush,
                rectanglePen,
                brush,
                new Thickness(0)
            );

            image3.Source = bitmap3;

            RenderTargetBitmap bitmap4 = DrawingContextExtension.GetRenderTargetBitmap
            (
                "Margin\n(20)",
                96,
                96,
                FONT_NAME,
                EM_SIZE,
                TextAlignment.Center,
                backgroundBrush,
                rectanglePen,
                brush,
                new Thickness(20)
            );

            image4.Source = bitmap4;

            RenderTargetBitmap bitmap5 = DrawingContextExtension.GetRenderTargetBitmap
            (
                "Margin\n(20,0,0,20)",
                96,
                96,
                FONT_NAME,
                EM_SIZE,
                TextAlignment.Center,
                backgroundBrush,
                rectanglePen,
                brush,
                new Thickness(20, 0, 0, 20)
            );

            image5.Source = bitmap5;

            RenderTargetBitmap bitmap6 = DrawingContextExtension.GetRenderTargetBitmap
            (
                "Margin\n(0,20,20,0)",
                96,
                96,
                FONT_NAME,
                EM_SIZE,
                TextAlignment.Center,
                backgroundBrush,
                rectanglePen,
                brush,
                new Thickness(0, 20, 20, 0)
            );

            image6.Source = bitmap6;            
        }

        #endregion
    }
}
728x90
반응형
그리드형
Posted by 사용자 icodebroker
TAG , , ,

댓글을 달아 주세요