Ejemplo n.º 1
0
        private bool Ekranabas(SharpDX.Vector2 ekran, string yazi, System.Drawing.Color renk, TextFormat qfont)
        {
            TextLayout TL = new SharpDX.DirectWrite.TextLayout(fontFactory, yazi, qfont, float.MaxValue, float.MaxValue);

            device.DrawTextLayout(ekran, TL, (new SolidColorBrush(device, RawColorFromColor(renk))), DrawTextOptions.NoSnap);
            TL.Dispose();
            return(true);
        }
Ejemplo n.º 2
0
        protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
        {
            // This sample should be used along side the help guide educational resource on this topic:
            // http://www.ninjatrader.com/support/helpGuides/nt8/en-us/?using_sharpdx_for_custom_chart_rendering.htm

            // Default plotting in base class. Uncomment if indicators holds at least one plot
            // in this case we would expect NOT to see the SMA plot we have as well in this sample script
            //base.OnRender(chartControl, chartScale);

            // 1.1 - SharpDX Vectors and Charting RenderTarget Coordinates

            // The SharpDX SDK uses "Vector2" objects to describe a two-dimensional point of a device (X and Y coordinates)
            SharpDX.Vector2 startPoint;
            SharpDX.Vector2 endPoint;

            // For our custom script, we need a way to determine the Chart's RenderTarget coordinates to draw our custom shapes
            // This info can be found within the NinjaTrader.Gui.ChartPanel class.
            // You can also use various chartScale and chartControl members to calculate values relative to time and price
            // However, those concepts will not be discussed or used in this sample
            // Notes:  RenderTarget is always the full ChartPanel, so we need to be mindful which sub-ChartPanel we're dealing with
            // Always use ChartPanel X, Y, W, H - as chartScale and chartControl properties WPF units, so they can be drastically different depending on DPI set
            startPoint = new SharpDX.Vector2(ChartPanel.X, ChartPanel.Y);
            endPoint   = new SharpDX.Vector2(ChartPanel.X + ChartPanel.W, ChartPanel.Y + ChartPanel.H);

            // These Vector2 objects are equivalent with WPF System.Windows.Point and can be used interchangeably depending on your requirements
            // For convenience, NinjaTrader provides a "ToVector2()" extension method to convert from WPF Points to SharpDX.Vector2
            SharpDX.Vector2 startPoint1 = new System.Windows.Point(ChartPanel.X, ChartPanel.Y + ChartPanel.H).ToVector2();
            SharpDX.Vector2 endPoint1   = new System.Windows.Point(ChartPanel.X + ChartPanel.W, ChartPanel.Y).ToVector2();

            // SharpDX.Vector2 objects contain X/Y properties which are helpful to recalculate new properties based on the initial vector
            float width  = endPoint.X - startPoint.X;
            float height = endPoint.Y - startPoint.Y;

            // Or you can recalculate a new vector from existing vector objects
            SharpDX.Vector2 center = (startPoint + endPoint) / 2;

            // Tip: This check is simply added to prevent the Indicator dialog menu from opening as a user clicks on the chart
            // The default behavior is to open the Indicator dialog menu if a user double clicks on the indicator
            // (i.e, the indicator falls within the RenderTarget "hit testing")
            // You can remove this check if you want the default behavior implemented
            if (!IsInHitTest)
            {
                // 1.2 - SharpDX Brush Resources

                // RenderTarget commands must use a special brush resource defined in the SharpDX.Direct2D1 namespace
                // These resources exist just like you will find in the WPF/Windows.System.Media namespace
                // such as SolidColorBrushes, LienarGraidentBrushes, RadialGradientBrushes, etc.
                // To begin, we will start with the most basic "Brush" type
                // Warning:  Brush objects must be disposed of after they have been used
                SharpDX.Direct2D1.Brush areaBrushDx;
                SharpDX.Direct2D1.Brush smallAreaBrushDx;
                SharpDX.Direct2D1.Brush textBrushDx;

                // for convenience, you can simply convert a WPF Brush to a DXBrush using the ToDxBrush() extension method provided by NinjaTrader
                // This is a common approach if you have a Brush property created e.g., on the UI you wish to use in custom rendering routines
                areaBrushDx      = areaBrush.ToDxBrush(RenderTarget);
                smallAreaBrushDx = smallAreaBrush.ToDxBrush(RenderTarget);
                textBrushDx      = textBrush.ToDxBrush(RenderTarget);

                // However - it should be noted that this conversion process can be rather expensive
                // If you have many brushes being created, and are not tied to WPF resources
                // You should rather favor creating the SharpDX Brush directly:
                // Warning:  SolidColorBrush objects must be disposed of after they have been used
                SharpDX.Direct2D1.SolidColorBrush customDXBrush = new SharpDX.Direct2D1.SolidColorBrush(RenderTarget,
                                                                                                        SharpDX.Color.DodgerBlue);

                // 1.3 - Using The RenderTarget
                // before executing chart commands, you have the ability to describe how the RenderTarget should render
                // for example, we can store the existing RenderTarget AntialiasMode mode
                // then update the AntialiasMode to be the quality of non-text primitives are rendered
                SharpDX.Direct2D1.AntialiasMode oldAntialiasMode = RenderTarget.AntialiasMode;
                RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.Aliased;

                // Note: The code above stores the oldAntialiasMode as a best practices
                // i.e., if you plan on changing a property of the RenderTarget, you should plan to set it back
                // This is to make sure your requirements to no interfere with the function of another script
                // Additionally smoothing has some performance impacts

                // Once you have defined all the necessary requirements for you object
                //  You can execute a command on the RenderTarget to draw specific shapes
                // e.g., we can now use the RenderTarget's DrawLine() command to render a line
                // using the start/end points and areaBrushDx objects defined before
                RenderTarget.DrawLine(startPoint, endPoint, areaBrushDx, 4);

                // Since rendering occurs in a sequential fashion, after you have executed a command
                // you can switch a property of the RenderTarget to meet other requirements
                // For example, we can draw a second line now which uses a different AntialiasMode
                // and the changes render on the chart for both lines from the time they received commands
                RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.PerPrimitive;
                RenderTarget.DrawLine(startPoint1, endPoint1, areaBrushDx, 4);

                // 1.4 - Rendering Custom Shapes

                // SharpDX namespace consists of several shapes you can use to draw objects more complicated than lines
                // For example, we can use the RectangleF object to draw a rectangle that covers the entire chart area
                SharpDX.RectangleF rect = new SharpDX.RectangleF(startPoint.X, startPoint.Y, width, height);

                // The RenderTarget consists of two commands related to Rectangles.
                // The FillRectangle() method is used to "Paint" the area of a Rectangle
                RenderTarget.FillRectangle(rect, areaBrushDx);

                // and DrawRectangle() is used to "Paint" the outline of a Rectangle
                RenderTarget.DrawRectangle(rect, customDXBrush, 2);

                // Another example is an ellipse which can be used to draw circles
                // The ellipse center point can be used from the Vectors calculated earlier
                // The width and height an absolute 100 device pixels
                // To ensure that pixel coordinates work across all DPI devices, we use the NinjaTrader ChartingExteions methods
                // Which will convert the "100" value from WPF pixels to Device Pixels both vertically and horizontally
                int ellipseRadiusY = ChartingExtensions.ConvertToVerticalPixels(100, ChartControl.PresentationSource);
                int ellipseRadiusX = ChartingExtensions.ConvertToHorizontalPixels(100, ChartControl.PresentationSource);

                SharpDX.Direct2D1.Ellipse ellipse = new SharpDX.Direct2D1.Ellipse(center, ellipseRadiusX, ellipseRadiusY);

                // 1.5 - Complex Brush Types and Shapes
                // For this ellipse, we can use one of the more complex brush types "RadialGradientBrush"
                // Warning:  RadialGradientBrush objects must be disposed of after they have been used
                SharpDX.Direct2D1.RadialGradientBrush radialGradientBrush;

                // However creating a RadialGradientBrush requires a few more properties than SolidColorBrush
                // First, you need to define the array gradient stops the brush will eventually use
                SharpDX.Direct2D1.GradientStop[] gradientStops = new SharpDX.Direct2D1.GradientStop[2];

                // With the gradientStops array, we can describe the color and position of the individual gradients
                gradientStops[0].Color    = SharpDX.Color.Goldenrod;
                gradientStops[0].Position = 0.0f;
                gradientStops[1].Color    = SharpDX.Color.SeaGreen;
                gradientStops[1].Position = 1.0f;

                // then declare a GradientStopCollection from our render target that uses the gradientStops array defined just before
                // Warning:  GradientStopCollection objects must be disposed of after they have been used
                SharpDX.Direct2D1.GradientStopCollection gradientStopCollection =
                    new SharpDX.Direct2D1.GradientStopCollection(RenderTarget, gradientStops);

                // we also need to tell our RadialGradientBrush to match the size and shape of the ellipse that we will be drawing
                // for convenience, SharpDX provides a RadialGradientBrushProperties structure to help define these properties
                SharpDX.Direct2D1.RadialGradientBrushProperties radialGradientBrushProperties =
                    new SharpDX.Direct2D1.RadialGradientBrushProperties
                {
                    GradientOriginOffset = new SharpDX.Vector2(0, 0),
                    Center  = ellipse.Point,
                    RadiusX = ellipse.RadiusY,
                    RadiusY = ellipse.RadiusY
                };

                // we now have everything we need to create a radial gradient brush
                radialGradientBrush = new SharpDX.Direct2D1.RadialGradientBrush(RenderTarget, radialGradientBrushProperties,
                                                                                gradientStopCollection);

                // Finally, we can use this radialGradientBrush to "Paint" the area of the ellipse
                RenderTarget.FillEllipse(ellipse, radialGradientBrush);

                // 1.6 - Simple Text Rendering

                // For rendering custom text to the Chart, there are a few ways you can approach depending on your requirements
                // The most straight forward way is to "borrow" the existing chartControl font provided as a "SimpleFont" class
                // Using the chartControl LabelFont, your custom object will also change to the user defined properties allowing
                // your object to match different fonts if defined by user.

                // The code below will use the chartControl Properties Label Font if it exists,
                // or fall back to a default property if it cannot obtain that value
                NinjaTrader.Gui.Tools.SimpleFont simpleFont = chartControl.Properties.LabelFont ?? new NinjaTrader.Gui.Tools.SimpleFont("Arial", 12);

                // the advantage of using a SimpleFont is they are not only very easy to describe
                // but there is also a convenience method which can be used to convert the SimpleFont to a SharpDX.DirectWrite.TextFormat used to render to the chart
                // Warning:  TextFormat objects must be disposed of after they have been used
                SharpDX.DirectWrite.TextFormat textFormat1 = simpleFont.ToDirectWriteTextFormat();

                // Once you have the format of the font, you need to describe how the font needs to be laid out
                // Here we will create a new Vector2() which draws the font according to the to top left corner of the chart (offset by a few pixels)
                SharpDX.Vector2 upperTextPoint = new SharpDX.Vector2(ChartPanel.X + 10, ChartPanel.Y + 20);
                // Warning:  TextLayout objects must be disposed of after they have been used
                SharpDX.DirectWrite.TextLayout textLayout1 =
                    new SharpDX.DirectWrite.TextLayout(NinjaTrader.Core.Globals.DirectWriteFactory,
                                                       NinjaTrader.Custom.Resource.SampleCustomPlotUpperLeftCorner, textFormat1, ChartPanel.X + ChartPanel.W,
                                                       textFormat1.FontSize);

                // With the format and layout of the text completed, we can now render the font to the chart
                RenderTarget.DrawTextLayout(upperTextPoint, textLayout1, textBrushDx,
                                            SharpDX.Direct2D1.DrawTextOptions.NoSnap);

                // 1.7 - Advanced Text Rendering

                // Font formatting and text layouts can get as complex as you need them to be
                // This example shows how to use a complete custom font unrelated to the existing user-defined chart control settings
                // Warning:  TextLayout and TextFormat objects must be disposed of after they have been used
                SharpDX.DirectWrite.TextFormat textFormat2 =
                    new SharpDX.DirectWrite.TextFormat(NinjaTrader.Core.Globals.DirectWriteFactory, "Century Gothic", FontWeight.Bold,
                                                       FontStyle.Italic, 32f);
                SharpDX.DirectWrite.TextLayout textLayout2 =
                    new SharpDX.DirectWrite.TextLayout(NinjaTrader.Core.Globals.DirectWriteFactory,
                                                       NinjaTrader.Custom.Resource.SampleCustomPlotLowerRightCorner, textFormat2, 400, textFormat1.FontSize);

                // the textLayout object provides a way to measure the described font through a "Metrics" object
                // This allows you to create new vectors on the chart which are entirely dependent on the "text" that is being rendered
                // For example, we can create a rectangle that surrounds our font based off the textLayout which would dynamically change if the text used in the layout changed dynamically
                SharpDX.Vector2 lowerTextPoint = new SharpDX.Vector2(ChartPanel.W - textLayout2.Metrics.Width - 5,
                                                                     ChartPanel.Y + (ChartPanel.H - textLayout2.Metrics.Height));
                SharpDX.RectangleF rect1 = new SharpDX.RectangleF(lowerTextPoint.X, lowerTextPoint.Y, textLayout2.Metrics.Width,
                                                                  textLayout2.Metrics.Height);

                // We can draw the Rectangle based on the TextLayout used above
                RenderTarget.FillRectangle(rect1, smallAreaBrushDx);
                RenderTarget.DrawRectangle(rect1, smallAreaBrushDx, 2);

                // And render the advanced text layout using the DrawTextLayout() method
                // Note:  When drawing the same text repeatedly, using the DrawTextLayout() method is more efficient than using the DrawText()
                // because the text doesn't need to be formatted and the layout processed with each call
                RenderTarget.DrawTextLayout(lowerTextPoint, textLayout2, textBrushDx, SharpDX.Direct2D1.DrawTextOptions.NoSnap);

                // 1.8 - Cleanup
                // This concludes all of the rendering concepts used in the sample
                // However - there are some final clean up processes we should always provided before we are done

                // If changed, do not forget to set the AntialiasMode back to the default value as described above as a best practice
                RenderTarget.AntialiasMode = oldAntialiasMode;

                // We also need to make sure to dispose of every device dependent resource on each render pass
                // Failure to dispose of these resources will eventually result in unnecessary amounts of memory being used on the chart
                // Although the effects might not be obvious as first, if you see issues related to memory increasing over time
                // Objects such as these should be inspected first
                areaBrushDx.Dispose();
                customDXBrush.Dispose();
                gradientStopCollection.Dispose();
                radialGradientBrush.Dispose();
                smallAreaBrushDx.Dispose();
                textBrushDx.Dispose();
                textFormat1.Dispose();
                textFormat2.Dispose();
                textLayout1.Dispose();
                textLayout2.Dispose();
            }
        }
