1- using System ;
1+ // Copyright (c) AhDung. All Rights Reserved.
2+
3+ using System ;
24using System . Drawing ;
35using System . Drawing . Drawing2D ;
46
5- namespace AhDung . Drawing
7+ namespace AhDung . Drawing ;
8+
9+ /// <summary>
10+ /// 描边位置
11+ /// </summary>
12+ public enum Direction
613{
714 /// <summary>
8- /// 描边位置
15+ /// 居中
916 /// </summary>
10- public enum Direction
11- {
12- /// <summary>
13- /// 居中
14- /// </summary>
15- Middle ,
16- /// <summary>
17- /// 内部
18- /// </summary>
19- Inner ,
20- /// <summary>
21- /// 外部
22- /// </summary>
23- Outer
24- }
17+ Middle ,
18+
19+ /// <summary>
20+ /// 内部
21+ /// </summary>
22+ Inner ,
23+
24+ /// <summary>
25+ /// 外部
26+ /// </summary>
27+ Outer
28+ }
29+
30+ /// <summary>
31+ /// 存储一系列边框要素并产生合适的画笔
32+ /// <para>- 边框居中+奇数粗度时是介于两像素之间画,所以粗细在视觉上不精确,建议错开任一条件</para>
33+ /// </summary>
34+ public class Border : IDisposable
35+ {
36+ //编写本类除了整合边框信息外,更重要的原因是如果不对画笔做额外处理,
37+ //Draw出来的边框是不理想的。本类的原理是:
38+ // - 偶数边框(这是得到理想效果的前提)
39+ // - 再利用画笔的CompoundArray属性将边框裁切掉一半,
40+ // 同时根据不同参数偏移描边位置,达到可内可外可居中的效果
41+
42+ float [ ] _compoundArray ;
2543
2644 /// <summary>
27- /// 存储一系列边框要素并产生合适的画笔
28- /// <para>- 边框居中+奇数粗度时是介于两像素之间画,所以粗细在视觉上不精确,建议错开任一条件</para>
45+ /// 根据_direction处理线段
2946 /// </summary>
30- public class Border : IDisposable
47+ float [ ] CompoundArray
3148 {
32- //编写本类除了整合边框信息外,更重要的原因是如果不对画笔做额外处理,
33- //Draw出来的边框是不理想的。本类的原理是:
34- // - 偶数边框(这是得到理想效果的前提)
35- // - 再利用画笔的CompoundArray属性将边框裁切掉一半,
36- // 同时根据不同参数偏移描边位置,达到可内可外可居中的效果
37-
38- float [ ] _compoundArray ;
39- /// <summary>
40- /// 根据_direction处理线段
41- /// </summary>
42- float [ ] CompoundArray
49+ get
4350 {
44- get
51+ _compoundArray ??= new float [ 2 ] ;
52+
53+ switch ( _direction )
4554 {
46- if ( _compoundArray == null )
47- {
48- _compoundArray = new float [ 2 ] ;
49- }
50- switch ( _direction )
51- {
52- case Direction . Middle : goto default ;
53- case Direction . Inner : _compoundArray [ 0 ] = 0.5f ; _compoundArray [ 1 ] = 1f ; break ;
54- case Direction . Outer : _compoundArray [ 0 ] = 0f ; _compoundArray [ 1 ] = 0.5f ; break ;
55- default : _compoundArray [ 0 ] = 0.25f ; _compoundArray [ 1 ] = 0.75f ; break ;
56- }
57- return _compoundArray ;
55+ case Direction . Middle : goto default ;
56+ case Direction . Inner :
57+ _compoundArray [ 0 ] = 0.5f ;
58+ _compoundArray [ 1 ] = 1f ;
59+ break ;
60+ case Direction . Outer :
61+ _compoundArray [ 0 ] = 0f ;
62+ _compoundArray [ 1 ] = 0.5f ;
63+ break ;
64+ default :
65+ _compoundArray [ 0 ] = 0.25f ;
66+ _compoundArray [ 1 ] = 0.75f ;
67+ break ;
5868 }
69+
70+ return _compoundArray ;
5971 }
72+ }
6073
61- readonly Pen _pen ;
74+ /// <summary>
75+ /// 获取用于画本边框的画笔。建议销毁本类而不是该画笔
76+ /// </summary>
77+ public Pen Pen { get ; }
6278
63- /// <summary>
64- /// 获取用于画本边框的画笔。建议销毁本类而不是该画笔
65- /// </summary>
66- public Pen Pen => _pen ;
79+ /// <summary>
80+ /// 边框宽度。默认1
81+ /// </summary>
82+ public int Width
83+ {
84+ get => ( int ) Pen . Width / 2 ;
85+ set => Pen . Width = value * 2 ;
86+ }
6787
68- /// <summary>
69- /// 边框宽度。默认1
70- /// </summary>
71- public int Width
72- {
73- get => ( int ) Pen . Width / 2 ;
74- set => Pen . Width = value * 2 ;
75- }
88+ /// <summary>
89+ /// 边框颜色
90+ /// </summary>
91+ public Color Color
92+ {
93+ get => Pen . Color ;
94+ set => Pen . Color = value ;
95+ }
7696
77- /// <summary>
78- /// 边框颜色
79- /// </summary>
80- public Color Color
81- {
82- get => Pen . Color ;
83- set => Pen . Color = value ;
84- }
97+ Direction _direction ;
8598
86- Direction _direction ;
87- /// <summary>
88- /// 边框位置。默认居中
89- /// </summary>
90- public Direction Direction
99+ /// <summary>
100+ /// 边框位置。默认居中
101+ /// </summary>
102+ public Direction Direction
103+ {
104+ get => _direction ;
105+ set
91106 {
92- get => _direction ;
93- set
94- {
95- if ( _direction == value ) { return ; }
96- _direction = value ;
97- Pen . CompoundArray = CompoundArray ;
98- }
99- }
107+ if ( _direction == value )
108+ return ;
100109
101- /// <summary>
102- /// 描边是否躲在填充之后。默认false
103- /// <para>- 如果躲,则处于内部的部分会被填充遮挡,反之则是填充被这部分边框遮挡</para>
104- /// <para>- 此属性仅供外部在绘制时确定描边和填充的次序</para>
105- /// </summary>
106- public bool Behind { get ; set ; }
107-
108- /// <summary>
109- /// 获取指定矩形加上本边框后的边界
110- /// </summary>
111- public Rectangle GetBounds ( Rectangle rectangle )
112- {
113- if ( ! IsValid ( ) || _direction == Direction . Inner )
114- {
115- return rectangle ;
116- }
117- var inflate = _direction == Direction . Middle
118- ? ( int ) Math . Ceiling ( Width / 2d )
119- : Width ;
120- rectangle . Inflate ( inflate , inflate ) ;
121- return rectangle ;
110+ _direction = value ;
111+ Pen . CompoundArray = CompoundArray ;
122112 }
113+ }
123114
124- /// <summary>
125- /// 指定颜色构造画笔
126- /// </summary>
127- public Border ( Color color ) : this ( color , 1 ) { }
115+ /// <summary>
116+ /// 描边是否躲在填充之后。默认false
117+ /// <para>- 如果躲,则处于内部的部分会被填充遮挡,反之则是填充被这部分边框遮挡</para>
118+ /// <para>- 此属性仅供外部在绘制时确定描边和填充的次序</para>
119+ /// </summary>
120+ public bool Behind { get ; set ; }
128121
129- /// <summary>
130- /// 指定颜色和宽度构造画笔
131- /// </summary>
132- public Border ( Color color , int width ) : this ( new Pen ( color , width ) , false ) { }
122+ /// <summary>
123+ /// 获取指定矩形加上本边框后的边界
124+ /// </summary>
125+ public Rectangle GetBounds ( Rectangle rectangle )
126+ {
127+ if ( ! IsValid ( ) || _direction == Direction . Inner )
128+ return rectangle ;
133129
134- /// <summary>
135- /// 基于现有画笔的副本构造
136- /// </summary>
137- public Border ( Pen pen ) : this ( pen , true ) { }
130+ var inflate = _direction == Direction . Middle
131+ ? ( int ) Math . Ceiling ( Width / 2d )
132+ : Width ;
138133
139- protected Border ( Pen pen , bool useCopy )
140- {
141- _pen = useCopy ? ( Pen ) pen . Clone ( ) : pen ;
142- _pen . Alignment = PenAlignment . Center ;
143- _pen . Width = _pen . Width * 2 ;
144- _pen . CompoundArray = CompoundArray ;
145- }
134+ rectangle . Inflate ( inflate , inflate ) ;
135+ return rectangle ;
136+ }
146137
147- /// <summary>
148- /// 是否有效边框。无宽度或完全透明视为无效
149- /// </summary>
150- public bool IsValid ( ) => Width > 0 && ( Pen . PenType != PenType . SolidColor || Color . A > 0 ) ;
138+ /// <summary>
139+ /// 指定颜色构造画笔
140+ /// </summary>
141+ public Border ( Color color ) : this ( color , 1 )
142+ {
143+ }
151144
152- /// <summary>
153- /// 是否有效边框。无宽度或完全透明视为无效
154- /// </summary>
155- public static bool IsValid ( Border border ) => border != null && border . IsValid ( ) ;
145+ /// <summary>
146+ /// 指定颜色和宽度构造画笔
147+ /// </summary>
148+ public Border ( Color color , int width ) : this ( new Pen ( color , width ) , false )
149+ {
150+ }
156151
157- /// <summary>
158- /// 确定指定颜色和宽度能否构成有效边框。有效=有色+有宽度
159- /// </summary>
160- public static bool IsValid ( Color color , int width ) => width > 0 && color . A > 0 ;
152+ /// <summary>
153+ /// 基于现有画笔的副本构造
154+ /// </summary>
155+ public Border ( Pen pen ) : this ( pen , true )
156+ {
157+ }
161158
162- /// <inheritdoc />
163- public void Dispose ( ) => Pen ? . Dispose ( ) ;
159+ /// <summary>
160+ /// 基于现有画笔构造
161+ /// </summary>
162+ protected Border ( Pen pen , bool useCopy )
163+ {
164+ Pen = useCopy ? ( Pen ) pen . Clone ( ) : pen ;
165+ Pen . Alignment = PenAlignment . Center ;
166+ Pen . Width *= 2 ;
167+ Pen . CompoundArray = CompoundArray ;
164168 }
165- }
169+
170+ /// <summary>
171+ /// 是否有效边框。无宽度或完全透明视为无效
172+ /// </summary>
173+ public bool IsValid ( ) => Width > 0 && ( Pen . PenType != PenType . SolidColor || Color . A > 0 ) ;
174+
175+ /// <summary>
176+ /// 是否有效边框。无宽度或完全透明视为无效
177+ /// </summary>
178+ public static bool IsValid ( Border border ) => border != null && border . IsValid ( ) ;
179+
180+ /// <summary>
181+ /// 确定指定颜色和宽度能否构成有效边框。有效=有色+有宽度
182+ /// </summary>
183+ public static bool IsValid ( Color color , int width ) => width > 0 && color . A > 0 ;
184+
185+ /// <inheritdoc />
186+ public void Dispose ( ) => Pen ? . Dispose ( ) ;
187+ }
0 commit comments