Ejemplo n.º 1
0
        public void Test_MonadLaw()
        {
            // return x >>= f == f x
            // m >>= return == m
            // (m >>= f) >>= g == m >>= (\x -> f x >>= g)

            {   // return x >>= f == f x
                Func <int, MaybeTask <int> > func = i => MaybeTask.Return(DummyTask(i));
                var result1 = func(10);
                var result2 = MaybeTask.Return(DummyTask(10)).Bind(func);
                Assert.Equal(result1.Awaitor.Result, result2.Awaitor.Result);
            }

            {   // m >>= return == m
                var result1 = MaybeTask.Return(DummyTask(10));
                var result2 = result1.Bind(i => MaybeTask.Return(DummyTask(i)));
                Assert.Equal(result1.Awaitor.Result, result2.Awaitor.Result);
            }

            {   // (m >>= f) >>= g == m >>= (\x -> f x >>= g)
                Func <int, MaybeTask <int> > f = i => MaybeTask.Return(DummyTask(i + 1));
                Func <int, MaybeTask <int> > g = i => MaybeTask.Return(DummyTask(i + 10));
                var m = MaybeTask.Return(DummyTask(10));

                var result1 = m.Bind(f).Bind(g);
                var result2 = m.Bind(i => f(i).Bind(g));
                Assert.Equal(result1.Awaitor.Result, result2.Awaitor.Result);
            }
        }
        internal static MaybeTask <IImageProvider> Bind(MaybeTask <IImageProvider> currentImage, MaybeTask <IImageProvider> previousImage)
        {
            // Note: the code below is written with static lambdas that don't close over any variables. This avoids heap allocations.

            if (currentImage.IsSynchronous)
            {
                if (previousImage.IsSynchronous)
                {
                    return(new MaybeTask <IImageProvider>(Bind(currentImage.Result, previousImage.Result)));
                }
                else // previousImage.IsAsynchronous
                {
                    return(new MaybeTask <IImageProvider>(previousImage.Task.ContinueWith(BindPreviousAsyncToCurrentSync, currentImage.Result, ContinuationOptions)));
                }
            }
            else // currentImage.IsAsynchronous
            {
                if (previousImage.IsSynchronous)
                {
                    return(new MaybeTask <IImageProvider>(currentImage.Task.ContinueWith(BindPreviousSyncToCurrentAsync, previousImage.Result, ContinuationOptions)));
                }
                else // previousImage.IsAsynchronous
                {
                    return(new MaybeTask <IImageProvider>(currentImage.Task.ContinueWith(BindPreviousAsyncToCurrentAsync, previousImage.Task, ContinuationOptions).Unwrap()));
                }
            }
        }
        internal static MaybeTask<IImageProvider> Bind(MaybeTask<IImageProvider> currentImage, MaybeTask<IImageProvider> previousImage)
        {
            // Note: the code below is written with static lambdas that don't close over any variables. This avoids heap allocations.

            if (currentImage.IsSynchronous)
            {
                if (previousImage.IsSynchronous)
                {
                    return new MaybeTask<IImageProvider>(Bind(currentImage.Result, previousImage.Result));
                }
                else // previousImage.IsAsynchronous
                {
                    return new MaybeTask<IImageProvider>(previousImage.Task.ContinueWith(BindPreviousAsyncToCurrentSync, currentImage.Result, ContinuationOptions));
                }
            }
            else // currentImage.IsAsynchronous
            {
                if (previousImage.IsSynchronous)
                {
                    return new MaybeTask<IImageProvider>(currentImage.Task.ContinueWith(BindPreviousSyncToCurrentAsync, previousImage.Result, ContinuationOptions));
                }
                else // previousImage.IsAsynchronous
                {
                    return new MaybeTask<IImageProvider>(currentImage.Task.ContinueWith(BindPreviousAsyncToCurrentAsync, previousImage.Task, ContinuationOptions).Unwrap());
                }
            }
        }
Ejemplo n.º 4
0
        public void Test_Awaitor1()
        {
            // 単一Task
            var state  = MaybeTask.From(DummyTask(10));
            var result = state.Awaitor.Result;

            Assert.True(result.HasValue);
            Assert.Equal(10, Polluter.Pollute(result));
        }