Ejemplo n.º 3
0
        static void over()
        {
            var inputPath  = "Input.png";
            var outputPath = "output.png";

            // 그래픽을 랜더링할 장비를 추가 - 3D or 2D
            var defaultDevice = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware,
                                                              d3d.DeviceCreationFlags.VideoSupport
                                                              | d3d.DeviceCreationFlags.BgraSupport
                                                              | d3d.DeviceCreationFlags.None);
            var d3dDevice  = defaultDevice.QueryInterface <d3d.Device1>(); //get a refer to the D3D 11.1 device
            var dxgiDevice = d3dDevice.QueryInterface <dxgi.Device1>();    //get a refer to the DXGI device
            var d2dDevice  = new d2.Device(dxgiDevice);

            // DeviceContext를 초기화. D2D 렌더링 타겟이 될 것이고 모든 렌더링 작업을 허용
            var d2dContext = new d2.DeviceContext(d2dDevice, d2.DeviceContextOptions.None);
            var dwFactory  = new dw.Factory();


            //D2D, WIC 둘 다 지원되는 픽셀 형식 지정
            var d2PixelFormat = new d2.PixelFormat(dxgi.Format.R8G8B8A8_UNorm, d2.AlphaMode.Premultiplied);
            //RGBA형식 사용
            var wicPixelFormat = wic.PixelFormat.Format32bppPRGBA;



            //이미지 로딩
            var imagingFactory = new wic.ImagingFactory2();
            var decoder        = new wic.PngBitmapDecoder(imagingFactory);
            var inputStream    = new wic.WICStream(imagingFactory, inputPath, NativeFileAccess.Read);

            decoder.Initialize(inputStream, wic.DecodeOptions.CacheOnLoad);



            //다이렉트2D가 사용할수 있도록 디코딩
            var formatConverter = new wic.FormatConverter(imagingFactory);

            formatConverter.Initialize(decoder.GetFrame(0), wicPixelFormat);


            //기본 이미지를 D2D이미지로 로드
            //var inputBitmap = d2.Bitmap1.FromWicBitmap(d2dContext, formatConverter, new d2.BitmapProperties1(d2PixelFormat));

            //이미지 크기 저장
            var inputImageSize = formatConverter.Size;
            var pixelWidth     = inputImageSize.Width;
            var pixelHeight    = inputImageSize.Height;


            //Effect1 : BitpmapSource - 디코딩된 이미지 데이터를 가져오고 BitmapSource 가져오기
            var bitmapSourceEffect = new d2.Effects.BitmapSource(d2dContext);

            bitmapSourceEffect.WicBitmapSource = formatConverter;



            // Effect 2 : GaussianBlur - bitmapsource에 가우시안블러 효과 적용
            var gaussianBlurEffect = new d2.Effects.GaussianBlur(d2dContext);

            gaussianBlurEffect.SetInput(0, bitmapSourceEffect.Output, true);
            gaussianBlurEffect.StandardDeviation = 5f;



            //overlay text setup
            var textFormat = new dw.TextFormat(dwFactory, "Arial", 15f);

            //draw a long text to show the automatic line wrapping
            var textToDraw = "sime ling text..." + "text" + "dddd";

            //create the text layout - this imroves the drawing performance for static text
            // as the glyph positions are precalculated
            //윤곽선 글꼴 데이터에서 글자 하나의 모양에 대한 기본 단위를 글리프(glyph)라고 한다
            var textLayout = new dw.TextLayout(dwFactory, textToDraw, textFormat, 300f, 1000f);

            SharpDX.Mathematics.Interop.RawColor4 color = new SharpDX.Mathematics.Interop.RawColor4(255, 255, 255, 1);
            var textBrush = new d2.SolidColorBrush(d2dContext, color);



            //여기서부터 다시

            //render target setup

            //create the d2d bitmap description using default flags and 96 DPI
            var d2dBitmapProps = new d2.BitmapProperties1(d2PixelFormat, 96, 96, d2.BitmapOptions.Target | d2.BitmapOptions.CannotDraw);

            //the render target
            var d2dRenderTarget = new d2.Bitmap1(d2dContext, new Size2(pixelWidth, pixelHeight), d2dBitmapProps);

            d2dContext.Target = d2dRenderTarget; //associate bitmap with the d2d context



            //Drawing

            //slow preparations - fast drawing
            d2dContext.BeginDraw();
            d2dContext.DrawImage(gaussianBlurEffect, new SharpDX.Mathematics.Interop.RawVector2(100f, 100f));
            d2dContext.DrawTextLayout(new SharpDX.Mathematics.Interop.RawVector2(50f, 50f), textLayout, textBrush);
            d2dContext.EndDraw();

            //Image save

            //delete the output file if it already exists
            if (System.IO.File.Exists(outputPath))
            {
                System.IO.File.Delete(outputPath);
            }

            //use the appropiate overload to write either to tream or to a file
            var stream = new wic.WICStream(imagingFactory, outputPath, NativeFileAccess.Write);

            //select the image encoding format HERE
            var encoder = new wic.PngBitmapEncoder(imagingFactory);

            encoder.Initialize(stream);

            var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder);

            bitmapFrameEncode.Initialize();
            bitmapFrameEncode.SetSize(pixelWidth, pixelHeight);
            bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat);

            //this is the trick to write d2d1 bitmap to WIC
            var imageEncoder = new wic.ImageEncoder(imagingFactory, d2dDevice);

            imageEncoder.WriteFrame(d2dRenderTarget, bitmapFrameEncode, new wic.ImageParameters(d2PixelFormat, 96, 96, 0, 0, pixelWidth, pixelHeight));

            bitmapFrameEncode.Commit();
            encoder.Commit();

            //cleanup

            //dispose everything and free used resources
            bitmapFrameEncode.Dispose();
            encoder.Dispose();
            stream.Dispose();
            textBrush.Dispose();
            textLayout.Dispose();
            textFormat.Dispose();
            formatConverter.Dispose();
            //gaussianBlurEffect.Dispose();
            bitmapSourceEffect.Dispose();
            d2dRenderTarget.Dispose();
            inputStream.Dispose();
            decoder.Dispose();
            d2dContext.Dispose();
            dwFactory.Dispose();
            imagingFactory.Dispose();
            d2dDevice.Dispose();
            dxgiDevice.Dispose();
            d3dDevice.Dispose();
            defaultDevice.Dispose();

            //save
            System.Diagnostics.Process.Start(outputPath);
        }
        internal CCTexture2D CreateTextSprite(string text, CCFontDefinition textDefinition)
        {
            if (string.IsNullOrEmpty(text))
                return new CCTexture2D();

            int imageWidth;
            int imageHeight;
            var textDef = textDefinition;
            var contentScaleFactorWidth = CCLabel.DefaultTexelToContentSizeRatios.Width;
            var contentScaleFactorHeight = CCLabel.DefaultTexelToContentSizeRatios.Height;
            textDef.FontSize *= contentScaleFactorWidth;
            textDef.Dimensions.Width *= contentScaleFactorWidth;
            textDef.Dimensions.Height *= contentScaleFactorHeight;

            bool hasPremultipliedAlpha;

            var font = CreateFont(textDef.FontName, textDef.FontSize);

            var _currentFontSizeEm = textDef.FontSize;
            var _currentDIP = ConvertPointSizeToDIP(_currentFontSizeEm);

            // color
            var foregroundColor = Color4.White;

            // alignment
            var horizontalAlignment = textDef.Alignment;
            var verticleAlignement = textDef.LineAlignment;

            var textAlign = (CCTextAlignment.Right == horizontalAlignment) ? TextAlignment.Trailing
                : (CCTextAlignment.Center == horizontalAlignment) ? TextAlignment.Center
                : TextAlignment.Leading;

            var paragraphAlign = (CCVerticalTextAlignment.Bottom == vertAlignment) ? ParagraphAlignment.Far
                : (CCVerticalTextAlignment.Center == vertAlignment) ? ParagraphAlignment.Center
                : ParagraphAlignment.Near;

            // LineBreak
            var lineBreak = (CCLabelLineBreak.Character == textDef.LineBreak) ? WordWrapping.Wrap
                : (CCLabelLineBreak.Word == textDef.LineBreak) ? WordWrapping.Wrap
                : WordWrapping.NoWrap;

            // LineBreak
            // TODO: Find a way to specify the type of line breaking if possible.

            var dimensions = new CCSize(textDef.Dimensions.Width, textDef.Dimensions.Height);

            var layoutAvailable = true;
            if (dimensions.Width <= 0)
            {
                dimensions.Width = 8388608;
                layoutAvailable = false;
            }

            if (dimensions.Height <= 0)
            {
                dimensions.Height = 8388608;
                layoutAvailable = false;
            }

            var fontName = font.FontFamily.FamilyNames.GetString(0);
            var textFormat = new TextFormat(FactoryDWrite, fontName,
                _currentFontCollection, FontWeight.Regular, FontStyle.Normal, FontStretch.Normal, _currentDIP);

            textFormat.TextAlignment = textAlign;
            textFormat.ParagraphAlignment = paragraphAlign;

            var textLayout = new TextLayout(FactoryDWrite, text, textFormat, dimensions.Width, dimensions.Height);

            var boundingRect = new RectangleF();

            // Loop through all the lines so we can find our drawing offsets
            var textMetrics = textLayout.Metrics;
            var lineCount = textMetrics.LineCount;

            // early out if something went wrong somewhere and nothing is to be drawn
            if (lineCount == 0)
                return new CCTexture2D();

            // Fill out the bounding rect width and height so we can calculate the yOffset later if needed
            boundingRect.X = 0; 
            boundingRect.Y = 0; 
            boundingRect.Width = textMetrics.Width;
            boundingRect.Height = textMetrics.Height;

            if (!layoutAvailable)
            {
                if (dimensions.Width == 8388608)
                {
                    dimensions.Width = boundingRect.Width;
                }
                if (dimensions.Height == 8388608)
                {
                    dimensions.Height = boundingRect.Height;
                }
            }

            imageWidth = (int)dimensions.Width;
            imageHeight = (int)dimensions.Height;

            // Recreate our layout based on calculated dimensions so that we can draw the text correctly
            // in our image when Alignment is not Left.
            if (textAlign != TextAlignment.Leading)
            {
                textLayout.MaxWidth = dimensions.Width;
                textLayout.MaxHeight = dimensions.Height;
            }

            // Line alignment
            var yOffset = (CCVerticalTextAlignment.Bottom == verticleAlignement
                || boundingRect.Bottom >= dimensions.Height) ? dimensions.Height - boundingRect.Bottom  // align to bottom
                : (CCVerticalTextAlignment.Top == verticleAlignement) ? 0                    // align to top
                : (imageHeight - boundingRect.Bottom) * 0.5f;                                   // align to center


            if (labelRenderer == null)
                labelRenderer = new CCLabel_Renderer81();

            try
            {

                // The following code creates a .png stream in memory of our Bitmap and uses it to create our Textue2D
                Texture2D tex = null;

                using (var pngStream = labelRenderer.RenderLabelToStream(imageWidth, imageHeight, foregroundColor,
                    new Vector2(boundingRect.X, yOffset), textLayout).Result)
                {
                    // Create the Texture2D from the png stream
                    tex = Texture2D.FromStream(CCDrawManager.SharedDrawManager.XnaGraphicsDevice, pngStream);

                }

                // Return our new CCTexture2D created from the Texture2D which will have our text drawn on it.
                return new CCTexture2D(tex);
            }
            catch (Exception exc)
            {
                CCLog.Log("CCLabel-Windows: Unable to create the backing image of our text.  Message: {0}", exc.StackTrace);
            }
            finally
            {

                if (textFormat != null)
                {
                    textFormat.Dispose();
                    textFormat = null;
                }

                if (textLayout != null)
                {
                    textLayout.Dispose();
                    textLayout = null;
                }
            }

            // If we have reached here then something has gone wrong.
            return new CCTexture2D();
        }
