Example #1
0
        public void HighlightsAndShadowsEffectCustomizations()
        {
            const uint D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_LINEAR = 0;
            const uint D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_SRGB   = 1;

            var effect = new HighlightsAndShadowsEffect();

            // Verify defaults.
            Assert.IsFalse(effect.SourceIsLinearGamma);
            Assert.AreEqual(D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_SRGB, EffectAccessor.GetProperty(effect, 3));

            // Change the property, and verify that the boxed value changes to match.
            effect.SourceIsLinearGamma = true;
            Assert.IsTrue(effect.SourceIsLinearGamma);
            Assert.AreEqual(D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_LINEAR, EffectAccessor.GetProperty(effect, 3));

            effect.SourceIsLinearGamma = false;
            Assert.IsFalse(effect.SourceIsLinearGamma);
            Assert.AreEqual(D2D1_HIGHLIGHTSANDSHADOWS_INPUT_GAMMA_SRGB, EffectAccessor.GetProperty(effect, 3));

            // Validate that IGraphicsEffectD2D1Interop reports the right customizations.
            int index;
            EffectPropertyMapping mapping;

            EffectAccessor.GetNamedPropertyMapping(effect, "SourceIsLinearGamma", out index, out mapping);
            Assert.AreEqual(3, index);
            Assert.AreEqual(EffectPropertyMapping.Unknown, mapping);
        }
Example #2
0
        static void TestEffectInterop(CanvasDevice device, CanvasDevice device2, TypeInfo effectType, IGraphicsEffect realizedEffect)
        {
            // One Win2D effect is backed by a realized ID2D1Effect instance, the other is not.
            // Their property values should be the same either way.
            IGraphicsEffect unrealizedEffect = (IGraphicsEffect)Activator.CreateInstance(effectType.AsType());

            PropertyValuesShouldMatch(effectType, realizedEffect, unrealizedEffect);

            // Create a new ID2D1Effect instance, then wrap a Win2D effect around it.
            // We should get the same default property values either way.
            IGraphicsEffect wrappedEffect = EffectAccessor.CreateThenWrapNewEffectOfSameType(device, realizedEffect);

            // Special case: Win2D intentionally defaults to a different DpiCompensationEffect.BorderMode vs. D2D.
            if (wrappedEffect is DpiCompensationEffect)
            {
                var dpiCompensationEffect = wrappedEffect as DpiCompensationEffect;
                Assert.AreEqual(EffectBorderMode.Soft, dpiCompensationEffect.BorderMode);
                dpiCompensationEffect.BorderMode = EffectBorderMode.Hard;
            }

            PropertyValuesShouldMatch(effectType, unrealizedEffect, wrappedEffect);

            // Re-realize the new effect onto a second device.
            // All property values should be successfully transferred across.
            RealizeEffect(device2, effectType, wrappedEffect);

            PropertyValuesShouldMatch(effectType, unrealizedEffect, wrappedEffect);
        }
Example #3
0
        public void EdgeDetectionEffectCustomizations()
        {
            var effect = new EdgeDetectionEffect();

            // Verify defaults.
            Assert.AreEqual(CanvasAlphaMode.Premultiplied, effect.AlphaMode);
            Assert.AreEqual(D2D1_ALPHA_MODE_PREMULTIPLIED, EffectAccessor.GetProperty(effect, 4));

            // Change the property, and verify that the boxed value changes to match.
            effect.AlphaMode = CanvasAlphaMode.Straight;
            Assert.AreEqual(D2D1_ALPHA_MODE_STRAIGHT, EffectAccessor.GetProperty(effect, 4));

            effect.AlphaMode = CanvasAlphaMode.Premultiplied;
            Assert.AreEqual(D2D1_ALPHA_MODE_PREMULTIPLIED, EffectAccessor.GetProperty(effect, 4));

            // Verify unsupported value throws.
            Assert.ThrowsException <ArgumentException>(() => { effect.AlphaMode = CanvasAlphaMode.Ignore; });
            Assert.AreEqual(CanvasAlphaMode.Premultiplied, effect.AlphaMode);

            // Validate that IGraphicsEffectD2D1Interop reports the right customizations.
            int index;
            EffectPropertyMapping mapping;

            EffectAccessor.GetNamedPropertyMapping(effect, "AlphaMode", out index, out mapping);
            Assert.AreEqual(4, index);
            Assert.AreEqual(EffectPropertyMapping.ColorMatrixAlphaMode, mapping);
        }
