327 lines
11 KiB
C#
327 lines
11 KiB
C#
![]() |
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();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|