Ejemplo n.º 5
0
        internal CCTexture2D CreateTextSprite(string text, CCFontDefinition textDefinition)
        {
            if (string.IsNullOrEmpty(text))
                return new CCTexture2D();

            int imageWidth;
            int imageHeight;
            var textDef = textDefinition;
            var contentScaleFactorWidth = CCLabel.DefaultTexelToContentSizeRatios.Width;
            var contentScaleFactorHeight = CCLabel.DefaultTexelToContentSizeRatios.Height;
            textDef.FontSize *= contentScaleFactorWidth;
            textDef.Dimensions.Width *= contentScaleFactorWidth;
            textDef.Dimensions.Height *= contentScaleFactorHeight;

            var font = CreateFont(textDef.FontName, textDef.FontSize);
            if (font == null)
            {
                CCLog.Log("Can not create font {0} with size {1}.", textDef.FontName, textDef.FontSize);
                return new CCTexture2D();
            }


            var _currentFontSizeEm = textDef.FontSize;
            var _currentDIP = ConvertPointSizeToDIP(_currentFontSizeEm);

            // color
            var foregroundColor = Color4.White;

            // alignment
            var horizontalAlignment = textDef.Alignment;
            var verticleAlignement = textDef.LineAlignment;

            var textAlign = (CCTextAlignment.Right == horizontalAlignment) ? TextAlignment.Trailing
                : (CCTextAlignment.Center == horizontalAlignment) ? TextAlignment.Center
                : TextAlignment.Leading;

            var paragraphAlign = (CCVerticalTextAlignment.Bottom == vertAlignment) ? ParagraphAlignment.Far
                : (CCVerticalTextAlignment.Center == vertAlignment) ? ParagraphAlignment.Center
                : ParagraphAlignment.Near;

            // LineBreak
            var lineBreak = (CCLabelLineBreak.Character == textDef.LineBreak) ? WordWrapping.Wrap
                : (CCLabelLineBreak.Word == textDef.LineBreak) ? WordWrapping.Wrap
                : WordWrapping.NoWrap;

            // LineBreak
            // TODO: Find a way to specify the type of line breaking if possible.

            var dimensions = new CCSize(textDef.Dimensions.Width, textDef.Dimensions.Height);

            var layoutAvailable = true;
            if (dimensions.Width <= 0)
            {
                dimensions.Width = 8388608;
                layoutAvailable = false;
            }

            if (dimensions.Height <= 0)
            {
                dimensions.Height = 8388608;
                layoutAvailable = false;
            }

            var fontName = font.FontFamily.FamilyNames.GetString(0);
            var textFormat = new TextFormat(FactoryDWrite, fontName,
                _currentFontCollection, FontWeight.Regular, FontStyle.Normal, FontStretch.Normal, _currentDIP);

            textFormat.TextAlignment = textAlign;
            textFormat.ParagraphAlignment = paragraphAlign;

            var textLayout = new TextLayout(FactoryDWrite, text, textFormat, dimensions.Width, dimensions.Height);

            var boundingRect = new RectangleF();

            // Loop through all the lines so we can find our drawing offsets
            var textMetrics = textLayout.Metrics;
            var lineCount = textMetrics.LineCount;

            // early out if something went wrong somewhere and nothing is to be drawn
            if (lineCount == 0)
                return new CCTexture2D();

            // Fill out the bounding rect width and height so we can calculate the yOffset later if needed
            boundingRect.X = 0; 
            boundingRect.Y = 0; 
            boundingRect.Width = textMetrics.Width;
            boundingRect.Height = textMetrics.Height;

            if (!layoutAvailable)
            {
                if (dimensions.Width == 8388608)
                {
                    dimensions.Width = boundingRect.Width;
                }
                if (dimensions.Height == 8388608)
                {
                    dimensions.Height = boundingRect.Height;
                }
            }

            imageWidth = (int)dimensions.Width;
            imageHeight = (int)dimensions.Height;

            // Recreate our layout based on calculated dimensions so that we can draw the text correctly
            // in our image when Alignment is not Left.
            if (textAlign != TextAlignment.Leading)
            {
                textLayout.MaxWidth = dimensions.Width;
                textLayout.MaxHeight = dimensions.Height;
            }

            // Line alignment
            var yOffset = (CCVerticalTextAlignment.Bottom == verticleAlignement
                || boundingRect.Bottom >= dimensions.Height) ? dimensions.Height - boundingRect.Bottom  // align to bottom
                : (CCVerticalTextAlignment.Top == verticleAlignement) ? 0                    // align to top
                : (imageHeight - boundingRect.Bottom) * 0.5f;                                   // align to center


            SharpDX.WIC.Bitmap sharpBitmap = null;
            WicRenderTarget sharpRenderTarget = null;
            SolidColorBrush solidBrush = null;

            try
            {
                // Select our pixel format
                var pixelFormat = SharpDX.WIC.PixelFormat.Format32bppPRGBA;

                // create our backing bitmap
                sharpBitmap = new SharpDX.WIC.Bitmap(FactoryImaging, imageWidth, imageHeight, pixelFormat, BitmapCreateCacheOption.CacheOnLoad);

                // Create the render target that we will draw to
                sharpRenderTarget = new WicRenderTarget(Factory2D, sharpBitmap, new RenderTargetProperties());
                // Create our brush to actually draw with
                solidBrush = new SolidColorBrush(sharpRenderTarget, foregroundColor);

                // Begin the drawing
                sharpRenderTarget.BeginDraw();

                if (textDefinition.isShouldAntialias)
                    sharpRenderTarget.AntialiasMode = AntialiasMode.Aliased;

                // Clear it
                sharpRenderTarget.Clear(TransparentColor);

                // Draw the text to the bitmap
                sharpRenderTarget.DrawTextLayout(new Vector2(boundingRect.X, yOffset), textLayout, solidBrush);

                // End our drawing which will commit the rendertarget to the bitmap
                sharpRenderTarget.EndDraw();

                // Debugging purposes
                //var s = "Label4";
                //SaveToFile(@"C:\Xamarin\" + s + ".png", _bitmap, _renderTarget);

                // The following code creates a .png stream in memory of our Bitmap and uses it to create our Textue2D
                Texture2D tex = null;

                using (var memStream = new MemoryStream())
                {
                    using (var encoder = new PngBitmapEncoder(FactoryImaging, memStream))
                    using (var frameEncoder = new BitmapFrameEncode(encoder))
                    {
                        frameEncoder.Initialize();
                        frameEncoder.WriteSource(sharpBitmap);
                        frameEncoder.Commit();
                        encoder.Commit();
                    }
                    // Create the Texture2D from the png stream
                    tex = Texture2D.FromStream(CCDrawManager.SharedDrawManager.XnaGraphicsDevice, memStream);
                }

                // Return our new CCTexture2D created from the Texture2D which will have our text drawn on it.
                return new CCTexture2D(tex);
            }
            catch (Exception exc)
            {
                CCLog.Log("CCLabel-Windows: Unable to create the backing image of our text.  Message: {0}", exc.StackTrace);
            }
            finally
            {
                if (sharpBitmap != null)
                {
                    sharpBitmap.Dispose();
                    sharpBitmap = null;
                }

                if (sharpRenderTarget != null)
                {
                    sharpRenderTarget.Dispose();
                    sharpRenderTarget = null;
                }

                if (solidBrush != null)
                {
                    solidBrush.Dispose();
                    solidBrush = null;
                }

                if (textFormat != null)
                {
                    textFormat.Dispose();
                    textFormat = null;
                }

                if (textLayout != null)
                {
                    textLayout.Dispose();
                    textLayout = null;
                }
            }

            // If we have reached here then something has gone wrong.
            return new CCTexture2D();
        }