Ejemplo n.º 5
0
        public void Test_Nothing()
        {
            // Nothingを返すTaskはNothingになる
            var state = MaybeTask
                        .From(NothingTask());
            var result = state.Awaitor.Result;

            Assert.False(result.HasValue);
        }
 public void MaybeTaskRepresentsResult()
 {
     object o = new object();
     var mt = new MaybeTask<object>(o);
     Assert.IsTrue(mt.WasSynchronous);
     Assert.IsTrue(mt.IsSynchronous);
     Assert.IsFalse(mt.IsEmpty);
     Assert.IsNull(mt.Task);
     Assert.AreEqual(o, mt.Result);
 }
 public void MaybeTaskRepresentsAlreadyCompletedTask()
 {
     object o = new object();
     var mt = new MaybeTask<object>(Task.FromResult(o));
     Assert.IsFalse(mt.WasSynchronous);
     Assert.IsTrue(mt.IsSynchronous); // result is available now
     Assert.IsFalse(mt.IsEmpty);
     Assert.IsNotNull(mt.Task);
     Assert.AreEqual(o, mt.Result);
 }
Ejemplo n.º 8
0
        public void Test_Nothing2()
        {
            // NothingをかえすTaskがある場合はNothingになる。
            var state = MaybeTask
                        .From(DummyTask(10))
                        .Map(NothingTask());
            var result = state.Awaitor.Result;

            Assert.False(result.HasValue);
        }
Ejemplo n.º 9
0
        public void MaybeTaskRepresentsAlreadyCompletedTask()
        {
            object o  = new object();
            var    mt = new MaybeTask <object>(Task.FromResult(o));

            Assert.IsFalse(mt.WasSynchronous);
            Assert.IsTrue(mt.IsSynchronous); // result is available now
            Assert.IsFalse(mt.IsEmpty);
            Assert.IsNotNull(mt.Task);
            Assert.AreEqual(o, mt.Result);
        }
Ejemplo n.º 10
0
        public void MaybeTaskRepresentsResult()
        {
            object o  = new object();
            var    mt = new MaybeTask <object>(o);

            Assert.IsTrue(mt.WasSynchronous);
            Assert.IsTrue(mt.IsSynchronous);
            Assert.IsFalse(mt.IsEmpty);
            Assert.IsNull(mt.Task);
            Assert.AreEqual(o, mt.Result);
        }
Ejemplo n.º 11
0
        public void Test_Awaitor2()
        {
            // 2つのTaskを直列化
            var state = MaybeTask
                        .From(DummyTask(10))
                        .Map(DummyTask(15));
            var result = state.Awaitor.Result;

            Assert.True(result.HasValue);
            Assert.Equal(10, Polluter.Pollute(result).Item1);
            Assert.Equal(15, Polluter.Pollute(result).Item2);
        }
Ejemplo n.º 12
0
        public void MaybeTaskRepresentsAlreadyCanceledTask()
        {
            object o   = new object();
            var    tcs = new TaskCompletionSource <object>();

            tcs.SetCanceled();
            var mt = new MaybeTask <object>(tcs.Task);

            Assert.IsFalse(mt.WasSynchronous);
            Assert.IsTrue(mt.IsSynchronous);
            Assert.IsFalse(mt.IsEmpty);
            Assert.IsNotNull(mt.Task);
            Assert.ThrowsException <AggregateException>(() => mt.Result);
        }
 public void MaybeTaskRepresentsCancelingTask()
 {
     object o = new object();
     var tcs = new TaskCompletionSource<object>();
     var mt = new MaybeTask<object>(tcs.Task);
     Assert.IsFalse(mt.WasSynchronous);
     Assert.IsFalse(mt.IsSynchronous);
     Assert.IsFalse(mt.IsEmpty);
     Assert.IsNotNull(mt.Task);
     tcs.SetCanceled();
     Assert.IsFalse(mt.WasSynchronous);
     Assert.IsTrue(mt.IsSynchronous);
     Assert.ThrowsException<AggregateException>(() => mt.Result);
 }
 public void MaybeTaskRepresentsCompletingTask()
 {
     object o = new object();
     var tcs = new TaskCompletionSource<object>();
     var mt = new MaybeTask<object>(tcs.Task);
     Assert.IsFalse(mt.WasSynchronous);
     Assert.IsFalse(mt.IsSynchronous);
     Assert.IsFalse(mt.IsEmpty);
     Assert.IsNotNull(mt.Task);
     tcs.SetResult(o);
     Assert.IsFalse(mt.WasSynchronous);
     Assert.IsTrue(mt.IsSynchronous);
     Assert.AreEqual(o, mt.Result);
 }
