解决SVG透明度和渐变显示问题

This commit is contained in:
小红帽 2024-01-18 22:09:17 +08:00
parent e35f7f1e41
commit 7f9eb19a7d
8 changed files with 318 additions and 268 deletions

View File

@ -217,6 +217,10 @@ namespace CPF.Controls
{ {
Invoke(() => Invoke(() =>
{ {
if (!s.Equals(Source))
{
return;
}
SetImage(a); SetImage(a);
needDisposeImg = false; needDisposeImg = false;
if (a == null) if (a == null)

View File

@ -2512,6 +2512,11 @@ namespace CPF.Controls
{ {
views.TryRemove(this, out _); views.TryRemove(this, out _);
base.Dispose(disposing); base.Dispose(disposing);
if (viewImpl != null)
{
viewImpl.Dispose();
//viewImpl = null;
}
} }
} }
/// <summary> /// <summary>

View File

@ -529,11 +529,11 @@ namespace CPF.Controls
RaiseEvent(e, nameof(Closed)); RaiseEvent(e, nameof(Closed));
} }
protected override void Dispose(bool disposing) //protected override void Dispose(bool disposing)
{ //{
windowImpl.Dispose(); // windowImpl.Dispose();
base.Dispose(disposing); // base.Dispose(disposing);
} //}
} }
public class ClosingEventArgs : EventArgs public class ClosingEventArgs : EventArgs

View File