Ejemplo n.º 6
0
        static void Main()
        {
            // input and output files are supposed to be in the program folder
            var inputPath  = "Input.png";
            var outputPath = "Output.png";

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // INITIALIZATION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // initialize the D3D device which will allow to render to image any graphics - 3D or 2D
            var defaultDevice = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware,
                                                              d3d.DeviceCreationFlags.VideoSupport
                                                              | d3d.DeviceCreationFlags.BgraSupport
                                                              | d3d.DeviceCreationFlags.Debug); // take out the Debug flag for better performance

            var d3dDevice  = defaultDevice.QueryInterface <d3d.Device1>();                      // get a reference to the Direct3D 11.1 device
            var dxgiDevice = d3dDevice.QueryInterface <dxgi.Device>();                          // get a reference to DXGI device

            var d2dDevice = new d2.Device(dxgiDevice);                                          // initialize the D2D device

            var imagingFactory = new wic.ImagingFactory2();                                     // initialize the WIC factory

            // initialize the DeviceContext - it will be the D2D render target and will allow all rendering operations
            var d2dContext = new d2.DeviceContext(d2dDevice, d2.DeviceContextOptions.None);

            var dwFactory = new dw.Factory();

            // specify a pixel format that is supported by both D2D and WIC
            var d2PixelFormat = new d2.PixelFormat(dxgi.Format.R8G8B8A8_UNorm, d2.AlphaMode.Premultiplied);
            // if in D2D was specified an R-G-B-A format - use the same for wic
            var wicPixelFormat = wic.PixelFormat.Format32bppPRGBA;

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // IMAGE LOADING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            var decoder     = new wic.PngBitmapDecoder(imagingFactory);                            // we will load a PNG image
            var inputStream = new wic.WICStream(imagingFactory, inputPath, NativeFileAccess.Read); // open the image file for reading

            decoder.Initialize(inputStream, wic.DecodeOptions.CacheOnLoad);

            // decode the loaded image to a format that can be consumed by D2D
            var formatConverter = new wic.FormatConverter(imagingFactory);

            formatConverter.Initialize(decoder.GetFrame(0), wicPixelFormat);

            // load the base image into a D2D Bitmap
            //var inputBitmap = d2.Bitmap1.FromWicBitmap(d2dContext, formatConverter, new d2.BitmapProperties1(d2PixelFormat));

            // store the image size - output will be of the same size
            var inputImageSize = formatConverter.Size;
            var pixelWidth     = inputImageSize.Width;
            var pixelHeight    = inputImageSize.Height;

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // EFFECT SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // Effect 1 : BitmapSource - take decoded image data and get a BitmapSource from it
            var bitmapSourceEffect = new d2.Effects.BitmapSource(d2dContext);

            bitmapSourceEffect.WicBitmapSource = formatConverter;

            // Effect 2 : GaussianBlur - give the bitmapsource a gaussian blurred effect
            var gaussianBlurEffect = new d2.Effects.GaussianBlur(d2dContext);

            gaussianBlurEffect.SetInput(0, bitmapSourceEffect.Output, true);
            gaussianBlurEffect.StandardDeviation = 5f;

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // OVERLAY TEXT SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            var textFormat = new dw.TextFormat(dwFactory, "Arial", 15f); // create the text format of specified font configuration

            // draw a long text to show the automatic line wrapping
            var textToDraw = "Some long text to show the drawing of preformatted "
                             + "glyphs using DirectWrite on the Direct2D surface."
                             + " Notice the automatic wrapping of line if it exceeds desired width.";

            // create the text layout - this improves the drawing performance for static text
            // as the glyph positions are precalculated
            var textLayout = new dw.TextLayout(dwFactory, textToDraw, textFormat, 300f, 1000f);

            var textBrush = new d2.SolidColorBrush(d2dContext, Color.LightGreen);

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // RENDER TARGET SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // create the d2d bitmap description using default flags (from SharpDX samples) and 96 DPI
            var d2dBitmapProps = new d2.BitmapProperties1(d2PixelFormat, 96, 96, d2.BitmapOptions.Target | d2.BitmapOptions.CannotDraw);

            // the render target
            var d2dRenderTarget = new d2.Bitmap1(d2dContext, new Size2(pixelWidth, pixelHeight), d2dBitmapProps);

            d2dContext.Target = d2dRenderTarget; // associate bitmap with the d2d context

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // DRAWING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // slow preparations - fast drawing:
            d2dContext.BeginDraw();
            d2dContext.DrawImage(gaussianBlurEffect);
            d2dContext.DrawTextLayout(new Vector2(5f, 5f), textLayout, textBrush);
            d2dContext.EndDraw();

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // IMAGE SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // delete the output file if it already exists
            if (System.IO.File.Exists(outputPath))
            {
                System.IO.File.Delete(outputPath);
            }

            // use the appropiate overload to write either to stream or to a file
            var stream = new wic.WICStream(imagingFactory, outputPath, NativeFileAccess.Write);

            // select the image encoding format HERE
            var encoder = new wic.PngBitmapEncoder(imagingFactory);

            encoder.Initialize(stream);

            var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder);

            bitmapFrameEncode.Initialize();
            bitmapFrameEncode.SetSize(pixelWidth, pixelHeight);
            bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat);

            // this is the trick to write D2D1 bitmap to WIC
            var imageEncoder = new wic.ImageEncoder(imagingFactory, d2dDevice);

            imageEncoder.WriteFrame(d2dRenderTarget, bitmapFrameEncode, new wic.ImageParameters(d2PixelFormat, 96, 96, 0, 0, pixelWidth, pixelHeight));

            bitmapFrameEncode.Commit();
            encoder.Commit();

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // CLEANUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // dispose everything and free used resources

            bitmapFrameEncode.Dispose();
            encoder.Dispose();
            stream.Dispose();
            textBrush.Dispose();
            textLayout.Dispose();
            textFormat.Dispose();
            formatConverter.Dispose();
            gaussianBlurEffect.Dispose();
            bitmapSourceEffect.Dispose();
            d2dRenderTarget.Dispose();
            inputStream.Dispose();
            decoder.Dispose();
            d2dContext.Dispose();
            dwFactory.Dispose();
            imagingFactory.Dispose();
            d2dDevice.Dispose();
            dxgiDevice.Dispose();
            d3dDevice.Dispose();
            defaultDevice.Dispose();

            // show the result
            System.Diagnostics.Process.Start(outputPath);
        }