Ejemplo n.º 15
0
        public void Test_Awaitor3_Flat()
        {
            // 3つのTaskを直列化
            // 結果は自身で定義する。
            var state = MaybeTask
                        .From(DummyTask(10))
                        .Map(async prev => (await DummyTask(15)).Map(next => (prev, next)))
                        .Map(async prev => (await DummyTask(20)).Map(next => (prev.Item1, prev.Item2, next)));
            var result = state.Awaitor.Result;

            Assert.True(result.HasValue);
            Assert.Equal(10, Polluter.Pollute(result).Item1);
            Assert.Equal(15, Polluter.Pollute(result).Item2);
            Assert.Equal(20, Polluter.Pollute(result).Item3);
        }
Ejemplo n.º 16
0
        public void MaybeTaskRepresentsCompletingTask()
        {
            object o   = new object();
            var    tcs = new TaskCompletionSource <object>();
            var    mt  = new MaybeTask <object>(tcs.Task);

            Assert.IsFalse(mt.WasSynchronous);
            Assert.IsFalse(mt.IsSynchronous);
            Assert.IsFalse(mt.IsEmpty);
            Assert.IsNotNull(mt.Task);
            tcs.SetResult(o);
            Assert.IsFalse(mt.WasSynchronous);
            Assert.IsTrue(mt.IsSynchronous);
            Assert.AreEqual(o, mt.Result);
        }