Example #4
0
        public void ArithmeticCompositeEffectCustomizations()
        {
            var effect = new ArithmeticCompositeEffect();

            // Verify defaults.
            Assert.AreEqual(1.0f, effect.MultiplyAmount);
            Assert.AreEqual(0.0f, effect.Source1Amount);
            Assert.AreEqual(0.0f, effect.Source2Amount);
            Assert.AreEqual(0.0f, effect.Offset);

            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 1, 0, 0, 0 }));

            // Change properties one at a time, and verify that the boxed value changes to match.
            effect.MultiplyAmount = 23;
            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 23, 0, 0, 0 }));

            effect.Source1Amount = 42;
            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 23, 42, 0, 0 }));

            effect.Source2Amount = -1;
            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 23, 42, -1, 0 }));

            effect.Offset = 100;
            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 23, 42, -1, 100 }));
        }
Example #5
0
        static void TestEffectProperties(TypeInfo effectType, IGraphicsEffect effect)
        {
            var properties = (from property in effectType.DeclaredProperties
                              where property.Name != "Name"
                              where property.Name != "Sources"
                              where property.PropertyType != typeof(IGraphicsEffectSource)
                              select property).ToList();

            IList <object> effectProperties = new ViewIndexerAsList <object>(() => EffectAccessor.GetPropertyCount(effect),
                                                                             i => EffectAccessor.GetProperty(effect, i));

            FilterOutCustomizedEffectProperties(effectType.AsType(), ref properties, ref effectProperties);

            // Should have the same number of strongly typed properties as elements in the properties collection.
            Assert.AreEqual(properties.Count, effectProperties.Count);

            // Store the initial property values.
            var initialValues = effectProperties.ToList();

            var whichIndexIsProperty = new List <int>();

            // Changing strongly typed properties should change the properties collection.
            for (int i = 0; i < effectProperties.Count; i++)
            {
                object testValue1 = GetArbitraryTestValue(properties[i].PropertyType, true);
                object testValue2 = GetArbitraryTestValue(properties[i].PropertyType, false);

                // Change a property value, and see which collection properties match the result.
                properties[i].SetValue(effect, testValue1);

                var matches1 = (from j in Enumerable.Range(0, effectProperties.Count)
                                where BoxedValuesAreEqual(effectProperties[j], Box(testValue1, properties[i]), properties[i])
                                select j).ToList();

                // Change the same property to a different value, and see which collection properties match now.
                properties[i].SetValue(effect, testValue2);

                var matches2 = (from j in Enumerable.Range(0, effectProperties.Count)
                                where BoxedValuesAreEqual(effectProperties[j], Box(testValue2, properties[i]), properties[i])
                                select j).ToList();

                // There should be one and only one property that matched both times. If not,
                // either we don't have 1 <-> 1 mapping between strongly typed properties and
                // collection indices, or something went wrong during the boxing type conversions.
                var intersection = matches1.Intersect(matches2);
                Assert.AreEqual(1, intersection.Count());
                int whichIndexIsThis = intersection.Single();
                whichIndexIsProperty.Add(whichIndexIsThis);

                // Change the property value back to its initial state.
                properties[i].SetValue(effect, Unbox(initialValues[whichIndexIsThis], properties[i]));
                Assert.IsTrue(BoxedValuesAreEqual(initialValues[whichIndexIsThis], effectProperties[whichIndexIsThis], properties[i]));
            }

            // Should not have any duplicate property mappings.
            Assert.AreEqual(whichIndexIsProperty.Count, whichIndexIsProperty.Distinct().Count());
        }
Example #6
0
        static void TestEffectSources(TypeInfo effectType, IGraphicsEffect effect)
        {
            var sourceProperties = (from property in effectType.DeclaredProperties
                                    where property.PropertyType == typeof(IGraphicsEffectSource)
                                    select property).ToList();

            // Should have the same number of strongly typed properties as the effect has sources.
            Assert.AreEqual(sourceProperties.Count, EffectAccessor.GetSourceCount(effect));

            // Initial source values should all be null.
            for (int i = 0; i < EffectAccessor.GetSourceCount(effect); i++)
            {
                Assert.IsNull(EffectAccessor.GetSource(effect, i));
                Assert.IsNull(sourceProperties[i].GetValue(effect));
            }

            var testValue1 = new GaussianBlurEffect();
            var testValue2 = new ShadowEffect();

            var whichIndexIsProperty = new List <int>();

            // Changing strongly typed properties should change the sources reported by IGraphicsEffectD2D1Interop.
            for (int i = 0; i < EffectAccessor.GetSourceCount(effect); i++)
            {
                // Change a property value, and see which source changes.
                sourceProperties[i].SetValue(effect, testValue1);

                int whichIndexIsThis = 0;

                while (EffectAccessor.GetSource(effect, whichIndexIsThis) != testValue1)
                {
                    whichIndexIsThis++;
                    Assert.IsTrue(whichIndexIsThis < EffectAccessor.GetSourceCount(effect));
                }

                whichIndexIsProperty.Add(whichIndexIsThis);

                // Change the same property value again, and make sure the same source changes.
                sourceProperties[i].SetValue(effect, testValue2);
                Assert.AreSame(testValue2, EffectAccessor.GetSource(effect, whichIndexIsThis));

                // Change the property value to null.
                sourceProperties[i].SetValue(effect, null);
                Assert.IsNull(EffectAccessor.GetSource(effect, whichIndexIsThis));
            }

            // Should not have any duplicate property mappings.
            Assert.AreEqual(whichIndexIsProperty.Count, whichIndexIsProperty.Distinct().Count());
        }
