示例#1
0
        public override Surface RenderThumbnail(int maxEdgeLength)
        {
            Size thumbSize = Utility.ComputeThumbnailSize(this.Size, maxEdgeLength);
            Surface thumb = new Surface(thumbSize);

            thumb.SuperSamplingFitSurface(this.surface);

            Surface thumb2 = new Surface(thumbSize);
            thumb2.ClearWithCheckboardPattern();
            UserBlendOps.NormalBlendOp nbop = new UserBlendOps.NormalBlendOp();
            nbop.Apply(thumb2, thumb);

            thumb.Dispose();
            thumb = null;

            return thumb2;
        }
示例#2
0
        protected void RenderCompositionTo(Surface dst, bool highQuality, bool forceUpToDate)
        {
            if (forceUpToDate)
            {
                UpdateComposition(false);
            }

            if (dst.Width == this.compositionSurface.Width && 
                dst.Height == this.compositionSurface.Height)
            {
                dst.ClearWithCheckboardPattern();
                new UserBlendOps.NormalBlendOp().Apply(dst, this.compositionSurface);
            }
            else if (highQuality)
            {
                Surface thumb = new Surface(dst.Size);
                thumb.SuperSamplingFitSurface(this.compositionSurface);

                dst.ClearWithCheckboardPattern();

                new UserBlendOps.NormalBlendOp().Apply(dst, thumb);

                thumb.Dispose();
            }
            else
            {
                this.surfaceBox.RenderTo(dst);
            }
        }
        private void DrawGradient(Graphics g)
        {
            g.PixelOffsetMode = PixelOffsetMode.Half;
            Rectangle gradientRect;

            float gradientAngle;

            switch (this.orientation)
            {
                case Orientation.Horizontal:
                    gradientAngle = 180.0f;
                    break;

                case Orientation.Vertical:
                    gradientAngle = 90.0f;
                    break;

                default:
                    throw new InvalidEnumArgumentException();
            }

            // draw gradient
            gradientRect = ClientRectangle;

            switch (this.orientation)
            {
                case Orientation.Horizontal:
                    gradientRect.Inflate(-triangleHalfLength, -triangleSize + 3);
                    break;

                case Orientation.Vertical:
                    gradientRect.Inflate(-triangleSize + 3, -triangleHalfLength);
                    break;

                default:
                    throw new InvalidEnumArgumentException();
            }

            if (this.customGradient != null && gradientRect.Width > 1 && gradientRect.Height > 1)
            {
                Surface gradientSurface = new Surface(gradientRect.Size);

                using (RenderArgs ra = new RenderArgs(gradientSurface))
                {
                    Utility.DrawColorRectangle(ra.Graphics, ra.Bounds, Color.Transparent, false);

                    if (Orientation == Orientation.Horizontal)
                    {
                        for (int x = 0; x < gradientSurface.Width; ++x)
                        {
                            // TODO: refactor, double buffer, save this computation in a bitmap somewhere
                            double index = (double)(x * (this.customGradient.Length - 1)) / (double)(gradientSurface.Width - 1);
                            int indexL = (int)Math.Floor(index);
                            double t = 1.0 - (index - indexL);
                            int indexR = (int)Math.Min(this.customGradient.Length - 1, Math.Ceiling(index));
                            Color colorL = this.customGradient[indexL];
                            Color colorR = this.customGradient[indexR];

                            double a1 = colorL.A / 255.0;
                            double r1 = colorL.R / 255.0;
                            double g1 = colorL.G / 255.0;
                            double b1 = colorL.B / 255.0;

                            double a2 = colorR.A / 255.0;
                            double r2 = colorR.R / 255.0;
                            double g2 = colorR.G / 255.0;
                            double b2 = colorR.B / 255.0;

                            double at = (t * a1) + ((1.0 - t) * a2);

                            double rt;
                            double gt;
                            double bt;
                            if (at == 0)
                            {
                                rt = 0;
                                gt = 0;
                                bt = 0;
                            }
                            else
                            {
                                rt = ((t * a1 * r1) + ((1.0 - t) * a2 * r2)) / at;
                                gt = ((t * a1 * g1) + ((1.0 - t) * a2 * g2)) / at;
                                bt = ((t * a1 * b1) + ((1.0 - t) * a2 * b2)) / at;
                            }

                            int ap = Utility.Clamp((int)Math.Round(at * 255.0), 0, 255);
                            int rp = Utility.Clamp((int)Math.Round(rt * 255.0), 0, 255);
                            int gp = Utility.Clamp((int)Math.Round(gt * 255.0), 0, 255);
                            int bp = Utility.Clamp((int)Math.Round(bt * 255.0), 0, 255);

                            for (int y = 0; y < gradientSurface.Height; ++y)
                            {
                                ColorBgra src = gradientSurface[x, y];

                                // we are assuming that src.A = 255

                                int rd = ((rp * ap) + (src.R * (255 - ap))) / 255;
                                int gd = ((gp * ap) + (src.G * (255 - ap))) / 255;
                                int bd = ((bp * ap) + (src.B * (255 - ap))) / 255;

                                // TODO: proper alpha blending!
                                gradientSurface[x, y] = ColorBgra.FromBgra((byte)bd, (byte)gd, (byte)rd, 255);
                            }
                        }

                        g.DrawImage(ra.Bitmap, gradientRect, ra.Bounds, GraphicsUnit.Pixel);
                    }
                    else if (Orientation == Orientation.Vertical)
                    {
                        // TODO
                    }
                    else
                    {
                        throw new InvalidEnumArgumentException();
                    }
                }

                gradientSurface.Dispose();
            }
            else
            {
                using (LinearGradientBrush lgb = new LinearGradientBrush(this.ClientRectangle,
                           maxColor, minColor, gradientAngle, false))
                {
                    g.FillRectangle(lgb, gradientRect);
                }
            }

            // fill background
            using (PdnRegion nonGradientRegion = new PdnRegion())
            {
                nonGradientRegion.MakeInfinite();
                nonGradientRegion.Exclude(gradientRect);

                using (SolidBrush sb = new SolidBrush(this.BackColor))
                {
                    g.FillRegion(sb, nonGradientRegion.GetRegionReadOnly());
                }
            }

            // draw value triangles
            for (int i = 0; i < this.vals.Length; i++)
            {
                int pos = ValueToPosition(vals[i]);
                Brush brush;
                Pen pen;

                if (i == highlight) 
                {
                    brush = Brushes.Blue;
                    pen = (Pen)Pens.White.Clone();
                } 
                else 
                {
                    brush = Brushes.Black;
                    pen = (Pen)Pens.Gray.Clone();
                }

                g.SmoothingMode = SmoothingMode.AntiAlias;

                Point a1;
                Point b1;
                Point c1;

                Point a2;
                Point b2;
                Point c2;

                switch (this.orientation)
                {
                    case Orientation.Horizontal:
                        a1 = new Point(pos - triangleHalfLength, 0);
                        b1 = new Point(pos, triangleSize - 1);
                        c1 = new Point(pos + triangleHalfLength, 0);

                        a2 = new Point(a1.X, Height - 1 - a1.Y);
                        b2 = new Point(b1.X, Height - 1 - b1.Y);
                        c2 = new Point(c1.X, Height - 1 - c1.Y);
                        break;

                    case Orientation.Vertical:
                        a1 = new Point(0, pos - triangleHalfLength);
                        b1 = new Point(triangleSize - 1, pos);
                        c1 = new Point(0, pos + triangleHalfLength);

                        a2 = new Point(Width - 1 - a1.X, a1.Y);
                        b2 = new Point(Width - 1 - b1.X, b1.Y);
                        c2 = new Point(Width - 1 - c1.X, c1.Y);
                        break;

                    default:
                        throw new InvalidEnumArgumentException();
                }

                if (this.drawNearNub)
                {
                    g.FillPolygon(brush, new Point[] { a1, b1, c1, a1 });
                }

                if (this.drawFarNub)
                {
                    g.FillPolygon(brush, new Point[] { a2, b2, c2, a2 });
                }

                if (pen != null)
                {
                    if (this.drawNearNub)
                    {
                        g.DrawPolygon(pen, new Point[] { a1, b1, c1, a1 });
                    }

                    if (this.drawFarNub)
                    {
                        g.DrawPolygon(pen, new Point[] { a2, b2, c2, a2 });
                    }

                    pen.Dispose();
                }
            }
        }