Ejemplo n.º 17
0
        public void Test_Awaitor3()
        {
            // 3つのTaskを直列化。
            // 結果はTuple<Tuple<1, 2>, 3>
            var state = MaybeTask
                        .From(DummyTask(10))
                        .Map(DummyTask(15))
                        .Map(DummyTask(20));
            var result = state.Awaitor.Result;

            Assert.True(result.HasValue);
            Assert.Equal(10, Polluter.Pollute(result).Item1.Item1);
            Assert.Equal(15, Polluter.Pollute(result).Item1.Item2);
            Assert.Equal(20, Polluter.Pollute(result).Item2);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Construct a layer style.
        /// </summary>
        /// <param name="blendFunction">Blend function to use when combining the result of this layer with the previous.</param>
        /// <param name="opacity">The opacity of the layer.</param>
        /// <param name="maskImage">If non-null, specifies a mask image that controls how this layer is blended onto the preceding one. See <see cref="Lumia.Imaging.Compositing.BlendEffect"/>.</param>
        /// <param name="targetArea">If non-empty, positions and scales the layer within the bounds of the preceding one. See <see cref="Lumia.Imaging.Compositing.BlendEffect"/>.</param>
        /// <returns>A layer style.</returns>
        public LayerStyle(BlendFunction blendFunction, double opacity, MaybeTask <IImageProvider> maskImage, Rect?targetArea = null)
        {
            BlendFunction = blendFunction;
            Opacity       = opacity;
            TargetArea    = targetArea;

            if (!maskImage.IsEmpty)
            {
                MaskResolver = context => maskImage;
            }
            else
            {
                MaskResolver = null;
            }
        }
Ejemplo n.º 19
0
        private Layer GetActiveBackgroundLayer(MaybeTask <IImageProvider> backgroundImage, Size backgroundImageSize)
        {
            var backgroundLayer = this[0];

            // Replace BG layer?
            if (!backgroundImage.IsEmpty)
            {
                if (backgroundLayer != EmptyLayer)
                {
                    throw new ArgumentException("LayerList was constructed with a background image, do not pass one into ToImageProvider.", "backgroundImage");
                }

                backgroundLayer = new Layer(LayerStyle.Normal(), backgroundImage, backgroundImageSize);
            }

            return(backgroundLayer);
        }
Ejemplo n.º 20
0
        public void Test_Awaitor3_Flat2()
        {
            // 3つのTaskを直列化
            // 結果は自身で定義する。
            // Maybe a -> (a -> Task<Maybe (a b)>) -> Maybe (a b)は実装がわかりにくいので自動化
            // Maybe a -> (a -> Task<(a Maybe b)>) -> (a Maybe b)とならないように。
            var state = MaybeTask
                        .From(DummyTask(10))
                        .Map(prev => DummyTask(15), (prev, next) => Optional.Just((prev, next)))
                        .Map(prev => DummyTask(20), (prev, next) => Optional.Just((prev.Item1, prev.Item2, next)));
            var result = state.Awaitor.Result;

            Assert.True(result.HasValue);
            Assert.Equal(10, Polluter.Pollute(result).Item1);
            Assert.Equal(15, Polluter.Pollute(result).Item2);
            Assert.Equal(20, Polluter.Pollute(result).Item3);
        }
Ejemplo n.º 21
0
        public void Test_Nothing3()
        {
            bool called1 = false;
            bool called2 = false;
            // NothingをかえすTaskがある場合はNothingになる。
            // ※Nothingの前のTaskを返却する関数は実行される。
            // ※Nothingの後のTaskを返却する関数は実行されない。
            var state = MaybeTask
                        .From(DummyTask(10))
                        .Map(prev => CallbackTask(() => { called1 = true; return(1); }))
                        .Map(NothingTask())
                        .Map(prev => CallbackTask(() => { called2 = true; return(1); }));
            var result = state.Awaitor.Result;

            Assert.False(result.HasValue);
            Assert.True(called1);
            Assert.False(called2);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Resolve a MaybeTask&lt;IImageProvider&gt; that represents the whole layer stack.
        /// </summary>
        /// <param name="backgroundImage">A MaybeTask&lt;IImageProvider&gt; resulting in the image to use for the background layer.</param>
        /// <param name="backgroundImageSize">Optionally, the size of the background image. If omitted, the natural size of the source will be used, but the size will not available in the LayerLinkingContext for lazy resolvers.</param>
        /// <param name="renderSizeHint">Optionally, the size of image that the layer stack will be rendered to. Note that this is just a hint, the resulting <see cref="IImageProvider" /> should also be rendered at this size by the user.</param>
        /// <returns>An IImageProvider that represents the whole layer stack.</returns>
        public MaybeTask <IImageProvider> ToImageProvider(MaybeTask <IImageProvider> backgroundImage, Size backgroundImageSize = default(Size), Size renderSizeHint = default(Size))
        {
            var backgroundLayer = GetActiveBackgroundLayer(backgroundImage, backgroundImageSize);

            var layerContextInvariants = new LayerContext.Invariants(backgroundLayer, backgroundImage, renderSizeHint);

            var layerContexts = new LayerContext[Count];

            layerContexts[0] = new LayerContext(layerContextInvariants, null, backgroundLayer, 0);

            backgroundImage = backgroundLayer.GetImageProvider(layerContexts[0]);

            var currentImage = backgroundImage;

            for (int layerIndex = 1; layerIndex < layerContexts.Length; ++layerIndex)
            {
                Debug.WriteLine("Resolving layer " + layerIndex);

                var context = new LayerContext(layerContextInvariants, layerContexts[layerIndex - 1].CurrentLayer, this[layerIndex], layerIndex);

                context.PreviousImage = currentImage;

                currentImage = context.CurrentLayer.GetImageProvider(context);
                Debug.Assert(!currentImage.IsEmpty, "Resolved imageprovider is null.");

                // Bind the previous image as the source of the current one.
                currentImage = LayerSource.Bind(currentImage, context.PreviousImage);

                // If blending is used, wrap the current image in a BlendEffect and bind the source to it as well.
                var blendedCurrentImage = LayerBlend.Apply(context, currentImage);
                if (!blendedCurrentImage.IsEmpty)
                {
                    blendedCurrentImage = LayerSource.Bind(blendedCurrentImage, context.PreviousImage);
                    currentImage        = blendedCurrentImage;
                }

                layerContexts[layerIndex] = context;
            }

            Debug.WriteLine("Resolved final image provider.");

            return(currentImage);
        }
Ejemplo n.º 23
0
        internal static MaybeTask <IImageProvider> Apply(LayerContext context, MaybeTask <IImageProvider> image)
        {
            var layer = context.CurrentLayer;

            var mask = new MaybeTask <IImageProvider>();

            if (layer.Style.MaskResolver != null)
            {
                mask = layer.Style.MaskResolver(context);
            }

            const double opacityEpsilon = 0.01;
            bool         isOpaque       = context.CurrentLayerIndex == 0 ||
                                          ((layer is AdjustmentLayer) &&
                                           layer.Style.BlendFunction == BlendFunction.Normal &&
                                           Math.Abs(layer.Style.Opacity - 1.0) <= opacityEpsilon);

            if (isOpaque)
            {
                return(new MaybeTask <IImageProvider>());
            }

            // This whole unfolded mess may look silly, but allows us to do the bare minimum.
            // It defers resolving task-ness until later, so there are less objects allocated on average.
            // Using async/await causes quite a few extra objects on the heap.
            // We also try to avoid Task.FromResult which is at least one extra Task on the heap.
            // Task.WhenAll is not efficient in .NET 4.0, and it's unknown how that translates to Silverlight for WP 8.0.

            var blendParams = new BlendParams
            {
                PreviousImage = context.PreviousImage,
                Image         = image,
                Mask          = mask,
                Style         = layer.Style
            };

            if (blendParams.PreviousImage.IsSynchronous)
            {
                if (blendParams.Image.IsSynchronous)
                {
                    if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty)
                    {
                        return(new MaybeTask <IImageProvider>(CreateBlendEffect(blendParams)));
                    }
                    else
                    {
                        return(new MaybeTask <IImageProvider>(
                                   mask.Task.ContinueWith((maskTask, state) =>
                        {
                            var bp = (BlendParams)state;
                            bp.Mask = new MaybeTask <IImageProvider>(maskTask.Result);

                            return CreateBlendEffect(bp);
                        }, blendParams, ContinuationOptions)));
                    }
                }
                else // image.IsAsynchronous
                {
                    if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty)
                    {
                        return(new MaybeTask <IImageProvider>(
                                   image.Task.ContinueWith((imageTask, state) =>
                        {
                            var bp = (BlendParams)state;
                            bp.Image = new MaybeTask <IImageProvider>(imageTask.Result);

                            return CreateBlendEffect(bp);
                        }, blendParams, ContinuationOptions)));
                    }
                    else // mask.IsAsynchronous
                    {
                        return(new MaybeTask <IImageProvider>(
                                   image.Task.ContinueWith((imageTask, state) =>
                        {
                            var bp = (BlendParams)state;
                            bp.Image = new MaybeTask <IImageProvider>(imageTask.Result);

                            return bp.Mask.Task.ContinueWith((maskTask, state2) =>
                            {
                                var bp2 = (BlendParams)state2;
                                bp2.Mask = new MaybeTask <IImageProvider>(maskTask.Result);

                                return CreateBlendEffect(bp2);
                            }, bp, ContinuationOptions);
                        }, blendParams, ContinuationOptions).Unwrap()));
                    }
                }
            }
            else // previousImage.IsAsynchronous
            {
                if (blendParams.Image.IsSynchronous)
                {
                    if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty)
                    {
                        return(new MaybeTask <IImageProvider>(
                                   blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) =>
                        {
                            var bp = (BlendParams)state;
                            bp.PreviousImage = new MaybeTask <IImageProvider>(previousImageTask.Result);

                            return CreateBlendEffect(bp);
                        }, blendParams, ContinuationOptions)));
                    }
                    else // mask.IsAsynchronous
                    {
                        return(new MaybeTask <IImageProvider>(
                                   blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state2) =>
                        {
                            var blendParams2 = (BlendParams)state2;
                            blendParams2.PreviousImage = new MaybeTask <IImageProvider>(previousImageTask.Result);

                            return blendParams2.Mask.Task.ContinueWith((maskTask, state3) =>
                            {
                                var blendParams3 = (BlendParams)state3;
                                blendParams3.Mask = new MaybeTask <IImageProvider>(maskTask.Result);

                                return CreateBlendEffect(blendParams3);
                            }, blendParams2, ContinuationOptions);
                        }, blendParams, ContinuationOptions).Unwrap()));
                    }
                }
                else // image.IsAsynchronous
                {
                    if (mask.IsSynchronous || mask.IsEmpty)
                    {
                        return(new MaybeTask <IImageProvider>(
                                   blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) =>
                        {
                            var bp = (BlendParams)state;
                            bp.PreviousImage = new MaybeTask <IImageProvider>(previousImageTask.Result);

                            return bp.Image.Task.ContinueWith((imageTask, state2) =>
                            {
                                var bp2 = (BlendParams)state2;
                                bp2.Image = new MaybeTask <IImageProvider>(imageTask.Result);

                                return CreateBlendEffect(bp2);
                            }, bp, ContinuationOptions);
                        }, blendParams, ContinuationOptions).Unwrap()));
                    }
                    else // mask.IsAsynchronous
                    {
                        return(new MaybeTask <IImageProvider>(
                                   blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) =>
                        {
                            var bp = (BlendParams)state;
                            bp.PreviousImage = new MaybeTask <IImageProvider>(previousImageTask.Result);

                            return bp.Image.Task.ContinueWith((imageTask, state2) =>
                            {
                                var bp2 = (BlendParams)state2;
                                bp2.Image = new MaybeTask <IImageProvider>(imageTask.Result);

                                return bp2.Mask.Task.ContinueWith((maskTask, state3) =>
                                {
                                    var bp3 = (BlendParams)state3;
                                    bp3.Mask = new MaybeTask <IImageProvider>(maskTask.Result);

                                    return CreateBlendEffect(bp3);
                                }, bp2, ContinuationOptions);
                            }, bp, ContinuationOptions);
                        }, blendParams, ContinuationOptions).Unwrap().Unwrap()));
                    }
                }
            }

            throw new NotImplementedException();
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Construct a layer style.
        /// </summary>
        /// <param name="blendFunction">Blend function to use when combining the result of this layer with the previous.</param>
        /// <param name="opacity">The opacity of the layer.</param>
        /// <param name="maskImage">If non-null, specifies a mask image that controls how this layer is blended onto the preceding one. See <see cref="Lumia.Imaging.Compositing.BlendEffect"/>.</param>
        /// <param name="targetArea">If non-empty, positions and scales the layer within the bounds of the preceding one. See <see cref="Lumia.Imaging.Compositing.BlendEffect"/>.</param>
        /// <returns>A layer style.</returns>
        public LayerStyle(BlendFunction blendFunction, double opacity, MaybeTask<IImageProvider> maskImage, Rect? targetArea = null)
        {
            BlendFunction = blendFunction;
            Opacity = opacity;
            TargetArea = targetArea;

            if (!maskImage.IsEmpty)
            {
                MaskResolver = context => maskImage;
            }
            else
            {
                MaskResolver = null;
            }
        }