Example #7
0
        public void ArithmeticCompositeEffectCustomizations()
        {
            var effect = new ArithmeticCompositeEffect();

            // Verify defaults.
            Assert.AreEqual(1.0f, effect.MultiplyAmount);
            Assert.AreEqual(0.0f, effect.Source1Amount);
            Assert.AreEqual(0.0f, effect.Source2Amount);
            Assert.AreEqual(0.0f, effect.Offset);

            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 1, 0, 0, 0 }));

            // Change properties one at a time, and verify that the boxed value changes to match.
            effect.MultiplyAmount = 23;
            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 23, 0, 0, 0 }));

            effect.Source1Amount = 42;
            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 23, 42, 0, 0 }));

            effect.Source2Amount = -1;
            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 23, 42, -1, 0 }));

            effect.Offset = 100;
            Assert.IsTrue(((float[])EffectAccessor.GetProperty(effect, 0)).SequenceEqual(new float[] { 23, 42, -1, 100 }));

            // Validate that IGraphicsEffectD2D1Interop reports the right customizations.
            int index;
            EffectPropertyMapping mapping;

            EffectAccessor.GetNamedPropertyMapping(effect, "MultiplyAmount", out index, out mapping);
            Assert.AreEqual(0, index);
            Assert.AreEqual(EffectPropertyMapping.VectorX, mapping);

            EffectAccessor.GetNamedPropertyMapping(effect, "Source1Amount", out index, out mapping);
            Assert.AreEqual(0, index);
            Assert.AreEqual(EffectPropertyMapping.VectorY, mapping);

            EffectAccessor.GetNamedPropertyMapping(effect, "Source2Amount", out index, out mapping);
            Assert.AreEqual(0, index);
            Assert.AreEqual(EffectPropertyMapping.VectorZ, mapping);

            EffectAccessor.GetNamedPropertyMapping(effect, "Offset", out index, out mapping);
            Assert.AreEqual(0, index);
            Assert.AreEqual(EffectPropertyMapping.VectorW, mapping);
        }
Example #8
0
        public void ColorMatrixEffectCustomizations()
        {
            const uint D2D1_COLORMATRIX_ALPHA_MODE_PREMULTIPLIED = 1;
            const uint D2D1_COLORMATRIX_ALPHA_MODE_STRAIGHT      = 2;

            var effect = new ColorMatrixEffect();

            // Verify defaults.
            Assert.AreEqual(CanvasAlphaMode.Premultiplied, effect.AlphaMode);
            Assert.AreEqual(D2D1_COLORMATRIX_ALPHA_MODE_PREMULTIPLIED, EffectAccessor.GetProperty(effect, 1));

            // Change the property, and verify that the boxed value changes to match.
            effect.AlphaMode = CanvasAlphaMode.Straight;
            Assert.AreEqual(D2D1_COLORMATRIX_ALPHA_MODE_STRAIGHT, EffectAccessor.GetProperty(effect, 1));

            effect.AlphaMode = CanvasAlphaMode.Premultiplied;
            Assert.AreEqual(D2D1_COLORMATRIX_ALPHA_MODE_PREMULTIPLIED, EffectAccessor.GetProperty(effect, 1));

            // Verify unsupported value throws.
            Assert.ThrowsException <ArgumentException>(() => { effect.AlphaMode = CanvasAlphaMode.Ignore; });
            Assert.AreEqual(CanvasAlphaMode.Premultiplied, effect.AlphaMode);
        }