示例#4
0
            private void ResizeDocument()
            {
                this.pleaseStop = false;

                // This is only sort of a hack: we must try and allocate enough for 2 extra layer-sized buffers
                // Then we free them immediately. This is just so that if we don't have enough memory that we'll
                // fail sooner rather than later.
                Surface s1 = new Surface(this.newSize);
                Surface s2 = new Surface(this.newSize);

                try
                {
                    foreach (Layer layer in src.Layers)
                    {
                        if (this.pleaseStop)
                        {
                            this.returnVal = false;
                            return;
                        }

                        if (layer is BitmapLayer)
                        {
                            Layer newLayer = ResizeLayer((BitmapLayer)layer, this.newSize.Width, this.newSize.Height, this.algorithm,
                                this.tilesPerLayer, new Procedure(RenderedRectHandler), ref this.pleaseStop);

                            if (newLayer == null)
                            {
                                this.returnVal = false;
                                return;
                            }

                            dst.Layers.Add(newLayer);
                        }
                        else
                        {
                            throw new InvalidOperationException("Resize does not support Layers that are not BitmapLayers");
                        }
                    }
                }

                finally
                {
                    s1.Dispose();
                    s2.Dispose();
                }

                this.returnVal = true;
            }
示例#5
0
        private static BitmapLayer ResizeLayer(BitmapLayer layer, int width, int height, ResamplingAlgorithm algorithm,
            int tileCount, Procedure progressCallback, ref bool pleaseStopMonitor)
        {
            Surface surface = new Surface(width, height);
            surface.Clear(ColorBgra.FromBgra(255, 255, 255, 0));

            PaintDotNet.Threading.ThreadPool threadPool = new PaintDotNet.Threading.ThreadPool();
            int rectCount;
            
            if (tileCount == 0)
            {
                rectCount = Processor.LogicalCpuCount;
            }
            else
            {
                rectCount = tileCount;
            }

            Rectangle[] rects = new Rectangle[rectCount];
            Utility.SplitRectangle(surface.Bounds, rects);

            FitSurfaceContext fsc = new FitSurfaceContext(surface, layer.Surface, rects, algorithm);

            if (progressCallback != null)
            {
                fsc.RenderedRect += progressCallback;
            }

            WaitCallback callback = new WaitCallback(fsc.FitSurface);

            for (int i = 0; i < rects.Length; ++i)
            {
                if (pleaseStopMonitor)
                {
                    break;
                }
                else
                {
                    threadPool.QueueUserWorkItem(callback, BoxedConstants.GetInt32(i));
                }
            }

            threadPool.Drain();
            threadPool.DrainExceptions();

            if (pleaseStopMonitor)
            {
                surface.Dispose();
                surface = null;
            }

            BitmapLayer newLayer;

            if (surface == null)
            {
                newLayer = null;
            }
            else
            {
                newLayer = new BitmapLayer(surface, true);
                newLayer.LoadProperties(layer.SaveProperties());
            }

            if (progressCallback != null)
            {
                fsc.RenderedRect -= progressCallback;
            }

            return newLayer;
        }