Ejemplo n.º 25
0
 /// <summary>
 /// Creates a layer with image content.
 /// </summary>
 /// <param name="layerStyle">Description of how to blend this layer onto the preceding one.</param>
 /// <param name="imageProvider">A value that represents either the <see cref="IImageProvider" /> that is the image content or a task that asynchronously results in it.</param>
 /// <param name="imageSize">Optional, the size of the image content of the layer.</param>
 public Layer(LayerStyle layerStyle, MaybeTask <IImageProvider> imageProvider, Size imageSize = default(Size))
 {
     Style            = layerStyle;
     GetImageProvider = context => imageProvider;
     ImageSize        = imageSize;
 }
 /// <summary>
 /// Creates an adjustment layer containing the specified effect.
 /// </summary>
 /// <param name="layerStyle">Layer style to use for this layer.</param>
 /// <param name="effectTask">An already started task that asynchronously results in the effect to apply in the adjustment layer.</param>
 /// <returns>The adjustment layer.</returns>
 public AdjustmentLayer(LayerStyle layerStyle, MaybeTask<IImageProvider> effectTask) :
     base(layerStyle, effectTask, Size.Empty)
 {
 }
Ejemplo n.º 27
0
 /// <summary>
 /// Creates an adjustment layer containing the specified effect.
 /// </summary>
 /// <param name="layerStyle">Layer style to use for this layer.</param>
 /// <param name="effectTask">An already started task that asynchronously results in the effect to apply in the adjustment layer.</param>
 /// <returns>The adjustment layer.</returns>
 public AdjustmentLayer(LayerStyle layerStyle, MaybeTask <IImageProvider> effectTask) :
     base(layerStyle, effectTask, Size.Empty)
 {
 }
