123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- using System;
- using System.ComponentModel;
- using System.Windows;
- using System.Windows.Media;
- using System.Windows.Threading;
- namespace HandyControl.Expression.Media;
- [TypeConverter(typeof(GeometryEffectConverter))]
- public abstract class GeometryEffect : Freezable
- {
- // ReSharper disable once InconsistentNaming
- private static GeometryEffect defaultGeometryEffect;
- public static readonly DependencyProperty GeometryEffectProperty =
- DependencyProperty.RegisterAttached("GeometryEffect", typeof(GeometryEffect),
- typeof(GeometryEffect),
- new DrawingPropertyMetadata(DefaultGeometryEffect,
- DrawingPropertyMetadataOptions.AffectsRender, OnGeometryEffectChanged));
- protected Geometry CachedGeometry;
- private bool _effectInvalidated;
- static GeometryEffect()
- {
- DrawingPropertyMetadata.DrawingPropertyChanged +=
- delegate (object sender, DrawingPropertyChangedEventArgs args)
- {
- if (sender is GeometryEffect effect && args.Metadata.AffectsRender)
- effect.InvalidateGeometry(InvalidateGeometryReasons.PropertyChanged);
- };
- }
- public static GeometryEffect DefaultGeometryEffect =>
- defaultGeometryEffect ?? (defaultGeometryEffect = new NoGeometryEffect());
- public Geometry OutputGeometry =>
- CachedGeometry;
- protected internal DependencyObject Parent { get; private set; }
- protected internal virtual void Attach(DependencyObject obj)
- {
- if (Parent != null) Detach();
- _effectInvalidated = true;
- CachedGeometry = null;
- if (InvalidateParent(obj)) Parent = obj;
- }
- public new GeometryEffect CloneCurrentValue()
- {
- return (GeometryEffect) base.CloneCurrentValue();
- }
- protected override Freezable CreateInstanceCore()
- {
- return (Freezable) Activator.CreateInstance(GetType());
- }
- protected abstract GeometryEffect DeepCopy();
- protected internal virtual void Detach()
- {
- _effectInvalidated = true;
- CachedGeometry = null;
- if (Parent != null)
- {
- InvalidateParent(Parent);
- Parent = null;
- }
- }
- public abstract bool Equals(GeometryEffect geometryEffect);
- public static GeometryEffect GetGeometryEffect(DependencyObject obj)
- {
- return (GeometryEffect) obj.GetValue(GeometryEffectProperty);
- }
- public bool InvalidateGeometry(InvalidateGeometryReasons reasons)
- {
- if (_effectInvalidated) return false;
- _effectInvalidated = true;
- if (reasons != InvalidateGeometryReasons.ParentInvalidated) InvalidateParent(Parent);
- return true;
- }
- private static bool InvalidateParent(DependencyObject parent)
- {
- if (parent is IShape shape)
- {
- shape.InvalidateGeometry(InvalidateGeometryReasons.ChildInvalidated);
- return true;
- }
- if (parent is GeometryEffect effect)
- {
- effect.InvalidateGeometry(InvalidateGeometryReasons.ChildInvalidated);
- return true;
- }
- return false;
- }
- private static void OnGeometryEffectChanged(DependencyObject obj,
- DependencyPropertyChangedEventArgs e)
- {
- var oldValue = e.OldValue as GeometryEffect;
- var newValue = e.NewValue as GeometryEffect;
- if (!Equals(oldValue, newValue))
- {
- if (oldValue != null && obj.Equals(oldValue.Parent)) oldValue.Detach();
- if (newValue != null)
- {
- if (newValue.Parent != null)
- {
- obj.Dispatcher.BeginInvoke(new Action(() =>
- {
- var effect = newValue.CloneCurrentValue();
- obj.SetValue(GeometryEffectProperty, effect);
- }), DispatcherPriority.Send, null);
- }
- else
- {
- newValue.Attach(obj);
- }
- }
- }
- }
- public bool ProcessGeometry(Geometry input)
- {
- var flag = false;
- if (_effectInvalidated)
- {
- flag |= UpdateCachedGeometry(input);
- _effectInvalidated = false;
- }
- return flag;
- }
- public static void SetGeometryEffect(DependencyObject obj, GeometryEffect value)
- {
- obj.SetValue(GeometryEffectProperty, value);
- }
- protected abstract bool UpdateCachedGeometry(Geometry input);
- private class NoGeometryEffect : GeometryEffect
- {
- protected override GeometryEffect DeepCopy()
- {
- return new NoGeometryEffect();
- }
- public override bool Equals(GeometryEffect geometryEffect)
- {
- if (geometryEffect != null) return geometryEffect is NoGeometryEffect;
- return true;
- }
- protected override bool UpdateCachedGeometry(Geometry input)
- {
- CachedGeometry = input;
- return false;
- }
- }
- }
|