CPF/CPF/TextureFill.cs

327 lines
11 KiB
C#
Raw Normal View History

2023-11-21 23:05:03 +08:00
using System;
using System.Collections.Generic;
using System.Text;
using CPF.Drawing;
using CPF.Controls;
namespace CPF
{
/// <summary>
/// 纹理图片填充
/// </summary>
public class TextureFill : ViewFill, Design.ISerializerCode
{
public virtual Image Image
{
get { return GetValue<Image>(); }
set { SetValue(value); }
}
/// <summary>
/// 纹理图片填充
/// </summary>
/// <param name="image"></param>
public TextureFill(Image image)
{
this.Image = image;
}
public TextureFill()
{
}
string path;
/// <summary>
/// 纹理图片路径可以是URL或者文件路径或者res://内嵌资源路径 格式url(img.gif) [no-repeat/repeat(clamp/tile)] [none/fill/uniform/UniformToFill] [x,y,w,h] 需要按顺序
/// </summary>
/// <param name="path"></param>
public TextureFill(string path)
{
try
{
if (path.StartsWith("url("))
{
var index = path.LastIndexOf(')');
Styling.ResourceManager.GetImage(path.Substring(4, index - 4), a =>
{
Threading.Dispatcher.MainThread.Invoke(() =>
{
if (a == null)
{
Image = Styling.ResourceManager.ErrorImage;
}
else
{
Image = a;
}
});
});
if (path.Length > index + 2)
{
var temp = path.Substring(index + 2).Split(' ');
if (temp.Length > 0 && !string.IsNullOrWhiteSpace(temp[0]))
{
var t = temp[0].ToLower().Trim();
if (t == "no-repeat" || t == "clamp")
{
WrapMode = WrapMode.Clamp;
}
else
{
WrapMode = WrapMode.Tile;
}
}
if (temp.Length > 1 && !string.IsNullOrWhiteSpace(temp[1]))
{
Stretch = (Stretch)Enum.Parse(typeof(Stretch), temp[1], true);
}
if (temp.Length > 2 && !string.IsNullOrWhiteSpace(temp[2]))
{
ImageClip = temp[2];
}
}
}
else
{
Styling.ResourceManager.GetImage(path, a =>
{
Threading.Dispatcher.MainThread.Invoke(() =>
{
if (a == null)
{
Image = Styling.ResourceManager.ErrorImage;
}
else
{
Image = a;
}
});
});
}
}
catch (Exception e)
{
throw new Exception("图片路径格式不对:" + path + e.Message);
}
this.path = path;
}
/// <summary>
/// 图片的裁剪区域
/// </summary>
public Rect ImageClip
{
get { return GetValue<Rect>(); }
set { SetValue(value); }
}
/// <summary>
/// 图片填充模式
/// </summary>
[PropertyMetadata(Stretch.None)]
public Stretch Stretch
{
get { return GetValue<Stretch>(); }
set { SetValue(value); }
}
/// <summary>
/// 平铺模式
/// </summary>
public WrapMode WrapMode
{
get { return GetValue<WrapMode>(); }
set { SetValue(value); }
}
Bitmap cacheImage;
[PropertyChanged(nameof(ImageClip))]
void RegisterImageClip(object newValue, object oldValue, PropertyMetadataAttribute attribute)
{
var rect = (Rect)newValue;
if (rect.X < 0 || rect.Y < 0)
{
throw new Exception("x,y不能小于0");
}
var img = Image;
if (cacheImage != null)
{
cacheImage.Dispose();
cacheImage = null;
}
if (img != null && rect.Width > 0 && rect.Height > 0)
{
cacheImage = new Bitmap((int)rect.Width, (int)rect.Height);
using (DrawingContext dc = DrawingContext.FromBitmap(cacheImage))
{
dc.Clear(Color.Transparent);
dc.DrawImage(img, new Rect(0, 0, rect.Width, rect.Height), rect);
}
}
}
[PropertyChanged(nameof(Image))]
void RegisterImage(object newValue, object oldValue, PropertyMetadataAttribute attribute)
{
if (cacheImage != null)
{
cacheImage.Dispose();
cacheImage = null;
}
Rect rect = ImageClip;
var img = newValue as Image;
if (img != null && rect.Width > 0 && rect.Height > 0)
{
cacheImage = new Bitmap((int)rect.Width, (int)rect.Height);
using (DrawingContext dc = DrawingContext.FromBitmap(cacheImage))
{
dc.Clear(Color.Transparent);
dc.DrawImage(img, new Rect(0, 0, rect.Width, rect.Height), rect);
}
}
}
//protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue, PropertyMetadataAttribute propertyMetadata)
//{
// base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata);
// if (propertyName == nameof(ImageClip))
// {
// var rect = (Rect)newValue;
// if (rect.X < 0 || rect.Y < 0)
// {
// throw new Exception("x,y不能小于0");
// }
// var img = Image;
// if (cacheImage != null)
// {
// cacheImage.Dispose();
// cacheImage = null;
// }
// if (img != null && rect.Width > 0 && rect.Height > 0)
// {
// cacheImage = new Bitmap((int)rect.Width, (int)rect.Height);
// using (DrawingContext dc = DrawingContext.FromBitmap(cacheImage))
// {
// dc.Clear(Color.Transparent);
// dc.DrawImage(img, new Rect(0, 0, rect.Width, rect.Height), rect);
// }
// }
// }
// else if (propertyName == nameof(Image))
// {
// if (newValue == null)
// {
// throw new Exception("Image不能为null");
// }
// else
// {
// if (cacheImage != null)
// {
// cacheImage.Dispose();
// cacheImage = null;
// }
// Rect rect = ImageClip;
// var img = newValue as Image;
// if (img != null && rect.Width > 0 && rect.Height > 0)
// {
// cacheImage = new Bitmap((int)rect.Width, (int)rect.Height);
// using (DrawingContext dc = DrawingContext.FromBitmap(cacheImage))
// {
// dc.Clear(Color.Transparent);
// dc.DrawImage(img, new Rect(0, 0, rect.Width, rect.Height), rect);
// }
// }
// }
// }
//}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (cacheImage != null)
{
cacheImage.Dispose();
cacheImage = null;
}
}
public override Brush CreateBrush(in Rect rect, in float renderScaling)
{
var image = Image;
if (image == null)
{
return new SolidColorBrush(Color.Transparent);
}
Image img = cacheImage == null ? image : cacheImage;
var m = Matrix.Identity;
var w = img.Width;
var h = img.Height;
var ww = rect.Width;
var hh = rect.Height;
OverrideMatrix(ref m, renderScaling);
switch (Stretch)
{
case Stretch.None:
break;
case Stretch.Fill:
m.Scale(rect.Width / img.Width, rect.Height / img.Height);
break;
case Stretch.Uniform:
if (w / rect.Width > h / rect.Height)
{
hh = rect.Width * h / w;
}
else
{
ww = rect.Height * w / h;
}
m.Scale(ww / img.Width, hh / img.Height);
m.Translate((rect.Width - ww) / 2, (rect.Height - hh) / 2);
break;
case Stretch.UniformToFill:
if (w / rect.Width < h / rect.Height)
{
hh = rect.Width * h / w;
}
else
{
ww = rect.Height * w / h;
}
m.Scale(ww / img.Width, hh / img.Height);
m.Translate((rect.Width - ww) / 2, (rect.Height - hh) / 2);
break;
}
m.Translate(rect.X, rect.Y);
return new TextureBrush(img, WrapMode, m);
}
protected virtual void OverrideMatrix(ref Matrix matrix, in float renderScaling)
{
}
public override string GetCreationCode()
{
if (!string.IsNullOrEmpty(path))
{
return "\"" + path + "\"";
}
else
{
return base.GetCreationCode();
}
}
public override string ToString()
{
if (!string.IsNullOrEmpty(path))
{
return path;
}
return base.ToString();
}
}
}