Ejemplo n.º 7
0
        static void Main()
        {
            // input and output files are supposed to be in the program folder
            var inputPath = "Input.png";
            var outputPath = "Output.png";

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // INITIALIZATION ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // initialize the D3D device which will allow to render to image any graphics - 3D or 2D
            var defaultDevice = new SharpDX.Direct3D11.Device(SharpDX.Direct3D.DriverType.Hardware,
                                                              d3d.DeviceCreationFlags.VideoSupport
                                                              | d3d.DeviceCreationFlags.BgraSupport
                                                              | d3d.DeviceCreationFlags.Debug); // take out the Debug flag for better performance

            var d3dDevice = defaultDevice.QueryInterface<d3d.Device1>(); // get a reference to the Direct3D 11.1 device
            var dxgiDevice = d3dDevice.QueryInterface<dxgi.Device>(); // get a reference to DXGI device

            var d2dDevice = new d2.Device(dxgiDevice); // initialize the D2D device

            var imagingFactory = new wic.ImagingFactory2(); // initialize the WIC factory

            // initialize the DeviceContext - it will be the D2D render target and will allow all rendering operations
            var d2dContext = new d2.DeviceContext(d2dDevice, d2.DeviceContextOptions.None);

            var dwFactory = new dw.Factory();

            // specify a pixel format that is supported by both D2D and WIC
            var d2PixelFormat = new d2.PixelFormat(dxgi.Format.R8G8B8A8_UNorm, d2.AlphaMode.Premultiplied);
            // if in D2D was specified an R-G-B-A format - use the same for wic
            var wicPixelFormat = wic.PixelFormat.Format32bppPRGBA;

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // IMAGE LOADING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            var decoder = new wic.PngBitmapDecoder(imagingFactory); // we will load a PNG image
            var inputStream = new wic.WICStream(imagingFactory, inputPath, NativeFileAccess.Read); // open the image file for reading
            decoder.Initialize(inputStream, wic.DecodeOptions.CacheOnLoad);

            // decode the loaded image to a format that can be consumed by D2D
            var formatConverter = new wic.FormatConverter(imagingFactory);
            formatConverter.Initialize(decoder.GetFrame(0), wicPixelFormat);

            // load the base image into a D2D Bitmap
            //var inputBitmap = d2.Bitmap1.FromWicBitmap(d2dContext, formatConverter, new d2.BitmapProperties1(d2PixelFormat));

            // store the image size - output will be of the same size
            var inputImageSize = formatConverter.Size;
            var pixelWidth = inputImageSize.Width;
            var pixelHeight = inputImageSize.Height;

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // EFFECT SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // Effect 1 : BitmapSource - take decoded image data and get a BitmapSource from it
            var bitmapSourceEffect = new d2.Effects.BitmapSource(d2dContext);
            bitmapSourceEffect.WicBitmapSource = formatConverter;

            // Effect 2 : GaussianBlur - give the bitmapsource a gaussian blurred effect
            var gaussianBlurEffect = new d2.Effects.GaussianBlur(d2dContext);
            gaussianBlurEffect.SetInput(0, bitmapSourceEffect.Output, true);
            gaussianBlurEffect.StandardDeviation = 5f;

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // OVERLAY TEXT SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            var textFormat = new dw.TextFormat(dwFactory, "Arial", 15f); // create the text format of specified font configuration

            // draw a long text to show the automatic line wrapping
            var textToDraw = "Some long text to show the drawing of preformatted "
                             + "glyphs using DirectWrite on the Direct2D surface."
                             + " Notice the automatic wrapping of line if it exceeds desired width.";

            // create the text layout - this improves the drawing performance for static text
            // as the glyph positions are precalculated
            var textLayout = new dw.TextLayout(dwFactory, textToDraw, textFormat, 300f, 1000f);

            var textBrush = new d2.SolidColorBrush(d2dContext, Color.LightGreen);

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // RENDER TARGET SETUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // create the d2d bitmap description using default flags (from SharpDX samples) and 96 DPI
            var d2dBitmapProps = new d2.BitmapProperties1(d2PixelFormat, 96, 96, d2.BitmapOptions.Target | d2.BitmapOptions.CannotDraw);

            // the render target
            var d2dRenderTarget = new d2.Bitmap1(d2dContext, new Size2(pixelWidth, pixelHeight), d2dBitmapProps);
            d2dContext.Target = d2dRenderTarget; // associate bitmap with the d2d context

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // DRAWING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // slow preparations - fast drawing:
            d2dContext.BeginDraw();
            d2dContext.DrawImage(gaussianBlurEffect);
            d2dContext.DrawTextLayout(new Vector2(5f, 5f), textLayout, textBrush);
            d2dContext.EndDraw();

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // IMAGE SAVING ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // delete the output file if it already exists
            if (System.IO.File.Exists(outputPath)) System.IO.File.Delete(outputPath);

            // use the appropiate overload to write either to stream or to a file
            var stream = new wic.WICStream(imagingFactory, outputPath, NativeFileAccess.Write);

            // select the image encoding format HERE
            var encoder = new wic.PngBitmapEncoder(imagingFactory);
            encoder.Initialize(stream);

            var bitmapFrameEncode = new wic.BitmapFrameEncode(encoder);
            bitmapFrameEncode.Initialize();
            bitmapFrameEncode.SetSize(pixelWidth, pixelHeight);
            bitmapFrameEncode.SetPixelFormat(ref wicPixelFormat);

            // this is the trick to write D2D1 bitmap to WIC
            var imageEncoder = new wic.ImageEncoder(imagingFactory, d2dDevice);
            imageEncoder.WriteFrame(d2dRenderTarget, bitmapFrameEncode, new wic.ImageParameters(d2PixelFormat, 96, 96, 0, 0, pixelWidth, pixelHeight));

            bitmapFrameEncode.Commit();
            encoder.Commit();

            // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            // CLEANUP ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            // dispose everything and free used resources

            bitmapFrameEncode.Dispose();
            encoder.Dispose();
            stream.Dispose();
            textBrush.Dispose();
            textLayout.Dispose();
            textFormat.Dispose();
            formatConverter.Dispose();
            gaussianBlurEffect.Dispose();
            bitmapSourceEffect.Dispose();
            d2dRenderTarget.Dispose();
            inputStream.Dispose();
            decoder.Dispose();
            d2dContext.Dispose();
            dwFactory.Dispose();
            imagingFactory.Dispose();
            d2dDevice.Dispose();
            dxgiDevice.Dispose();
            d3dDevice.Dispose();
            defaultDevice.Dispose();

            // show the result
            System.Diagnostics.Process.Start(outputPath);
        }