@ -147,8 +147,8 @@ namespace CPF.Svg
public override ViewFill GetBrush(double opacity) public override ViewFill GetBrush(double opacity)
{ {
byte a = (byte)(255 * opacity / 100);
Color c = Color; Color c = Color;
byte a = (byte)(c.A * opacity / 100);
Color newcol = Color.FromArgb(a, c.R, c.G, c.B); Color newcol = Color.FromArgb(a, c.R, c.G, c.B);
if (sb == null || sb.IsDisposed) if (sb == null || sb.IsDisposed)
{ {
@ -158,7 +158,7 @@ namespace CPF.Svg
return sb; return sb;
} }
} }
abstract class GradientColor : PaintServer internal abstract class GradientColor : PaintServer
{ {
// http://www.w3.org/TR/SVG11/pservers.html#LinearGradients // http://www.w3.org/TR/SVG11/pservers.html#LinearGradients
List<GradientStop> m_stops = new List<GradientStop>(); List<GradientStop> m_stops = new List<GradientStop>();
@ -244,7 +244,11 @@ namespace CPF.Svg
{ {
LinearGradientFill b = new LinearGradientFill(); LinearGradientFill b = new LinearGradientFill();
foreach (GradientStop stop in Stops) foreach (GradientStop stop in Stops)
b.GradientStops.Add(stop); {
var c = stop.Color;
byte a = (byte)(c.A * opacity / 100);
b.GradientStops.Add(new GradientStop(Color.FromArgb(a, c.R, c.G, c.B), stop.Position));
}
//b.MappingMode = BrushMappingMode.RelativeToBoundingBox; //b.MappingMode = BrushMappingMode.RelativeToBoundingBox;
b.StartPoint = "0, 0"; b.StartPoint = "0, 0";
@ -336,7 +340,11 @@ namespace CPF.Svg
{ {
RadialGradientFill b = new RadialGradientFill(); RadialGradientFill b = new RadialGradientFill();
foreach (GradientStop stop in Stops) foreach (GradientStop stop in Stops)
b.GradientStops.Add(stop); {
var c = stop.Color;
byte a = (byte)(c.A * opacity / 100);
b.GradientStops.Add(new GradientStop(Color.FromArgb(a, c.R, c.G, c.B), stop.Position));
}
//b.GradientOrigin = new System.Windows.Point(0.5, 0.5); //b.GradientOrigin = new System.Windows.Point(0.5, 0.5);
b.Center = "50%,50%"; b.Center = "50%,50%";

View File

@ -168,7 +168,7 @@ namespace CPF.Svg
//public bool ClosePath { get; private set;} //public bool ClosePath { get; private set;}
// http://apike.ca/prog_svg_paths.html // http://apike.ca/prog_svg_paths.html
public PathShape(XmlNode node) : base(node) public PathShape(XmlNode node, SvgShape parent) : base(node, parent)
{ {
//ClosePath = false; //ClosePath = false;
string path = XmlUtil.AttrValue(node, "d", string.Empty); string path = XmlUtil.AttrValue(node, "d", string.Empty);

View File

@ -205,10 +205,13 @@ namespace CPF.Svg
var fill = Fill; var fill = Fill;
foreach (var item in m_elements) foreach (var item in m_elements)
{
if (item.GetFill().Color == null)
{ {
item.GetFill().FillBrush = fill; item.GetFill().FillBrush = fill;
} }
} }
}
/// <summary> /// <summary>
/// 图片缩放模式 /// 图片缩放模式
@ -244,10 +247,13 @@ namespace CPF.Svg
{ {
var fill = newValue as ViewFill; var fill = newValue as ViewFill;
foreach (var item in m_elements) foreach (var item in m_elements)
{
if (item.GetFill().Color == null)
{ {
item.GetFill().FillBrush = fill; item.GetFill().FillBrush = fill;
} }
} }
}
Size naturalSize; Size naturalSize;
protected override Size MeasureOverride(in Size availableSize) protected override Size MeasureOverride(in Size availableSize)
@ -504,6 +510,17 @@ namespace CPF.Svg
} }
} }
if (item.Fill != null && item.Fill.FillBrush != null) if (item.Fill != null && item.Fill.FillBrush != null)
{
if (item.Fill.Color is GradientColor svgFill)
{
using (var brush = item.Fill.FillBrush.CreateBrush(svgFill.GradientUnits == SVGTags.sGradientUserSpace ? new Rect(0, 0, naturalSize.Width, naturalSize.Height) : item.Geometry.GetBounds(), Root.RenderScaling))
{
dc.FillPath(brush, item.Geometry);
}
}
else
{
if (item.Fill.Color != null)
{ {
using (var brush = item.Fill.FillBrush.CreateBrush(item.Geometry.GetBounds(), Root.RenderScaling)) using (var brush = item.Fill.FillBrush.CreateBrush(item.Geometry.GetBounds(), Root.RenderScaling))
{ {
@ -511,6 +528,8 @@ namespace CPF.Svg
} }
} }
} }
}
}
if (item.Transform != null) if (item.Transform != null)
{ {
dc.Transform = old; dc.Transform = old;

View File

@ -63,8 +63,8 @@ namespace CPF.Svg
public float Opacity { get; set; } = 1; public float Opacity { get; set; } = 1;
public virtual Transform Transform { get; private set; } public virtual Transform Transform { get; private set; }
public SvgShape Parent { get; set; } public SvgShape Parent { get; private set; }
public SvgShape(XmlNode node) : this(node, null) { } //public SvgShape(XmlNode node) : this(node, null) { }
public SvgShape(XmlNode node, SvgShape parent) : base(node) public SvgShape(XmlNode node, SvgShape parent) : base(node)
{ {
Parent = parent; Parent = parent;
@ -83,6 +83,18 @@ namespace CPF.Svg
m_stroke.Opacity *= Opacity; m_stroke.Opacity *= Opacity;
} }
} }
if (parent != null && parent.Opacity != 1)
{
if (m_fill != null)
{
m_fill.Opacity *= parent.Opacity;
m_fill.FillBrush = null;
}
if (m_stroke != null)
{
m_stroke.Opacity *= parent.Opacity;
}
}
} }
} }
public SvgShape(List<ShapeUtil.Attribute> attrs, SvgShape parent) : base(null) public SvgShape(List<ShapeUtil.Attribute> attrs, SvgShape parent) : base(null)
@ -308,7 +320,7 @@ namespace CPF.Svg
public float Height { get; set; } public float Height { get; set; }
public float RX { get; set; } public float RX { get; set; }
public float RY { get; set; } public float RY { get; set; }
public RectangleShape(XmlNode node) : base(node) public RectangleShape(XmlNode node, SvgShape parent) : base(node, parent)
{ {
X = (float)XmlUtil.AttrValue(node, "x", 0); X = (float)XmlUtil.AttrValue(node, "x", 0);
Y = (float)XmlUtil.AttrValue(node, "y", 0); Y = (float)XmlUtil.AttrValue(node, "y", 0);
@ -399,7 +411,7 @@ namespace CPF.Svg
public float CX { get; set; } public float CX { get; set; }
public float CY { get; set; } public float CY { get; set; }
public float R { get; set; } public float R { get; set; }
public CircleShape(XmlNode node) : base(node) public CircleShape(XmlNode node, SvgShape parent) : base(node, parent)
{ {
CX = (float)XmlUtil.AttrValue(node, "cx", 0); CX = (float)XmlUtil.AttrValue(node, "cx", 0);
CY = (float)XmlUtil.AttrValue(node, "cy", 0); CY = (float)XmlUtil.AttrValue(node, "cy", 0);
@ -456,7 +468,7 @@ namespace CPF.Svg
public float CY { get; set; } public float CY { get; set; }
public float RX { get; set; } public float RX { get; set; }
public float RY { get; set; } public float RY { get; set; }
public EllipseShape(XmlNode node) : base(node) public EllipseShape(XmlNode node, SvgShape parent) : base(node, parent)
{ {
CX = (float)XmlUtil.AttrValue(node, "cx", 0); CX = (float)XmlUtil.AttrValue(node, "cx", 0);
CY = (float)XmlUtil.AttrValue(node, "cy", 0); CY = (float)XmlUtil.AttrValue(node, "cy", 0);
@ -510,7 +522,7 @@ namespace CPF.Svg
{ {
public Point P1 { get; private set; } public Point P1 { get; private set; }
public Point P2 { get; private set; } public Point P2 { get; private set; }
public LineShape(XmlNode node) : base(node) public LineShape(XmlNode node, SvgShape parent) : base(node, parent)
{ {
double x1 = XmlUtil.AttrValue(node, "x1", 0); double x1 = XmlUtil.AttrValue(node, "x1", 0);
double y1 = XmlUtil.AttrValue(node, "y1", 0); double y1 = XmlUtil.AttrValue(node, "y1", 0);
@ -532,7 +544,7 @@ namespace CPF.Svg
class PolylineShape : SvgShape class PolylineShape : SvgShape
{ {
public Point[] Points { get; private set; } public Point[] Points { get; private set; }
public PolylineShape(XmlNode node) : base(node) public PolylineShape(XmlNode node, SvgShape parent) : base(node, parent)
{ {
string points = XmlUtil.AttrValue(node, SVGTags.sPoints, string.Empty); string points = XmlUtil.AttrValue(node, SVGTags.sPoints, string.Empty);
ShapeUtil.StringSplitter split = new ShapeUtil.StringSplitter(points); ShapeUtil.StringSplitter split = new ShapeUtil.StringSplitter(points);
@ -562,7 +574,7 @@ namespace CPF.Svg
class PolygonShape : SvgShape class PolygonShape : SvgShape
{ {
public Point[] Points { get; private set; } public Point[] Points { get; private set; }
public PolygonShape(XmlNode node) : base(node) public PolygonShape(XmlNode node, SvgShape parent) : base(node, parent)
{ {
string points = XmlUtil.AttrValue(node, SVGTags.sPoints, string.Empty); string points = XmlUtil.AttrValue(node, SVGTags.sPoints, string.Empty);
ShapeUtil.StringSplitter split = new ShapeUtil.StringSplitter(points); ShapeUtil.StringSplitter split = new ShapeUtil.StringSplitter(points);
@ -595,7 +607,7 @@ namespace CPF.Svg
public double X { get; set; } public double X { get; set; }
public double Y { get; set; } public double Y { get; set; }
public string hRef { get; set; } public string hRef { get; set; }
public UseShape(XmlNode node) : base(node) public UseShape(XmlNode node, SvgShape parent) : base(node, parent)
{ {
X = XmlUtil.AttrValue(node, "x", 0); X = XmlUtil.AttrValue(node, "x", 0);
Y = XmlUtil.AttrValue(node, "y", 0); Y = XmlUtil.AttrValue(node, "y", 0);
@ -646,21 +658,21 @@ namespace CPF.Svg
get { return m_elements; } get { return m_elements; }
} }
SvgShape AddChild(SvgShape shape) //SvgShape AddChild(SvgShape shape)
//{
// m_elements.Add(shape);
// shape.Parent = this;
// return shape;
//}
public Group(XmlNode node, SvgShape parent) : base(node, parent)
{ {
m_elements.Add(shape); //// parent on group must be set before children are added
shape.Parent = this; //this.Parent = parent;
return shape;
}
public Group(XmlNode node, SvgShape parent) : base(node)
{
// parent on group must be set before children are added
this.Parent = parent;
foreach (XmlNode childnode in node.ChildNodes) foreach (XmlNode childnode in node.ChildNodes)
{ {
SvgShape shape = AddToList(m_elements, childnode, this); SvgShape shape = AddToList(m_elements, childnode, this);
if (shape != null) //if (shape != null)
shape.Parent = this; // shape.Parent = this;
} }
//if (Id.Length > 0) //if (Id.Length > 0)
// svg.AddShape(Id, this); // svg.AddShape(Id, this);
@ -671,37 +683,37 @@ namespace CPF.Svg
return null; return null;
if (childnode.Name == SVGTags.sShapeRect) if (childnode.Name == SVGTags.sShapeRect)
{ {
list.Add(new RectangleShape(childnode)); list.Add(new RectangleShape(childnode, parent));
return list[list.Count - 1]; return list[list.Count - 1];
} }
if (childnode.Name == SVGTags.sShapeCircle) if (childnode.Name == SVGTags.sShapeCircle)
{ {
list.Add(new CircleShape(childnode)); list.Add(new CircleShape(childnode, parent));
return list[list.Count - 1]; return list[list.Count - 1];
} }
if (childnode.Name == SVGTags.sShapeEllipse) if (childnode.Name == SVGTags.sShapeEllipse)
{ {
list.Add(new EllipseShape(childnode)); list.Add(new EllipseShape(childnode, parent));
return list[list.Count - 1]; return list[list.Count - 1];
} }
if (childnode.Name == SVGTags.sShapeLine) if (childnode.Name == SVGTags.sShapeLine)
{ {
list.Add(new LineShape(childnode)); list.Add(new LineShape(childnode, parent));
return list[list.Count - 1]; return list[list.Count - 1];
} }
if (childnode.Name == SVGTags.sShapePolyline) if (childnode.Name == SVGTags.sShapePolyline)
{ {
list.Add(new PolylineShape(childnode)); list.Add(new PolylineShape(childnode, parent));
return list[list.Count - 1]; return list[list.Count - 1];
} }
if (childnode.Name == SVGTags.sShapePolygon) if (childnode.Name == SVGTags.sShapePolygon)
{ {
list.Add(new PolygonShape(childnode)); list.Add(new PolygonShape(childnode, parent));
return list[list.Count - 1]; return list[list.Count - 1];
} }
if (childnode.Name == SVGTags.sShapePath) if (childnode.Name == SVGTags.sShapePath)
{ {
list.Add(new PathShape(childnode)); list.Add(new PathShape(childnode, parent));
return list[list.Count - 1]; return list[list.Count - 1];
} }
if (childnode.Name == SVGTags.sShapeGroup) if (childnode.Name == SVGTags.sShapeGroup)
@ -726,7 +738,7 @@ namespace CPF.Svg
} }
if (childnode.Name == SVGTags.sShapeUse) if (childnode.Name == SVGTags.sShapeUse)
{ {
list.Add(new UseShape(childnode)); list.Add(new UseShape(childnode, parent));
return list[list.Count - 1]; return list[list.Count - 1];
} }
//if (childnode.Name == SVGTags.sShapeImage) //if (childnode.Name == SVGTags.sShapeImage)

View File

@ -25,11 +25,13 @@ namespace CPF.Svg
get get
{ {
if (Color != null)
return Color.GetBrush(Opacity);
if (fillBrush != null) if (fillBrush != null)
return fillBrush; return fillBrush;
return null; if (Color != null)
{
return Color.GetBrush(Opacity);
}
return fillBrush;
} }
set set