1 | unit ColGrad; |
2 | |
3 | interface |
4 | |
5 | Uses Graphics; |
6 | |
7 | Type |
8 | TColArray = Record |
9 | Bytes : Array [0..3] Of Byte; |
10 | End; |
11 | |
12 | TGradientPoint = Class (TObject) |
13 | Protected |
14 | IColour : TColor; |
15 | IPosition : Single; |
16 | INext : TGradientPoint; |
17 | |
18 | Procedure ISetPosition (Pos : Single); |
19 | |
20 | Public |
21 | Constructor Create; Overload; Virtual; |
22 | Constructor Create (Col : TColor; Pos : Single); Overload; Virtual; |
23 | Destructor Destroy; Override; |
24 | |
25 | Property Colour : TColor Read IColour Write IColour; |
26 | Property Position : Single Read IPosition Write ISetPosition; |
27 | Property Next : TGradientPoint Read INext Write INext; |
28 | |
29 | End; |
30 | |
31 | TGradientPoints = Class (TObject) |
32 | Protected |
33 | IPoints : TGradientPoint; |
34 | ICount : LongInt; |
35 | |
36 | Function IGetPoint (PointIndex : LongInt) : TGradientPoint; |
37 | |
38 | Public |
39 | Constructor Create; Virtual; |
40 | Destructor Destroy; Override; |
41 | |
42 | Property Count : LongInt Read ICount; |
43 | Property Points [PointIndex : LongInt] : TGradientPoint Read IGetPoint; Default; |
44 | |
45 | Procedure Add (NewPoint : TGradientPoint); Virtual; |
46 | Procedure Delete (Point : TGradientPoint); Virtual; |
47 | Procedure Clear; Virtual; |
48 | |
49 | End; |
50 | |
51 | TColourGradient = Class (TObject) |
52 | Protected |
53 | IHighColour, ILowColour : TColor; |
54 | IPoints : TGradientPoints; |
55 | |
56 | Public |
57 | Constructor Create; Overload; Virtual; |
58 | Constructor Create (HiCol, LoCol : TColor); Overload; Virtual; |
59 | Destructor Destroy; Override; |
60 | |
61 | Property HighColour : TColor Read IHighColour Write IHighColour; |
62 | Property LowColour : TColor Read ILowColour Write ILowColour; |
63 | Property Points : TGradientPoints Read IPoints; |
64 | |
65 | Function ColourAtPosition (Pos : Single) : TColor; Virtual; |
66 | Procedure Copy (ToGrad : TColourGradient); Virtual; |
67 | |
68 | End; |
69 | |
70 | implementation |
71 | |
72 | Procedure TGradientPoint.ISetPosition (Pos : Single); |
73 | Begin |
74 | If Pos < 0 Then |
75 | IPosition := 0 |
76 | Else |
77 | If Pos > 1 Then |
78 | IPosition := 1 |
79 | Else |
80 | IPosition := Pos; |
81 | End; |
82 | |
83 | Constructor TGradientPoint.Create; |
84 | Begin |
85 | Inherited Create; |
86 | IColour := clGray; |
87 | IPosition := 0.5; |
88 | INext := NIL; |
89 | End; |
90 | |
91 | Constructor TGradientPoint.Create (Col : TColor; Pos : Single); |
92 | Begin |
93 | Inherited Create; |
94 | IColour := Col; |
95 | IPosition := Pos; |
96 | INext := NIL; |
97 | End; |
98 | |
99 | Destructor TGradientPoint.Destroy; |
100 | Begin |
101 | Inherited; |
102 | End; |
103 | |
104 | Function TGradientPoints.IGetPoint (PointIndex : LongInt) : TGradientPoint; |
105 | Var |
106 | Count : LongInt; |
107 | Current : TGradientPoint; |
108 | Begin |
109 | If PointIndex >= ICount Then |
110 | Result := NIL |
111 | Else |
112 | Begin |
113 | Current := IPoints; |
114 | For Count := 1 To PointIndex Do |
115 | Current := Current.Next; |
116 | Result := Current; |
117 | End; |
118 | End; |
119 | |
120 | Constructor TGradientPoints.Create; |
121 | Begin |
122 | Inherited Create; |
123 | IPoints := NIL; |
124 | ICount := 0; |
125 | End; |
126 | |
127 | Destructor TGradientPoints.Destroy; |
128 | Begin |
129 | Self.Clear; |
130 | Inherited; |
131 | End; |
132 | |
133 | Procedure TGradientPoints.Add (NewPoint : TGradientPoint); |
134 | Var |
135 | Current : TGradientPoint; |
136 | Begin |
137 | If IPoints = NIL Then |
138 | IPoints := NewPoint |
139 | Else |
140 | Begin |
141 | Current := IPoints; |
142 | While Current.Next <> NIL Do |
143 | Current := Current.Next; |
144 | Current.Next := NewPoint; |
145 | End; |
146 | ICount := ICount + 1; |
147 | End; |
148 | |
149 | Procedure TGradientPoints.Delete (Point : TGradientPoint); |
150 | Var |
151 | Current, Previous : TGradientPoint; |
152 | Found : Boolean; |
153 | Begin |
154 | If IPoints = Point Then |
155 | Begin |
156 | Previous := IPoints; |
157 | IPoints := IPoints.Next; |
158 | Previous.Free; |
159 | ICount := ICount - 1; |
160 | End |
161 | Else |
162 | Begin |
163 | Current := IPoints; |
164 | Found := False; |
165 | While (Current.Next <> NIL) And (Not (Found)) Do |
166 | Begin |
167 | If Current.Next = Point Then |
168 | Begin |
169 | Previous := Current.Next; |
170 | Current.Next := Current.Next.Next; |
171 | Previous.Free; |
172 | Found := True; |
173 | ICount := ICount - 1; |
174 | End |
175 | Else |
176 | Current := Current.Next; |
177 | End; |
178 | End; |
179 | End; |
180 | |
181 | Procedure TGradientPoints.Clear; |
182 | Var |
183 | Current, Previous : TGradientPoint; |
184 | Begin |
185 | Current := IPoints; |
186 | While Current <> NIL Do |
187 | Begin |
188 | Previous := Current; |
189 | Current := Current.Next; |
190 | Previous.Free; |
191 | End; |
192 | ICount := 0; |
193 | IPoints := NIL; |
194 | End; |
195 | |
196 | Constructor TColourGradient.Create; |
197 | Begin |
198 | Inherited Create; |
199 | ILowColour := clGray; |
200 | IHighColour := clGray; |
201 | IPoints := TGradientPoints.Create; |
202 | End; |
203 | |
204 | Constructor TColourGradient.Create (HiCol, LoCol : TColor); |
205 | Begin |
206 | Inherited Create; |
207 | IHighColour := HiCol; |
208 | ILowColour := LoCol; |
209 | IPoints := TGradientPoints.Create; |
210 | End; |
211 | |
212 | Destructor TColourGradient.Destroy; |
213 | Begin |
214 | IPoints.Free; |
215 | Inherited; |
216 | End; |
217 | |
218 | Function TColourGradient.ColourAtPosition (Pos : Single) : TColor; |
219 | Var |
220 | CurrentPoint : TGradientPoint; |
221 | HiPoint, LoPoint, MidPoint : Single; |
222 | HiCol, LoCol, ResCol : TColArray; |
223 | BytePos : Byte; |
224 | Begin |
225 | If Pos < 0 Then |
226 | Result := IHighColour |
227 | Else |
228 | If Pos > 1 Then |
229 | Result := ILowColour |
230 | Else |
231 | Begin |
232 | HiPoint := 0; |
233 | LoPoint := 1; |
234 | Move (IHighColour, HiCol, 4); |
235 | Move (ILowColour, LoCol, 4); |
236 | |
237 | CurrentPoint := IPoints [0]; |
238 | While CurrentPoint <> NIL Do |
239 | Begin |
240 | If (CurrentPoint.Position <= Pos) And |
241 | (CurrentPoint.Position >= HiPoint) Then |
242 | Begin |
243 | HiPoint := CurrentPoint.Position; |
244 | Move (CurrentPoint.Colour, HiCol, 4); |
245 | End; |
246 | CurrentPoint := CurrentPoint.Next; |
247 | End; |
248 | |
249 | CurrentPoint := IPoints [0]; |
250 | While CurrentPoint <> NIL Do |
251 | Begin |
252 | If (CurrentPoint.Position >= Pos) And |
253 | (CurrentPoint.Position <= LoPoint) Then |
254 | Begin |
255 | LoPoint := CurrentPoint.Position; |
256 | Move (CurrentPoint.Colour, LoCol, 4); |
257 | End; |
258 | CurrentPoint := CurrentPoint.Next; |
259 | End; |
260 | |
261 | If HiPoint = LoPoint Then |
262 | ResCol := LoCol |
263 | Else |
264 | Begin |
265 | MidPoint := (Pos - HiPoint) / (LoPoint - HiPoint); |
266 | For BytePos := 0 To 3 Do |
267 | Begin |
268 | HiPoint := HiCol.Bytes [BytePos]; |
269 | LoPoint := LoCol.Bytes [BytePos]; |
270 | ResCol.Bytes [BytePos] := Round (HiPoint + ((LoPoint - HiPoint) * MidPoint)); |
271 | End; |
272 | End; |
273 | |
274 | Move (ResCol, Result, 4); |
275 | End; |
276 | End; |
277 | |
278 | Procedure TColourGradient.Copy (ToGrad : TColourGradient); |
279 | Var |
280 | Current : TGradientPoint; |
281 | Begin |
282 | ToGrad.LowColour := ILowColour; |
283 | ToGrad.HighColour := IHighColour; |
284 | ToGrad.Points.Clear; |
285 | Current := IPoints [0]; |
286 | While Current <> NIL Do |
287 | Begin |
288 | ToGrad.Points.Add (TGradientPoint.Create (Current.Colour, Current.Position)); |
289 | Current := Current.Next; |
290 | End; |
291 | End; |
292 | |
293 | end. |