Ejemplo n.º 28
0
 internal Invariants(Layer backgroundLayer, MaybeTask <IImageProvider> backgroundImage, Size renderSizeHint)
 {
     BackgroundLayer  = backgroundLayer;
     BackgroundImage  = backgroundImage;
     HintedRenderSize = renderSizeHint;
 }
Ejemplo n.º 29
0
 /// <summary>
 /// Creates a layer with image content.
 /// </summary>
 /// <param name="layerStyle">Description of how to blend this layer onto the preceding one.</param>
 /// <param name="imageProvider">A value that represents either the <see cref="IImageProvider" /> that is the image content or a task that asynchronously results in it.</param>
 /// <param name="imageSize">Optional, the size of the image content of the layer.</param>
 public Layer(LayerStyle layerStyle, MaybeTask<IImageProvider> imageProvider, Size imageSize = default(Size))
 {
     Style = layerStyle;
     GetImageProvider = context => imageProvider;
     ImageSize = imageSize;
 }
Ejemplo n.º 30
0
 internal Invariants(Layer backgroundLayer, MaybeTask<IImageProvider> backgroundImage, Size renderSizeHint)
 {
     BackgroundLayer = backgroundLayer;
     BackgroundImage = backgroundImage;
     HintedRenderSize = renderSizeHint;
 }