示例#6
0
        private Surface GetDoubleBuffer(Size size)
        {
            Surface localDBSurface = null;
            Size    oldSize        = new Size(0, 0);

            // If we already have a double buffer surface reference, but if that surface
            // is already disposed then don't worry about it.
            if (this.doubleBufferSurface != null && this.doubleBufferSurface.IsDisposed)
            {
                oldSize = this.doubleBufferSurface.Size;
                this.doubleBufferSurface = null;
            }

            // If we already have a double buffer surface reference, but if that surface
            // is too small, then nuke it.
            if (this.doubleBufferSurface != null &&
                (this.doubleBufferSurface.Width < size.Width || this.doubleBufferSurface.Height < size.Height))
            {
                oldSize = this.doubleBufferSurface.Size;
                this.doubleBufferSurface.Dispose();
                this.doubleBufferSurface   = null;
                doubleBufferSurfaceWeakRef = null;
            }

            // If we don't have a double buffer, then we'd better get one.
            if (this.doubleBufferSurface != null)
            {
                // Got one!
                localDBSurface = this.doubleBufferSurface;
            }
            else if (doubleBufferSurfaceWeakRef != null)
            {
                // First, try to get the one that's already shared amongst all SurfaceBox instances.
                localDBSurface = doubleBufferSurfaceWeakRef.Target;

                // If it's disposed, then forget about it.
                if (localDBSurface != null && localDBSurface.IsDisposed)
                {
                    oldSize                    = localDBSurface.Size;
                    localDBSurface             = null;
                    doubleBufferSurfaceWeakRef = null;
                }
            }

            // Make sure the surface is big enough.
            if (localDBSurface != null && (localDBSurface.Width < size.Width || localDBSurface.Height < size.Height))
            {
                oldSize = localDBSurface.Size;
                localDBSurface.Dispose();
                localDBSurface             = null;
                doubleBufferSurfaceWeakRef = null;
            }

            // So, do we have a surface? If not then we'd better make one.
            if (localDBSurface == null)
            {
                Size newSize = new Size(Math.Max(size.Width, oldSize.Width), Math.Max(size.Height, oldSize.Height));
                localDBSurface             = new Surface(newSize.Width, newSize.Height);
                doubleBufferSurfaceWeakRef = new WeakReference <Surface>(localDBSurface);
            }

            this.doubleBufferSurface = localDBSurface;
            Surface window = localDBSurface.CreateWindow(0, 0, size.Width, size.Height);

            return(window);
        }
        private void DrawGradient(Graphics g)
        {
            g.PixelOffsetMode = PixelOffsetMode.Half;
            Rectangle gradientRect;

            float gradientAngle;

            switch (this.orientation)
            {
            case Orientation.Horizontal:
                gradientAngle = 180.0f;
                break;

            case Orientation.Vertical:
                gradientAngle = 90.0f;
                break;

            default:
                throw new InvalidEnumArgumentException();
            }

            // draw gradient
            gradientRect = ClientRectangle;

            switch (this.orientation)
            {
            case Orientation.Horizontal:
                gradientRect.Inflate(-triangleHalfLength, -triangleSize + 3);
                break;

            case Orientation.Vertical:
                gradientRect.Inflate(-triangleSize + 3, -triangleHalfLength);
                break;

            default:
                throw new InvalidEnumArgumentException();
            }

            if (this.customGradient != null && gradientRect.Width > 1 && gradientRect.Height > 1)
            {
                Surface gradientSurface = new Surface(gradientRect.Width, gradientRect.Height);

                using (RenderArgs ra = new RenderArgs(gradientSurface))
                {
                    Utility.DrawColorRectangle(ra.Graphics, ra.Bounds, Color.Transparent, false);

                    if (Orientation == Orientation.Horizontal)
                    {
                        for (int x = 0; x < gradientSurface.Width; ++x)
                        {
                            // TODO: refactor, double buffer, save this computation in a bitmap somewhere
                            double index  = (double)(x * (this.customGradient.Length - 1)) / (double)(gradientSurface.Width - 1);
                            int    indexL = (int)Math.Floor(index);
                            double t      = 1.0 - (index - indexL);
                            int    indexR = (int)Math.Min(this.customGradient.Length - 1, Math.Ceiling(index));
                            Color  colorL = this.customGradient[indexL];
                            Color  colorR = this.customGradient[indexR];

                            double a1 = colorL.A / 255.0;
                            double r1 = colorL.R / 255.0;
                            double g1 = colorL.G / 255.0;
                            double b1 = colorL.B / 255.0;

                            double a2 = colorR.A / 255.0;
                            double r2 = colorR.R / 255.0;
                            double g2 = colorR.G / 255.0;
                            double b2 = colorR.B / 255.0;

                            double at = (t * a1) + ((1.0 - t) * a2);

                            double rt;
                            double gt;
                            double bt;
                            if (at == 0)
                            {
                                rt = 0;
                                gt = 0;
                                bt = 0;
                            }
                            else
                            {
                                rt = ((t * a1 * r1) + ((1.0 - t) * a2 * r2)) / at;
                                gt = ((t * a1 * g1) + ((1.0 - t) * a2 * g2)) / at;
                                bt = ((t * a1 * b1) + ((1.0 - t) * a2 * b2)) / at;
                            }

                            int ap = Utility.Clamp((int)Math.Round(at * 255.0), 0, 255);
                            int rp = Utility.Clamp((int)Math.Round(rt * 255.0), 0, 255);
                            int gp = Utility.Clamp((int)Math.Round(gt * 255.0), 0, 255);
                            int bp = Utility.Clamp((int)Math.Round(bt * 255.0), 0, 255);

                            for (int y = 0; y < gradientSurface.Height; ++y)
                            {
                                ColorBgra src = gradientSurface[x, y];

                                // we are assuming that src.A = 255

                                int rd = ((rp * ap) + (src.R * (255 - ap))) / 255;
                                int gd = ((gp * ap) + (src.G * (255 - ap))) / 255;
                                int bd = ((bp * ap) + (src.B * (255 - ap))) / 255;

                                // TODO: proper alpha blending!
                                gradientSurface[x, y] = ColorBgra.FromBgra((byte)bd, (byte)gd, (byte)rd, 255);
                            }
                        }

                        g.DrawImage(ra.Bitmap, gradientRect, ra.Bounds, GraphicsUnit.Pixel);
                    }
                    else if (Orientation == Orientation.Vertical)
                    {
                        // TODO
                    }
                    else
                    {
                        throw new InvalidEnumArgumentException();
                    }
                }

                gradientSurface.Dispose();
            }
            else
            {
                using (LinearGradientBrush lgb = new LinearGradientBrush(this.ClientRectangle,
                                                                         maxColor, minColor, gradientAngle, false))
                {
                    g.FillRectangle(lgb, gradientRect);
                }
            }

            // fill background
            using (Region nonGradientRegion = new Region())
            {
                nonGradientRegion.MakeInfinite();
                nonGradientRegion.Exclude(gradientRect);

                using (SolidBrush sb = new SolidBrush(this.BackColor))
                {
                    g.FillRegion(sb, nonGradientRegion);
                }
            }

            // draw value triangles
            for (int i = 0; i < this.vals.Length; i++)
            {
                int   pos = ValueToPosition(vals[i]);
                Brush brush;
                Pen   pen;

                if (i == highlight)
                {
                    brush = Brushes.Blue;
                    pen   = (Pen)Pens.White.Clone();
                }
                else
                {
                    brush = Brushes.Black;
                    pen   = (Pen)Pens.Gray.Clone();
                }

                g.SmoothingMode = SmoothingMode.AntiAlias;

                Point a1;
                Point b1;
                Point c1;

                Point a2;
                Point b2;
                Point c2;

                switch (this.orientation)
                {
                case Orientation.Horizontal:
                    a1 = new Point(pos - triangleHalfLength, 0);
                    b1 = new Point(pos, triangleSize - 1);
                    c1 = new Point(pos + triangleHalfLength, 0);

                    a2 = new Point(a1.X, Height - 1 - a1.Y);
                    b2 = new Point(b1.X, Height - 1 - b1.Y);
                    c2 = new Point(c1.X, Height - 1 - c1.Y);
                    break;

                case Orientation.Vertical:
                    a1 = new Point(0, pos - triangleHalfLength);
                    b1 = new Point(triangleSize - 1, pos);
                    c1 = new Point(0, pos + triangleHalfLength);

                    a2 = new Point(Width - 1 - a1.X, a1.Y);
                    b2 = new Point(Width - 1 - b1.X, b1.Y);
                    c2 = new Point(Width - 1 - c1.X, c1.Y);
                    break;

                default:
                    throw new InvalidEnumArgumentException();
                }

                if (this.drawNearNub)
                {
                    g.FillPolygon(brush, new Point[] { a1, b1, c1, a1 });
                }

                if (this.drawFarNub)
                {
                    g.FillPolygon(brush, new Point[] { a2, b2, c2, a2 });
                }

                if (pen != null)
                {
                    if (this.drawNearNub)
                    {
                        g.DrawPolygon(pen, new Point[] { a1, b1, c1, a1 });
                    }

                    if (this.drawFarNub)
                    {
                        g.DrawPolygon(pen, new Point[] { a2, b2, c2, a2 });
                    }

                    pen.Dispose();
                }
            }
        }
        protected virtual void OnPreRenderComplete(RenderArgs dstArgs, RenderArgs srcArgs)
        {
            Rectangle[] rois;
            Surface surfaceCopy;
            RenderArgs args;
            RenderArgs currentSourceArgs;
            RenderArgs currentDestinationArgs;
            Rectangle boundingTile;

            if (FullImageSelected(srcArgs.Bounds))
            {
                boundingTile = dstArgs.Bounds;
            }
            else
            {
                boundingTile = this.EnvironmentParameters.GetSelection(dstArgs.Bounds).GetBoundsInt();
                boundingTile.Inflate(base.ApronSize, base.ApronSize);
                boundingTile.Intersect(dstArgs.Bounds);
            }

            rois = base.SliceRectangles(new Rectangle[] { boundingTile });

            surfaceCopy = new Surface(dstArgs.Width, dstArgs.Height, SurfaceCreationFlags.DoNotZeroFillHint); //dstArgs.Surface.Clone();
            args = new RenderArgs(surfaceCopy);

            currentSourceArgs = srcArgs;
            currentDestinationArgs = args;

            this.pass = 1;
            OnBeginPass(this.pass, currentDestinationArgs, currentSourceArgs);
            OnRenderRegion(rois, currentDestinationArgs, currentSourceArgs);

            if (Passes == 1)
            {
                CopyRois(this.EnvironmentParameters.GetSelection(dstArgs.Bounds).GetRegionScansInt(),
                    dstArgs.Surface,
                    surfaceCopy);
                surfaceCopy.Dispose();
            }
            else
            {
                if (base.tmr != null)
                {
                    base.tmr = new System.Diagnostics.Stopwatch();
                    base.tmr.Start();
                }

                this.pass = 2;
                if (FullImageSelected(srcArgs.Bounds))
                {
                    currentSourceArgs = args;
                    currentDestinationArgs = dstArgs;

                    OnBeginPass(this.pass, currentDestinationArgs, currentSourceArgs);
                    OnRenderRegion(rois, currentDestinationArgs, currentSourceArgs);
                    surfaceCopy.Dispose();
                }
                else
                {
                    Surface surfaceCopy2;
                    RenderArgs args2;
                    surfaceCopy2 = new Surface(dstArgs.Width, dstArgs.Height, SurfaceCreationFlags.DoNotZeroFillHint);
                    args2 = new RenderArgs(surfaceCopy2);

                    currentSourceArgs = args;
                    currentDestinationArgs = args2;

                    OnBeginPass(this.pass, currentDestinationArgs, currentSourceArgs);
                    OnRenderRegion(rois, currentDestinationArgs, currentSourceArgs);
                    surfaceCopy.Dispose();

                    CopyRois(this.EnvironmentParameters.GetSelection(dstArgs.Bounds).GetRegionScansInt(),
                        dstArgs.Surface,
                        surfaceCopy2);

                    surfaceCopy2.Dispose();
                }
            }
        }