Example #9
0
        static ICanvasImage RealizeEffect(CanvasDevice device, TypeInfo effectType, IGraphicsEffect effect)
        {
            var dummySourceImage = new CanvasCommandList(device);

            // We can't realize an effect with invalid inputs, so must first set them all to something reasonable.
            foreach (var sourceProperty in effectType.DeclaredProperties.Where(p => p.PropertyType == typeof(IGraphicsEffectSource)))
            {
                sourceProperty.SetValue(effect, dummySourceImage);
            }

            // Add one image to any variable size Sources collection properties.
            foreach (var sourcesProperty in effectType.DeclaredProperties.Where(p => p.Name == "Sources"))
            {
                var sources = sourcesProperty.GetValue(effect) as IList <IGraphicsEffectSource>;

                sources.Clear();
                sources.Add(dummySourceImage);
            }

            EffectAccessor.RealizeEffect(device, effect);

            return(dummySourceImage);
        }
Example #10
0
        static void TestEffectProperties(TypeInfo effectType, IGraphicsEffect effect)
        {
            var properties = GetEffectProperties(effectType).ToList();

            IList <object> effectProperties = new ViewIndexerAsList <object>(() => EffectAccessor.GetPropertyCount(effect),
                                                                             i => EffectAccessor.GetProperty(effect, i));

            FilterOutCustomizedEffectProperties(effectType.AsType(), ref properties, ref effectProperties);

            // Should have the same number of strongly typed properties as elements in the properties collection.
            Assert.AreEqual(properties.Count, effectProperties.Count);

            // Store the initial property values.
            var initialValues = effectProperties.ToList();

            var whichIndexIsProperty = new List <int>();

            // Changing strongly typed properties should change the properties collection.
            for (int i = 0; i < effectProperties.Count; i++)
            {
                object testValue1 = GetArbitraryTestValue(properties[i].PropertyType, true);
                object testValue2 = GetArbitraryTestValue(properties[i].PropertyType, false);

                // Change a property value, and see which collection properties match the result.
                properties[i].SetValue(effect, testValue1);
                AssertPropertyValuesAreEqual(testValue1, properties[i].GetValue(effect));

                var matches1 = (from j in Enumerable.Range(0, effectProperties.Count)
                                where BoxedValuesAreEqual(effectProperties[j], Box(testValue1, properties[i]), properties[i])
                                select j).ToList();

                // Change the same property to a different value, and see which collection properties match now.
                properties[i].SetValue(effect, testValue2);
                AssertPropertyValuesAreEqual(testValue2, properties[i].GetValue(effect));

                var matches2 = (from j in Enumerable.Range(0, effectProperties.Count)
                                where BoxedValuesAreEqual(effectProperties[j], Box(testValue2, properties[i]), properties[i])
                                select j).ToList();

                // There should be one and only one property that matched both times. If not,
                // either we don't have 1 <-> 1 mapping between strongly typed properties and
                // collection indices, or something went wrong during the boxing type conversions.
                var intersection = matches1.Intersect(matches2);
                Assert.AreEqual(1, intersection.Count());
                int whichIndexIsThis = intersection.Single();
                whichIndexIsProperty.Add(whichIndexIsThis);

                // Change the property value back to its initial state.
                var unboxedValue = Unbox(initialValues[whichIndexIsThis], properties[i]);
                properties[i].SetValue(effect, unboxedValue);
                AssertPropertyValuesAreEqual(unboxedValue, properties[i].GetValue(effect));
                Assert.IsTrue(BoxedValuesAreEqual(initialValues[whichIndexIsThis], effectProperties[whichIndexIsThis], properties[i]));

                // Validate that IGraphicsEffectD2D1Interop agrees with what we think the type and index of this property is.
                int mappingIndex;
                EffectPropertyMapping mapping;

                EffectAccessor.GetNamedPropertyMapping(effect, properties[i].Name, out mappingIndex, out mapping);

                int expectedMappingIndex = whichIndexIsThis;

                if (effectProperties is FilteredViewOfList <object> )
                {
                    expectedMappingIndex = ((FilteredViewOfList <object>)effectProperties).GetOriginalIndex(expectedMappingIndex);
                }

                Assert.AreEqual(expectedMappingIndex, mappingIndex);

                var expectedMapping = GetExpectedPropertyMapping(properties[i], effectProperties[whichIndexIsThis]);
                Assert.AreEqual(expectedMapping, mapping);
            }

            // Should not have any duplicate property mappings.
            Assert.AreEqual(whichIndexIsProperty.Count, whichIndexIsProperty.Distinct().Count());
        }