Ejemplo n.º 31
0
        internal static MaybeTask<IImageProvider> Apply(LayerContext context, MaybeTask<IImageProvider> image)
        {
            var layer = context.CurrentLayer;

            var mask = new MaybeTask<IImageProvider>();

            if (layer.Style.MaskResolver != null)
            {
                mask = layer.Style.MaskResolver(context);                
            }

            const double opacityEpsilon = 0.01;
            bool isOpaque = context.CurrentLayerIndex == 0 ||
                ((layer is AdjustmentLayer) &&
                layer.Style.BlendFunction == BlendFunction.Normal &&
                Math.Abs(layer.Style.Opacity - 1.0) <= opacityEpsilon);

            if (isOpaque)
            {
                return new MaybeTask<IImageProvider>();
            }

            // This whole unfolded mess may look silly, but allows us to do the bare minimum. 
            // It defers resolving task-ness until later, so there are less objects allocated on average.
            // Using async/await causes quite a few extra objects on the heap.
            // We also try to avoid Task.FromResult which is at least one extra Task on the heap.
            // Task.WhenAll is not efficient in .NET 4.0, and it's unknown how that translates to Silverlight for WP 8.0.

            var blendParams = new BlendParams
            {
                PreviousImage = context.PreviousImage,
                Image = image,
                Mask = mask,
                Style = layer.Style
            };

            if (blendParams.PreviousImage.IsSynchronous)
            {
                if (blendParams.Image.IsSynchronous)
                {
                    if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty)
                    {
                        return new MaybeTask<IImageProvider>(CreateBlendEffect(blendParams));
                    }
                    else
                    {
                        return new MaybeTask<IImageProvider>(
                            mask.Task.ContinueWith((maskTask, state) =>
                            {
                                var bp = (BlendParams)state;
                                bp.Mask = new MaybeTask<IImageProvider>(maskTask.Result);

                                return CreateBlendEffect(bp);

                            }, blendParams, ContinuationOptions));
                    }
                }
                else // image.IsAsynchronous
                {
                    if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty)
                    {
                        return new MaybeTask<IImageProvider>(
                            image.Task.ContinueWith((imageTask, state) =>
                            {
                                var bp = (BlendParams)state;
                                bp.Image = new MaybeTask<IImageProvider>(imageTask.Result);

                                return CreateBlendEffect(bp);

                            }, blendParams, ContinuationOptions));
                    }
                    else // mask.IsAsynchronous
                    {
                        return new MaybeTask<IImageProvider>(
                            image.Task.ContinueWith((imageTask, state) =>
                            {
                                var bp = (BlendParams)state;
                                bp.Image = new MaybeTask<IImageProvider>(imageTask.Result);

                                return bp.Mask.Task.ContinueWith((maskTask, state2) =>
                                {
                                    var bp2 = (BlendParams)state2;
                                    bp2.Mask = new MaybeTask<IImageProvider>(maskTask.Result);

                                    return CreateBlendEffect(bp2);

                                }, bp, ContinuationOptions);

                            }, blendParams, ContinuationOptions).Unwrap());
                    }
                }
            }
            else // previousImage.IsAsynchronous
            {
                if (blendParams.Image.IsSynchronous)
                {
                    if (blendParams.Mask.IsSynchronous || blendParams.Mask.IsEmpty)
                    {
                        return new MaybeTask<IImageProvider>(
                            blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) =>
                            {
                                var bp = (BlendParams)state;
                                bp.PreviousImage = new MaybeTask<IImageProvider>(previousImageTask.Result);

                                return CreateBlendEffect(bp);

                            }, blendParams, ContinuationOptions));
                    }
                    else // mask.IsAsynchronous
                    {
                        return new MaybeTask<IImageProvider>(
                            blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state2) =>
                            {
                                var blendParams2 = (BlendParams)state2;
                                blendParams2.PreviousImage = new MaybeTask<IImageProvider>(previousImageTask.Result);

                                return blendParams2.Mask.Task.ContinueWith((maskTask, state3) =>
                                {
                                    var blendParams3 = (BlendParams)state3;
                                    blendParams3.Mask = new MaybeTask<IImageProvider>(maskTask.Result);

                                    return CreateBlendEffect(blendParams3);

                                }, blendParams2, ContinuationOptions);

                            }, blendParams, ContinuationOptions).Unwrap());
                    }
                }
                else // image.IsAsynchronous
                {
                    if (mask.IsSynchronous || mask.IsEmpty)
                    {
                        return new MaybeTask<IImageProvider>(
                            blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) =>
                            {
                                var bp = (BlendParams)state;
                                bp.PreviousImage = new MaybeTask<IImageProvider>(previousImageTask.Result);

                                return bp.Image.Task.ContinueWith((imageTask, state2) =>
                                {
                                    var bp2 = (BlendParams)state2;
                                    bp2.Image = new MaybeTask<IImageProvider>(imageTask.Result);

                                    return CreateBlendEffect(bp2);

                                }, bp, ContinuationOptions);

                            }, blendParams, ContinuationOptions).Unwrap());
                    }
                    else // mask.IsAsynchronous
                    {
                        return new MaybeTask<IImageProvider>(
                            blendParams.PreviousImage.Task.ContinueWith((previousImageTask, state) =>
                            {
                                var bp = (BlendParams)state;
                                bp.PreviousImage = new MaybeTask<IImageProvider>(previousImageTask.Result);

                                return bp.Image.Task.ContinueWith((imageTask, state2) =>
                                {
                                    var bp2 = (BlendParams)state2;
                                    bp2.Image = new MaybeTask<IImageProvider>(imageTask.Result);

                                    return bp2.Mask.Task.ContinueWith((maskTask, state3) =>
                                    {
                                        var bp3 = (BlendParams)state3;
                                        bp3.Mask = new MaybeTask<IImageProvider>(maskTask.Result);

                                        return CreateBlendEffect(bp3);

                                    }, bp2, ContinuationOptions);

                                }, bp, ContinuationOptions);

                            }, blendParams, ContinuationOptions).Unwrap().Unwrap());
                    }
                }
            }

            throw new NotImplementedException();
        }