Ejemplo n.º 8
0
        protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
        {
            // Tip: This check is simply added to prevent the Indicator dialog menu from opening as a user clicks on the chart
            // The default behavior is to open the Indicator dialog menu if a user double clicks on the indicator
            // (i.e, the indicator falls within the RenderTarget "hit testing")
            // You can remove this check if you want the default behavior implemented
            if (!IsInHitTest)
            {
                // 1.2 - SharpDX Brush Resources
                // RenderTarget commands must use a special brush resource defined in the SharpDX.Direct2D1 namespace
                // These resources exist just like you will find in the WPF/Windows.System.Media namespace
                // such as SolidColorBrushes, LienarGraidentBrushes, RadialGradientBrushes, etc.
                // To begin, we will start with the most basic "Brush" type
                // Warning:  Brush objects must be disposed of after they have been used
                SharpDX.Direct2D1.Brush areaBrushDx;
                SharpDX.Direct2D1.Brush smallAreaBrushDx;
                SharpDX.Direct2D1.Brush textBrushDx;
                // for convenience, you can simply convert a WPF Brush to a DXBrush using the ToDxBrush() extension method provided by NinjaTrader
                // This is a common approach if you have a Brush property created e.g., on the UI you wish to use in custom rendering routines
                areaBrushDx      = areaBrush.ToDxBrush(RenderTarget);
                smallAreaBrushDx = smallAreaBrush.ToDxBrush(RenderTarget);
                textBrushDx      = textBrush.ToDxBrush(RenderTarget);
                // 1.3 - Using The RenderTarget
                // before executing chart commands, you have the ability to describe how the RenderTarget should render
                // for example, we can store the existing RenderTarget AntialiasMode mode
                // then update the AntialiasMode to be the quality of non-text primitives are rendered
                SharpDX.Direct2D1.AntialiasMode oldAntialiasMode = RenderTarget.AntialiasMode;
                RenderTarget.AntialiasMode = SharpDX.Direct2D1.AntialiasMode.Aliased;
                // 1.6 - Simple Text Rendering

                // For rendering custom text to the Chart, there are a few ways you can approach depending on your requirements
                // The most straight forward way is to "borrow" the existing chartControl font provided as a "SimpleFont" class
                // Using the chartControl LabelFont, your custom object will also change to the user defined properties allowing
                // your object to match different fonts if defined by user.

                // The code below will use the chartControl Properties Label Font if it exists,
                // or fall back to a default property if it cannot obtain that value
                NinjaTrader.Gui.Tools.SimpleFont simpleFont = chartControl.Properties.LabelFont ?? new NinjaTrader.Gui.Tools.SimpleFont("Arial", 12);

                // the advantage of using a SimpleFont is they are not only very easy to describe
                // but there is also a convenience method which can be used to convert the SimpleFont to a SharpDX.DirectWrite.TextFormat used to render to the chart
                // Warning:  TextFormat objects must be disposed of after they have been used
                SharpDX.DirectWrite.TextFormat textFormat1 = simpleFont.ToDirectWriteTextFormat();

                // Once you have the format of the font, you need to describe how the font needs to be laid out
                // Here we will create a new Vector2() which draws the font according to the to top left corner of the chart (offset by a few pixels)
                SharpDX.Vector2 upperTextPoint = new SharpDX.Vector2(ChartPanel.X + 10, ChartPanel.Y + 20);
                // Warning:  TextLayout objects must be disposed of after they have been used
                SharpDX.DirectWrite.TextLayout textLayout1 =
                    new SharpDX.DirectWrite.TextLayout(NinjaTrader.Core.Globals.DirectWriteFactory,
                                                       NinjaTrader.Custom.Resource.SampleCustomPlotUpperLeftCorner, textFormat1, ChartPanel.X + ChartPanel.W,
                                                       textFormat1.FontSize);

//			// With the format and layout of the text completed, we can now render the font to the chart
//			RenderTarget.DrawTextLayout(upperTextPoint, textLayout1, textBrushDx,
//				SharpDX.Direct2D1.DrawTextOptions.NoSnap);

//			// 1.7 - Advanced Text Rendering

//			// Font formatting and text layouts can get as complex as you need them to be
//			// This example shows how to use a complete custom font unrelated to the existing user-defined chart control settings
//			// Warning:  TextLayout and TextFormat objects must be disposed of after they have been used
                SharpDX.DirectWrite.TextFormat textFormat2 =
                    new SharpDX.DirectWrite.TextFormat(NinjaTrader.Core.Globals.DirectWriteFactory, "Century Gothic", FontWeight.Bold,
                                                       FontStyle.Italic, 32f);
                SharpDX.DirectWrite.TextLayout textLayout2 =
                    new SharpDX.DirectWrite.TextLayout(NinjaTrader.Core.Globals.DirectWriteFactory,
                                                       NinjaTrader.Custom.Resource.SampleCustomPlotLowerRightCorner, textFormat2, 400, textFormat1.FontSize);

//			// the textLayout object provides a way to measure the described font through a "Metrics" object
//			// This allows you to create new vectors on the chart which are entirely dependent on the "text" that is being rendered
//			// For example, we can create a rectangle that surrounds our font based off the textLayout which would dynamically change if the text used in the layout changed dynamically
                SharpDX.Vector2 lowerTextPoint = new SharpDX.Vector2(ChartPanel.W - textLayout2.Metrics.Width - 5,
                                                                     ChartPanel.Y + (ChartPanel.H - textLayout2.Metrics.Height));
                SharpDX.RectangleF rect1 = new SharpDX.RectangleF(lowerTextPoint.X, lowerTextPoint.Y, textLayout2.Metrics.Width,
                                                                  textLayout2.Metrics.Height);

//			// We can draw the Rectangle based on the TextLayout used above
                RenderTarget.FillRectangle(rect1, smallAreaBrushDx);
//			RenderTarget.DrawRectangle(rect1, smallAreaBrushDx, 2);

                // And render the advanced text layout using the DrawTextLayout() method
                // Note:  When drawing the same text repeatedly, using the DrawTextLayout() method is more efficient than using the DrawText()
                // because the text doesn't need to be formatted and the layout processed with each call
                RenderTarget.DrawTextLayout(lowerTextPoint, textLayout2, textBrushDx, SharpDX.Direct2D1.DrawTextOptions.NoSnap);

                // 1.8 - Cleanup
                // This concludes all of the rendering concepts used in the sample
                // However - there are some final clean up processes we should always provided before we are done

                // If changed, do not forget to set the AntialiasMode back to the default value as described above as a best practice
                RenderTarget.AntialiasMode = oldAntialiasMode;

                // We also need to make sure to dispose of every device dependent resource on each render pass
                // Failure to dispose of these resources will eventually result in unnecessary amounts of memory being used on the chart
                // Although the effects might not be obvious as first, if you see issues related to memory increasing over time
                // Objects such as these should be inspected first
                areaBrushDx.Dispose();
                //		customDXBrush.Dispose();
                //		gradientStopCollection.Dispose();
                //radialGradientBrush.Dispose();
                smallAreaBrushDx.Dispose();
                textBrushDx.Dispose();
                textFormat1.Dispose();
                textFormat2.Dispose();
                textLayout1.Dispose();
                textLayout2.Dispose();
            }
        }
        public void DrawText(string text, int font, int brush, float x, float y, bool bufferText = true)
        {
            if (bufferText)
            {
                var bufferPos = -1;

                for (var i = 0; i < _layoutContainer.Count; i++)
                {
                    if (_layoutContainer[i].Text.Length != text.Length || _layoutContainer[i].Text != text) continue;
                    bufferPos = i;
                    break;
                }

                if (bufferPos == -1)
                {
                    _layoutContainer.Add(new LayoutBuffer(text, new TextLayout(_fontFactory, text, _fontContainer[font], float.MaxValue, float.MaxValue)));
                    bufferPos = _layoutContainer.Count - 1;
                }

                _device.DrawTextLayout(new RawVector2(x, y), _layoutContainer[bufferPos].TextLayout, _brushContainer[brush], DrawTextOptions.NoSnap);
            }
            else
            {
                var layout = new TextLayout(_fontFactory, text, _fontContainer[font], float.MaxValue, float.MaxValue);
                _device.DrawTextLayout(new RawVector2(x, y), layout, _brushContainer[brush]);
                layout.Dispose();
            }
        }