1 | unit BGRAGradients;
|
---|
2 |
|
---|
3 | {$mode objfpc}{$H+}
|
---|
4 | {$i bgrabitmap.inc}
|
---|
5 | {$i bgrasse.inc}
|
---|
6 |
|
---|
7 | interface
|
---|
8 |
|
---|
9 | { Here are various functions that draw gradients, shadow and lighting }
|
---|
10 |
|
---|
11 | uses
|
---|
12 | Classes, BGRAGraphics, BGRABitmapTypes, BGRABitmap, BGRABlend, BGRAPhongTypes, BGRASSE;
|
---|
13 |
|
---|
14 | {$IFDEF BGRABITMAP_USE_LCL}{ Creates a bitmap with the specified text horizontally centered and with a shadow }
|
---|
15 | function TextShadow(AWidth,AHeight: Integer; AText: String; AFontHeight: Integer; ATextColor,AShadowColor: TBGRAPixel;
|
---|
16 | AOffSetX,AOffSetY: Integer; ARadius: Integer = 0; AFontStyle: TFontStyles = []; AFontName: String = 'Default'; AShowText: Boolean = True): TBGRABitmap;
|
---|
17 | {$ENDIF}
|
---|
18 |
|
---|
19 | {----------------------------------------------------------------------}
|
---|
20 | { Functions to draw multiple gradients.
|
---|
21 | See : http://wiki.lazarus.freepascal.org/Double_Gradient#nGradient }
|
---|
22 | type
|
---|
23 | TnGradientInfo = record
|
---|
24 | StartColor,StopColor: TBGRAPixel;
|
---|
25 | Direction: TGradientDirection;
|
---|
26 | EndPercent : single; // Position from 0 to 1
|
---|
27 | end;
|
---|
28 |
|
---|
29 | function nGradientInfo(StartColor, StopColor: TBGRAPixel; Direction: TGradientDirection; EndPercent: Single): TnGradientInfo;
|
---|
30 |
|
---|
31 | function nGradientAlphaFill(ARect: TRect; ADir: TGradientDirection; const AGradient: array of TnGradientInfo): TBGRABitmap; overload;
|
---|
32 | function nGradientAlphaFill(AWidth, AHeight: Integer; ADir: TGradientDirection; const AGradient: array of TnGradientInfo): TBGRABitmap; overload;
|
---|
33 | procedure nGradientAlphaFill(ACanvas: TCanvas; ARect: TRect; ADir: TGradientDirection; const AGradient: array of TnGradientInfo); overload;
|
---|
34 | procedure nGradientAlphaFill(ABitmap: TBGRABitmap; ARect: TRect; ADir: TGradientDirection; const AGradient: array of TnGradientInfo); overload;
|
---|
35 |
|
---|
36 | function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
|
---|
37 | ADirection1,ADirection2,ADir: TGradientDirection; AValue: Single): TBGRABitmap; overload;
|
---|
38 | function DoubleGradientAlphaFill(AWidth,AHeight: Integer; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
|
---|
39 | ADirection1,ADirection2,ADir: TGradientDirection; AValue: Single): TBGRABitmap; overload;
|
---|
40 | procedure DoubleGradientAlphaFill(ACanvas: TCanvas; ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
|
---|
41 | ADirection1,ADirection2,ADir: TGradientDirection; AValue: Single); overload;
|
---|
42 | procedure DoubleGradientAlphaFill(ABitmap: TBGRABitmap; ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
|
---|
43 | ADirection1,ADirection2,ADir: TGradientDirection; AValue: Single); overload;
|
---|
44 |
|
---|
45 | {----------------------------------------------------------------------}
|
---|
46 | { Phong shading functions. Use a height map (grayscale image or a precise map filled with MapHeightToBGRA)
|
---|
47 | to determine orientation and position of the surface.
|
---|
48 |
|
---|
49 | Phong shading consist in adding an ambiant light, a diffuse light (angle between light and object),
|
---|
50 | and a specular light (angle between light, object and observer, i.e. reflected light) }
|
---|
51 |
|
---|
52 | type
|
---|
53 | TRectangleMapOption = (rmoNoLeftBorder,rmoNoTopBorder,rmoNoRightBorder,rmoNoBottomBorder,rmoLinearBorder);
|
---|
54 | TRectangleMapOptions = set of TRectangleMapOption;
|
---|
55 |
|
---|
56 | { TPhongShading }
|
---|
57 |
|
---|
58 | TPhongShading = class(TCustomPhongShading)
|
---|
59 | LightSourceIntensity : Single; //global intensity of the light
|
---|
60 |
|
---|
61 | LightSourceDistanceTerm, //minimum distance always added (positive value)
|
---|
62 | LightSourceDistanceFactor, //how much actual distance is taken into account (usually 0 or 1)
|
---|
63 | LightDestFactor : Single; //how much the location of the lightened pixel is taken into account (usually 0 or 1)
|
---|
64 |
|
---|
65 | LightPositionZ : Integer;
|
---|
66 | LightColor: TBGRAPixel; //color of the light reflection
|
---|
67 |
|
---|
68 | SpecularFactor, //how much light is reflected (0..1)
|
---|
69 | SpecularIndex : Single; //how concentrated reflected light is (positive value)
|
---|
70 |
|
---|
71 | AmbientFactor, //ambiant lighting whereever the point is (0..1)
|
---|
72 | DiffusionFactor, //diffusion, i.e. how much pixels are lightened by light source (0..1)
|
---|
73 | NegativeDiffusionFactor : Single; //how much hidden surface are darkened (0..1)
|
---|
74 | DiffuseSaturation: Boolean; //when diffusion saturates, use light color to show it
|
---|
75 |
|
---|
76 | constructor Create;
|
---|
77 |
|
---|
78 | { Render the specified map on the destination bitmap with one solid color. Map altitude
|
---|
79 | indicate the global height of the map. }
|
---|
80 | procedure Draw(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
81 | Color : TBGRAPixel); override;
|
---|
82 |
|
---|
83 | { Render with a color map of the same size as the height map. Map altitude
|
---|
84 | indicate the global height of the map. }
|
---|
85 | procedure Draw(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
86 | ColorMap : TBGRACustomBitmap); override;
|
---|
87 |
|
---|
88 | { Render with a color scanner. Map altitude
|
---|
89 | indicate the global height of the map. }
|
---|
90 | procedure DrawScan(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
91 | ColorScan : IBGRAScanner); override;
|
---|
92 |
|
---|
93 | { Draw a cone of the specified color }
|
---|
94 | procedure DrawCone(dest: TBGRACustomBitmap; X,Y,Size,Altitude: Integer; Color: TBGRAPixel); overload;
|
---|
95 | procedure DrawCone(dest: TBGRACustomBitmap; bounds: TRect; Altitude: Integer; Color: TBGRAPixel); overload;
|
---|
96 |
|
---|
97 | { Draw a vertical cone of the specified color }
|
---|
98 | procedure DrawVerticalCone(dest: TBGRACustomBitmap; bounds: TRect; Altitude: Integer; Color: TBGRAPixel);
|
---|
99 |
|
---|
100 | { Draw an horizontal cylinder of the specified color }
|
---|
101 | procedure DrawHorizontalCylinder(dest: TBGRACustomBitmap; bounds: TRect; Altitude: Integer; Color: TBGRAPixel);
|
---|
102 |
|
---|
103 | { Draw a vertical cylinder of the specified color }
|
---|
104 | procedure DrawVerticalCylinder(dest: TBGRACustomBitmap; bounds: TRect; Altitude: Integer; Color: TBGRAPixel);
|
---|
105 |
|
---|
106 | { Draw a hemisphere of the specified color }
|
---|
107 | procedure DrawSphere(dest: TBGRACustomBitmap; bounds: TRect; Altitude: Integer; Color: TBGRAPixel);
|
---|
108 |
|
---|
109 | { Draw a rectangle of the specified color }
|
---|
110 | procedure DrawRectangle(dest: TBGRACustomBitmap; bounds: TRect; Border,Altitude: Integer; Color: TBGRAPixel; RoundCorners: Boolean; Options: TRectangleMapOptions);
|
---|
111 | protected
|
---|
112 |
|
---|
113 | procedure DrawMapNormal(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
114 | ColorMap : TBGRACustomBitmap);
|
---|
115 | procedure DrawScannerNormal(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
116 | ColorScan : IBGRAScanner);
|
---|
117 | procedure DrawColorNormal(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
118 | Color : TBGRAPixel);
|
---|
119 |
|
---|
120 | {$ifdef BGRASSE_AVAILABLE}
|
---|
121 | procedure DrawMapSSE(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
122 | ColorMap : TBGRACustomBitmap);
|
---|
123 | procedure DrawScannerSSE(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
124 | ColorScan : IBGRAScanner);
|
---|
125 | procedure DrawColorSSE(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
126 | Color : TBGRAPixel);
|
---|
127 | {$endif}
|
---|
128 |
|
---|
129 | end;
|
---|
130 |
|
---|
131 | { Create a grayscale height map for a cone (may not be precise enough) }
|
---|
132 | function CreateConeMap(size: integer): TBGRABitmap;
|
---|
133 |
|
---|
134 | { Create a precise height map for a cone (not grayscale anymore but more precise) }
|
---|
135 | function CreateConePreciseMap(width,height: integer): TBGRABitmap;
|
---|
136 |
|
---|
137 | { Create a precise height map for a vertical cone (not grayscale anymore but more precise) }
|
---|
138 | function CreateVerticalConePreciseMap(width,height: integer): TBGRABitmap;
|
---|
139 |
|
---|
140 | { Create a precise height map for a vertical cylinder (not grayscale anymore but more precise) }
|
---|
141 | function CreateVerticalCylinderPreciseMap(width,height: integer): TBGRABitmap;
|
---|
142 |
|
---|
143 | { Create a precise height map for an horizontal cylinder (not grayscale anymore but more precise) }
|
---|
144 | function CreateHorizontalCylinderPreciseMap(width,height: integer): TBGRABitmap;
|
---|
145 |
|
---|
146 | { Create a grayscale height map for a sphere (may not be precise enough) }
|
---|
147 | function CreateSphereMap(width,height: integer): TBGRABitmap;
|
---|
148 |
|
---|
149 | { Create a precise height map for a sphere (not grayscale anymore but more precise) }
|
---|
150 | function CreateSpherePreciseMap(width,height: integer): TBGRABitmap;
|
---|
151 |
|
---|
152 | { Create a rectangle height map with a border }
|
---|
153 | function CreateRectangleMap(width,height,border: integer; options: TRectangleMapOptions = []): TBGRABitmap;
|
---|
154 |
|
---|
155 | { Create a precise height map for a rectangle height map with a border (not grayscale anymore but more precise) }
|
---|
156 | function CreateRectanglePreciseMap(width,height,border: integer; options: TRectangleMapOptions = []): TBGRABitmap;
|
---|
157 | function CreateRectanglePreciseMap(width, height, borderWidth, borderHeight: integer; options: TRectangleMapOptions): TBGRABitmap;
|
---|
158 |
|
---|
159 | { Create a round rectangle height map with a border }
|
---|
160 | function CreateRoundRectangleMap(width,height,border: integer; options: TRectangleMapOptions = []): TBGRABitmap;
|
---|
161 |
|
---|
162 | { Create a precise height map for a round rectangle height map with a border (not grayscale anymore but more precise) }
|
---|
163 | function CreateRoundRectanglePreciseMap(width,height,border: integer; options: TRectangleMapOptions = []): TBGRABitmap;
|
---|
164 | function CreateRoundRectanglePreciseMap(width,height,borderWidth,borderHeight: integer; options: TRectangleMapOptions = []): TBGRABitmap;
|
---|
165 |
|
---|
166 | {---------- Perlin Noise -------------}
|
---|
167 | { Random image using a superposition of interpolated random values.
|
---|
168 | See : http://wiki.lazarus.freepascal.org/Perlin_Noise
|
---|
169 | http://freespace.virgin.net/hugo.elias/models/m_perlin.htm }
|
---|
170 |
|
---|
171 | { Creates a non-tilable random grayscale image }
|
---|
172 | function CreatePerlinNoiseMap(AWidth, AHeight: integer; HorizontalPeriod: Single = 1;
|
---|
173 | VerticalPeriod: Single = 1; Exponent: Double = 1; ResampleFilter: TResampleFilter = rfCosine): TBGRABitmap;
|
---|
174 |
|
---|
175 | { Creates a tilable random grayscale image }
|
---|
176 | function CreateCyclicPerlinNoiseMap(AWidth, AHeight: integer; HorizontalPeriod: Single = 1;
|
---|
177 | VerticalPeriod: Single = 1; Exponent: Double = 1; ResampleFilter: TResampleFilter = rfCosine): TBGRABitmap;
|
---|
178 |
|
---|
179 | implementation
|
---|
180 |
|
---|
181 | uses Types, Math, SysUtils{$IFDEF BGRABITMAP_USE_LCL}, BGRATextFX{$ENDIF}; {GraphType unit used by phongdraw.inc}
|
---|
182 |
|
---|
183 | {$IFDEF BGRABITMAP_USE_LCL}function TextShadow(AWidth, AHeight: Integer; AText: String;
|
---|
184 | AFontHeight: Integer; ATextColor, AShadowColor: TBGRAPixel; AOffSetX,
|
---|
185 | AOffSetY: Integer; ARadius: Integer; AFontStyle: TFontStyles;
|
---|
186 | AFontName: String; AShowText: Boolean): TBGRABitmap;
|
---|
187 | begin
|
---|
188 | result := BGRATextFX.TextShadow(AWidth,AHeight,AText,AFontHeight,ATextColor,AShadowColor,AOffsetX,AOffsetY,ARadius,AFontStyle,AFontName,AShowText) as TBGRABitmap;
|
---|
189 | end;{$ENDIF}
|
---|
190 |
|
---|
191 | function nGradientInfo(StartColor, StopColor: TBGRAPixel;
|
---|
192 | Direction: TGradientDirection; EndPercent: Single): TnGradientInfo;
|
---|
193 | begin
|
---|
194 | result.StartColor := StartColor;
|
---|
195 | result.StopColor := StopColor;
|
---|
196 | result.Direction := Direction;
|
---|
197 | result.EndPercent := EndPercent;
|
---|
198 | end;
|
---|
199 |
|
---|
200 | function DoubleGradientAlphaFill(ARect: TRect; AStart1,AStop1,AStart2,AStop2: TBGRAPixel;
|
---|
201 | ADirection1,ADirection2,ADir: TGradientDirection; AValue: Single): TBGRABitmap;
|
---|
202 | var
|
---|
203 | ABitmap: TBGRABitmap;
|
---|
204 | ARect1,ARect2: TRect;
|
---|
205 | APoint1,APoint2,APoint3,APoint4: TPointF;
|
---|
206 | begin
|
---|
207 | Dec(ARect.Right, ARect.Left);
|
---|
208 | ARect.Left := 0;
|
---|
209 | Dec(ARect.Bottom,ARect.Top);
|
---|
210 | ARect.Top := 0;
|
---|
211 |
|
---|
212 | ABitmap := TBGRABitmap.Create(ARect.Right,ARect.Bottom);
|
---|
213 |
|
---|
214 | if AValue <> 0 then ARect1:=ARect;
|
---|
215 | if AValue <> 1 then ARect2:=ARect;
|
---|
216 |
|
---|
217 | if ADir = gdVertical then begin
|
---|
218 | ARect1.Bottom:=Round(ARect1.Bottom * AValue);
|
---|
219 | ARect2.Top:=ARect1.Bottom;
|
---|
220 | end
|
---|
221 | else if ADir = gdHorizontal then begin
|
---|
222 | ARect1.Right:=Round(ARect1.Right * AValue);
|
---|
223 | ARect2.Left:=ARect1.Right;
|
---|
224 | end;
|
---|
225 | if ADirection1 = gdVertical then begin
|
---|
226 | APoint1:=PointF(ARect1.Left,ARect1.Top);
|
---|
227 | APoint2:=PointF(ARect1.Left,ARect1.Bottom);
|
---|
228 | end
|
---|
229 | else if ADirection1 = gdHorizontal then begin
|
---|
230 | APoint1:=PointF(ARect1.Left,ARect1.Top);
|
---|
231 | APoint2:=PointF(ARect1.Right,ARect1.Top);
|
---|
232 | end;
|
---|
233 | if ADirection2 = gdVertical then begin
|
---|
234 | APoint3:=PointF(ARect2.Left,ARect2.Top);
|
---|
235 | APoint4:=PointF(ARect2.Left,ARect2.Bottom);
|
---|
236 | end
|
---|
237 | else if ADirection2 = gdHorizontal then begin
|
---|
238 | APoint3:=PointF(ARect2.Left,ARect2.Top);
|
---|
239 | APoint4:=PointF(ARect2.Right,ARect2.Top);
|
---|
240 | end;
|
---|
241 |
|
---|
242 | if AValue <> 0 then
|
---|
243 | ABitmap.GradientFill(ARect1.Left,ARect1.Top,ARect1.Right,ARect1.Bottom,
|
---|
244 | AStart1,AStop1,gtLinear,APoint1,APoint2,dmSet,True);
|
---|
245 | if AValue <> 1 then
|
---|
246 | ABitmap.GradientFill( ARect2.Left,ARect2.Top,ARect2.Right,ARect2.Bottom,
|
---|
247 | AStart2,AStop2,gtLinear,APoint3,APoint4,dmSet,True);
|
---|
248 |
|
---|
249 | Result:=ABitmap;
|
---|
250 | end;
|
---|
251 |
|
---|
252 | function DoubleGradientAlphaFill(AWidth, AHeight: Integer; AStart1, AStop1,
|
---|
253 | AStart2, AStop2: TBGRAPixel; ADirection1, ADirection2,
|
---|
254 | ADir: TGradientDirection; AValue: Single): TBGRABitmap;
|
---|
255 | begin
|
---|
256 | result := DoubleGradientAlphaFill(Rect(0,0,AWidth,AHeight),
|
---|
257 | AStart1,AStop1,AStart2,AStop2,
|
---|
258 | ADirection1,ADirection2, ADir, AValue);
|
---|
259 | end;
|
---|
260 |
|
---|
261 | procedure DoubleGradientAlphaFill(ACanvas: TCanvas; ARect: TRect; AStart1,
|
---|
262 | AStop1, AStart2, AStop2: TBGRAPixel; ADirection1, ADirection2,
|
---|
263 | ADir: TGradientDirection; AValue: Single);
|
---|
264 | var
|
---|
265 | bmp: TBGRABitmap;
|
---|
266 | begin
|
---|
267 | bmp := DoubleGradientAlphaFill(ARect,AStart1,AStop1,AStart2,AStop2,ADirection1,ADirection2,ADir,AValue);
|
---|
268 | bmp.Draw(ACanvas,ARect.Left,ARect.Top,not bmp.HasTransparentPixels);
|
---|
269 | bmp.Free;
|
---|
270 | end;
|
---|
271 |
|
---|
272 | procedure DoubleGradientAlphaFill(ABitmap: TBGRABitmap; ARect: TRect; AStart1,
|
---|
273 | AStop1, AStart2, AStop2: TBGRAPixel; ADirection1, ADirection2,
|
---|
274 | ADir: TGradientDirection; AValue: Single);
|
---|
275 | var
|
---|
276 | bmp: TBGRABitmap;
|
---|
277 | begin
|
---|
278 | bmp := DoubleGradientAlphaFill(ARect,AStart1,AStop1,AStart2,AStop2,ADirection1,ADirection2,ADir,AValue);
|
---|
279 | ABitmap.PutImage(ARect.Left,ARect.Top,bmp,dmDrawWithTransparency);
|
---|
280 | bmp.Free;
|
---|
281 | end;
|
---|
282 |
|
---|
283 | function nGradientAlphaFill(ARect: TRect; ADir: TGradientDirection;
|
---|
284 | const AGradient: array of TnGradientInfo): TBGRABitmap;
|
---|
285 | var
|
---|
286 | i:integer;
|
---|
287 | AnRect, OldRect: TRect;
|
---|
288 | Point1, Point2: TPointF;
|
---|
289 | begin
|
---|
290 | Result := TBGRABitmap.Create(ARect.Right-ARect.Left,ARect.Bottom-ARect.Top);
|
---|
291 | Dec(ARect.Right, ARect.Left);
|
---|
292 | ARect.Left := 0;
|
---|
293 | Dec(ARect.Bottom,ARect.Top);
|
---|
294 | ARect.Top := 0;
|
---|
295 |
|
---|
296 | OldRect := ARect;
|
---|
297 |
|
---|
298 | if ADir = gdVertical then
|
---|
299 | OldRect.Bottom := ARect.Top
|
---|
300 | else
|
---|
301 | OldRect.Right := ARect.Left;
|
---|
302 |
|
---|
303 | for i := 0 to high(AGradient) do
|
---|
304 | begin
|
---|
305 | AnRect:=OldRect;
|
---|
306 | if ADir = gdVertical then
|
---|
307 | begin
|
---|
308 | AnRect.Bottom:=Round((ARect.Bottom-ARect.Top) * AGradient[i].endPercent + ARect.Top);
|
---|
309 | AnRect.Top:=OldRect.Bottom;
|
---|
310 | Point1:=PointF(AnRect.Left,AnRect.Top);
|
---|
311 | Point2:=PointF(AnRect.Left,AnRect.Bottom);
|
---|
312 | end
|
---|
313 | else
|
---|
314 | begin
|
---|
315 | AnRect.Right:=Round((ARect.Right-ARect.Left) * AGradient[i].endPercent + ARect.Left);
|
---|
316 | AnRect.Left:=OldRect.Right;
|
---|
317 | Point1:=PointF(AnRect.Left,AnRect.Top);
|
---|
318 | Point2:=PointF(AnRect.Right,AnRect.Top);
|
---|
319 | end;
|
---|
320 | Result.GradientFill(AnRect.Left,AnRect.Top,AnRect.Right,AnRect.Bottom,
|
---|
321 | AGradient[i].StartColor,AGradient[i].StopColor,gtLinear,Point1,Point2,dmSet,True);
|
---|
322 | OldRect := AnRect;
|
---|
323 | end;
|
---|
324 | end;
|
---|
325 |
|
---|
326 | function nGradientAlphaFill(AWidth, AHeight: Integer; ADir: TGradientDirection;
|
---|
327 | const AGradient: array of TnGradientInfo): TBGRABitmap;
|
---|
328 | begin
|
---|
329 | result := nGradientAlphaFill(Rect(0,0,AWidth,AHeight),ADir,AGradient);
|
---|
330 | end;
|
---|
331 |
|
---|
332 | procedure nGradientAlphaFill(ACanvas: TCanvas; ARect: TRect;
|
---|
333 | ADir: TGradientDirection; const AGradient: array of TnGradientInfo);
|
---|
334 | var
|
---|
335 | bmp: TBGRABitmap;
|
---|
336 | begin
|
---|
337 | bmp := nGradientAlphaFill(ARect, ADir, AGradient);
|
---|
338 | bmp.Draw(ACanvas,ARect.Left,ARect.Top,not bmp.HasTransparentPixels);
|
---|
339 | bmp.Free;
|
---|
340 | end;
|
---|
341 |
|
---|
342 | procedure nGradientAlphaFill(ABitmap: TBGRABitmap; ARect: TRect;
|
---|
343 | ADir: TGradientDirection; const AGradient: array of TnGradientInfo);
|
---|
344 | var
|
---|
345 | bmp: TBGRABitmap;
|
---|
346 | begin
|
---|
347 | bmp := nGradientAlphaFill(ARect, ADir, AGradient);
|
---|
348 | ABitmap.PutImage(ARect.Left,ARect.Top,bmp,dmDrawWithTransparency);
|
---|
349 | bmp.Free;
|
---|
350 | end;
|
---|
351 |
|
---|
352 | { TPhongShading }
|
---|
353 |
|
---|
354 | constructor TPhongShading.Create;
|
---|
355 | begin
|
---|
356 | //set default values
|
---|
357 | LightSourceIntensity := 500;
|
---|
358 | LightSourceDistanceTerm := 150;
|
---|
359 | LightSourceDistanceFactor := 1;
|
---|
360 | LightDestFactor := 1;
|
---|
361 | LightColor := BGRAWhite;
|
---|
362 | AmbientFactor := 0.3;
|
---|
363 | DiffusionFactor := 0.9;
|
---|
364 | DiffuseSaturation:= False;
|
---|
365 | NegativeDiffusionFactor := 0.1;
|
---|
366 | SpecularFactor := 0.6;
|
---|
367 | SpecularIndex := 10;
|
---|
368 | LightPosition := Point(-100,-100);
|
---|
369 | LightPositionZ := 100;
|
---|
370 | end;
|
---|
371 |
|
---|
372 | Const
|
---|
373 | PhongLightPrecisionSh = 12;
|
---|
374 | PhongLightPrecision = 1 shl PhongLightPrecisionSh;
|
---|
375 | PhongLightPrecisionDiv2 = PhongLightPrecision shr 1;
|
---|
376 |
|
---|
377 | {------------------ Phong drawing ----------------}
|
---|
378 | { Look for the fastest method available }
|
---|
379 | procedure TPhongShading.Draw(dest: TBGRACustomBitmap; map: TBGRACustomBitmap; mapAltitude: integer; ofsX,ofsY: integer;
|
---|
380 | Color : TBGRAPixel);
|
---|
381 | begin
|
---|
382 | {$ifdef BGRASSE_AVAILABLE}
|
---|
383 | if UseSSE then
|
---|
384 | DrawColorSSE(dest,map,mapAltitude,ofsX,ofsY,Color)
|
---|
385 | else
|
---|
386 | {$endif}
|
---|
387 | DrawColorNormal(dest,map,mapAltitude,ofsX,ofsY,Color);
|
---|
388 | end;
|
---|
389 |
|
---|
390 | procedure TPhongShading.Draw(dest: TBGRACustomBitmap; map: TBGRACustomBitmap;
|
---|
391 | mapAltitude: integer; ofsX, ofsY: integer; ColorMap: TBGRACustomBitmap);
|
---|
392 | begin
|
---|
393 | {$ifdef BGRASSE_AVAILABLE}
|
---|
394 | if UseSSE then
|
---|
395 | DrawMapSSE(dest,map,mapAltitude,ofsX,ofsY,ColorMap)
|
---|
396 | else
|
---|
397 | {$endif}
|
---|
398 | DrawMapNormal(dest,map,mapAltitude,ofsX,ofsY,ColorMap);
|
---|
399 | end;
|
---|
400 |
|
---|
401 | procedure TPhongShading.DrawScan(dest: TBGRACustomBitmap; map: TBGRACustomBitmap;
|
---|
402 | mapAltitude: integer; ofsX, ofsY: integer; ColorScan: IBGRAScanner);
|
---|
403 | begin
|
---|
404 | {$ifdef BGRASSE_AVAILABLE}
|
---|
405 | if UseSSE then
|
---|
406 | DrawScannerSSE(dest,map,mapAltitude,ofsX,ofsY,ColorScan)
|
---|
407 | else
|
---|
408 | {$endif}
|
---|
409 | DrawScannerNormal(dest,map,mapAltitude,ofsX,ofsY,ColorScan);
|
---|
410 | end;
|
---|
411 |
|
---|
412 | {------------------ End of phong drawing ----------------}
|
---|
413 |
|
---|
414 | procedure TPhongShading.DrawCone(dest: TBGRACustomBitmap; X, Y, Size,
|
---|
415 | Altitude: Integer; Color: TBGRAPixel);
|
---|
416 | var map: TBGRABitmap;
|
---|
417 | begin
|
---|
418 | map := CreateConePreciseMap(Size,Size);
|
---|
419 | Draw(dest,map,Altitude,X,Y,Color);
|
---|
420 | map.Free;
|
---|
421 | end;
|
---|
422 |
|
---|
423 | procedure TPhongShading.DrawCone(dest: TBGRACustomBitmap; bounds: TRect;
|
---|
424 | Altitude: Integer; Color: TBGRAPixel);
|
---|
425 | var map: TBGRABitmap;
|
---|
426 | temp: integer;
|
---|
427 | begin
|
---|
428 | if Bounds.Right < Bounds.Left then
|
---|
429 | begin
|
---|
430 | temp := Bounds.Left;
|
---|
431 | bounds.Left := bounds.Right;
|
---|
432 | Bounds.Right := temp;
|
---|
433 | end;
|
---|
434 | if Bounds.Bottom < Bounds.Top then
|
---|
435 | begin
|
---|
436 | temp := Bounds.Bottom;
|
---|
437 | bounds.Bottom := bounds.Top;
|
---|
438 | Bounds.Top := temp;
|
---|
439 | end;
|
---|
440 | map := CreateConePreciseMap(Bounds.Right-Bounds.Left,Bounds.Bottom-Bounds.Top);
|
---|
441 | Draw(dest,map,Altitude,bounds.Left,bounds.Top,Color);
|
---|
442 | map.Free;
|
---|
443 | end;
|
---|
444 |
|
---|
445 | procedure TPhongShading.DrawVerticalCone(dest: TBGRACustomBitmap;
|
---|
446 | bounds: TRect; Altitude: Integer; Color: TBGRAPixel);
|
---|
447 | var map: TBGRABitmap;
|
---|
448 | temp: integer;
|
---|
449 | begin
|
---|
450 | if Bounds.Right < Bounds.Left then
|
---|
451 | begin
|
---|
452 | temp := Bounds.Left;
|
---|
453 | bounds.Left := bounds.Right;
|
---|
454 | Bounds.Right := temp;
|
---|
455 | end;
|
---|
456 | if Bounds.Bottom < Bounds.Top then
|
---|
457 | begin
|
---|
458 | temp := Bounds.Bottom;
|
---|
459 | bounds.Bottom := bounds.Top;
|
---|
460 | Bounds.Top := temp;
|
---|
461 | end;
|
---|
462 | map := CreateVerticalConePreciseMap(Bounds.Right-Bounds.Left,Bounds.Bottom-Bounds.Top);
|
---|
463 | Draw(dest,map,Altitude,bounds.Left,bounds.Top,Color);
|
---|
464 | map.Free;
|
---|
465 | end;
|
---|
466 |
|
---|
467 | procedure TPhongShading.DrawHorizontalCylinder(dest: TBGRACustomBitmap;
|
---|
468 | bounds: TRect; Altitude: Integer; Color: TBGRAPixel);
|
---|
469 | var map: TBGRABitmap;
|
---|
470 | temp: integer;
|
---|
471 | begin
|
---|
472 | if Bounds.Right < Bounds.Left then
|
---|
473 | begin
|
---|
474 | temp := Bounds.Left;
|
---|
475 | bounds.Left := bounds.Right;
|
---|
476 | Bounds.Right := temp;
|
---|
477 | end;
|
---|
478 | if Bounds.Bottom < Bounds.Top then
|
---|
479 | begin
|
---|
480 | temp := Bounds.Bottom;
|
---|
481 | bounds.Bottom := bounds.Top;
|
---|
482 | Bounds.Top := temp;
|
---|
483 | end;
|
---|
484 | map := CreateHorizontalCylinderPreciseMap(Bounds.Right-Bounds.Left,Bounds.Bottom-Bounds.Top);
|
---|
485 | Draw(dest,map,Altitude,bounds.Left,bounds.Top,Color);
|
---|
486 | map.Free;
|
---|
487 | end;
|
---|
488 |
|
---|
489 | procedure TPhongShading.DrawVerticalCylinder(dest: TBGRACustomBitmap;
|
---|
490 | bounds: TRect; Altitude: Integer; Color: TBGRAPixel);
|
---|
491 | var map: TBGRABitmap;
|
---|
492 | temp: integer;
|
---|
493 | begin
|
---|
494 | if Bounds.Right < Bounds.Left then
|
---|
495 | begin
|
---|
496 | temp := Bounds.Left;
|
---|
497 | bounds.Left := bounds.Right;
|
---|
498 | Bounds.Right := temp;
|
---|
499 | end;
|
---|
500 | if Bounds.Bottom < Bounds.Top then
|
---|
501 | begin
|
---|
502 | temp := Bounds.Bottom;
|
---|
503 | bounds.Bottom := bounds.Top;
|
---|
504 | Bounds.Top := temp;
|
---|
505 | end;
|
---|
506 | map := CreateVerticalCylinderPreciseMap(Bounds.Right-Bounds.Left,Bounds.Bottom-Bounds.Top);
|
---|
507 | Draw(dest,map,Altitude,bounds.Left,bounds.Top,Color);
|
---|
508 | map.Free;
|
---|
509 | end;
|
---|
510 |
|
---|
511 | procedure TPhongShading.DrawSphere(dest: TBGRACustomBitmap; bounds: TRect;
|
---|
512 | Altitude: Integer; Color: TBGRAPixel);
|
---|
513 | var map: TBGRABitmap;
|
---|
514 | temp: integer;
|
---|
515 | begin
|
---|
516 | if Bounds.Right < Bounds.Left then
|
---|
517 | begin
|
---|
518 | temp := Bounds.Left;
|
---|
519 | bounds.Left := bounds.Right;
|
---|
520 | Bounds.Right := temp;
|
---|
521 | end;
|
---|
522 | if Bounds.Bottom < Bounds.Top then
|
---|
523 | begin
|
---|
524 | temp := Bounds.Bottom;
|
---|
525 | bounds.Bottom := bounds.Top;
|
---|
526 | Bounds.Top := temp;
|
---|
527 | end;
|
---|
528 | map := CreateSpherePreciseMap(Bounds.Right-Bounds.Left,Bounds.Bottom-Bounds.Top);
|
---|
529 | Draw(dest,map,Altitude,bounds.Left,bounds.Top,Color);
|
---|
530 | map.Free;
|
---|
531 | end;
|
---|
532 |
|
---|
533 | procedure TPhongShading.DrawRectangle(dest: TBGRACustomBitmap; bounds: TRect;
|
---|
534 | Border,Altitude: Integer; Color: TBGRAPixel; RoundCorners: Boolean; Options: TRectangleMapOptions);
|
---|
535 | var map: TBGRABitmap;
|
---|
536 | temp: integer;
|
---|
537 | begin
|
---|
538 | if Bounds.Right < Bounds.Left then
|
---|
539 | begin
|
---|
540 | temp := Bounds.Left;
|
---|
541 | bounds.Left := bounds.Right;
|
---|
542 | Bounds.Right := temp;
|
---|
543 | end;
|
---|
544 | if Bounds.Bottom < Bounds.Top then
|
---|
545 | begin
|
---|
546 | temp := Bounds.Bottom;
|
---|
547 | bounds.Bottom := bounds.Top;
|
---|
548 | Bounds.Top := temp;
|
---|
549 | end;
|
---|
550 | if border > 10 then
|
---|
551 | begin
|
---|
552 | if RoundCorners then
|
---|
553 | map := CreateRoundRectanglePreciseMap(Bounds.Right-Bounds.Left,Bounds.Bottom-Bounds.Top,Border,Options)
|
---|
554 | else
|
---|
555 | map := CreateRectanglePreciseMap(Bounds.Right-Bounds.Left,Bounds.Bottom-Bounds.Top,Border,Options);
|
---|
556 | end else
|
---|
557 | begin
|
---|
558 | if RoundCorners then
|
---|
559 | map := CreateRoundRectangleMap(Bounds.Right-Bounds.Left,Bounds.Bottom-Bounds.Top,Border,Options)
|
---|
560 | else
|
---|
561 | map := CreateRectangleMap(Bounds.Right-Bounds.Left,Bounds.Bottom-Bounds.Top,Border,Options);
|
---|
562 | end;
|
---|
563 | Draw(dest,map,Altitude,bounds.Left,bounds.Top,Color);
|
---|
564 | map.Free;
|
---|
565 | end;
|
---|
566 |
|
---|
567 | procedure TPhongShading.DrawMapNormal(dest: TBGRACustomBitmap; map: TBGRACustomBitmap;
|
---|
568 | mapAltitude: integer; ofsX, ofsY: integer; ColorMap: TBGRACustomBitmap);
|
---|
569 | {$I phongdraw.inc }
|
---|
570 |
|
---|
571 | procedure TPhongShading.DrawColorNormal(dest: TBGRACustomBitmap; map: TBGRACustomBitmap;
|
---|
572 | mapAltitude: integer; ofsX, ofsY: integer; Color: TBGRAPixel);
|
---|
573 | {$define PARAM_SIMPLECOLOR}
|
---|
574 | {$I phongdraw.inc }
|
---|
575 |
|
---|
576 | procedure TPhongShading.DrawScannerNormal(dest: TBGRACustomBitmap;
|
---|
577 | map: TBGRACustomBitmap; mapAltitude: integer; ofsX, ofsY: integer;
|
---|
578 | ColorScan: IBGRAScanner);
|
---|
579 | {$define PARAM_SCANNER}
|
---|
580 | {$I phongdraw.inc }
|
---|
581 |
|
---|
582 | {$ifdef BGRASSE_AVAILABLE}
|
---|
583 | procedure TPhongShading.DrawMapSSE(dest: TBGRACustomBitmap; map: TBGRACustomBitmap;
|
---|
584 | mapAltitude: integer; ofsX, ofsY: integer; ColorMap: TBGRACustomBitmap);
|
---|
585 | {$define PARAM_PHONGSSE}
|
---|
586 | {$I phongdraw.inc }
|
---|
587 |
|
---|
588 | procedure TPhongShading.DrawColorSSE(dest: TBGRACustomBitmap; map: TBGRACustomBitmap;
|
---|
589 | mapAltitude: integer; ofsX, ofsY: integer; Color: TBGRAPixel);
|
---|
590 | {$define PARAM_PHONGSSE}
|
---|
591 | {$define PARAM_SIMPLECOLOR}
|
---|
592 | {$I phongdraw.inc }
|
---|
593 |
|
---|
594 | procedure TPhongShading.DrawScannerSSE(dest: TBGRACustomBitmap;
|
---|
595 | map: TBGRACustomBitmap; mapAltitude: integer; ofsX, ofsY: integer;
|
---|
596 | ColorScan: IBGRAScanner);
|
---|
597 | {$define PARAM_PHONGSSE}
|
---|
598 | {$define PARAM_SCANNER}
|
---|
599 | {$I phongdraw.inc }
|
---|
600 |
|
---|
601 | {$endif}
|
---|
602 |
|
---|
603 | {************************ maps ***********************************}
|
---|
604 |
|
---|
605 | function CreateConeMap(size: integer): TBGRABitmap;
|
---|
606 | var cx,cy,r: single;
|
---|
607 | mask: TBGRABitmap;
|
---|
608 | begin
|
---|
609 | cx := (size-1)/2;
|
---|
610 | cy := (size-1)/2;
|
---|
611 | r := (size-1)/2;
|
---|
612 | result := TBGRABitmap.Create(size,size);
|
---|
613 | result.GradientFill(0,0,size,size,BGRAWhite,BGRABlack,gtRadial,PointF(cx,cy),PointF(cx+r,cy),dmSet,False);
|
---|
614 |
|
---|
615 | mask := TBGRABitmap.Create(size,size,BGRABlack);
|
---|
616 | mask.FillEllipseAntialias(cx,cy,r,r,BGRAWhite);
|
---|
617 | result.ApplyMask(mask);
|
---|
618 | mask.Free;
|
---|
619 | end;
|
---|
620 |
|
---|
621 | function CreateConePreciseMap(width,height: integer): TBGRABitmap;
|
---|
622 | var cx,cy,rx,ry,d: single;
|
---|
623 | xb,yb: integer;
|
---|
624 | p: PBGRAPixel;
|
---|
625 | mask: TBGRABitmap;
|
---|
626 | begin
|
---|
627 | result := TBGRABitmap.Create(width,height);
|
---|
628 | cx := (width-1)/2;
|
---|
629 | cy := (height-1)/2;
|
---|
630 | rx := (width-1)/2;
|
---|
631 | ry := (height-1)/2;
|
---|
632 | for yb := 0 to height-1 do
|
---|
633 | begin
|
---|
634 | p := result.scanline[yb];
|
---|
635 | for xb := 0 to width-1 do
|
---|
636 | begin
|
---|
637 | d := sqr((xb-cx)/(rx+1))+sqr((yb-cy)/(ry+1));
|
---|
638 | if d >= 1 then
|
---|
639 | p^ := BGRAPixelTransparent else
|
---|
640 | p^ := MapHeightToBGRA(1-sqrt(d),255);
|
---|
641 | inc(p);
|
---|
642 | end;
|
---|
643 | end;
|
---|
644 | //antialiased border
|
---|
645 | mask := TBGRABitmap.Create(width,height,BGRABlack);
|
---|
646 | mask.FillEllipseAntialias(cx,cy,rx,ry,BGRAWhite);
|
---|
647 | result.ApplyMask(mask);
|
---|
648 | mask.Free;
|
---|
649 | end;
|
---|
650 |
|
---|
651 | function CreateVerticalConePreciseMap(width, height: integer): TBGRABitmap;
|
---|
652 | var cx,rx,d,vpos: single;
|
---|
653 | xb,yb: integer;
|
---|
654 | p: PBGRAPixel;
|
---|
655 | mask: TBGRABitmap;
|
---|
656 | begin
|
---|
657 | result := TBGRABitmap.Create(width,height);
|
---|
658 | if (height=0) or (width=0) then exit;
|
---|
659 | cx := (width-1)/2;
|
---|
660 | for yb := 0 to height-1 do
|
---|
661 | begin
|
---|
662 | p := result.scanline[yb];
|
---|
663 | vpos := (yb+1)/height;
|
---|
664 | rx := width/2*vpos;
|
---|
665 | for xb := 0 to width-1 do
|
---|
666 | begin
|
---|
667 | d := sqr((xb-cx)/(rx+1));
|
---|
668 | if d >= 1 then
|
---|
669 | p^ := BGRAPixelTransparent else
|
---|
670 | p^ := MapHeightToBGRA(sqrt(1-d)*vpos,255);
|
---|
671 | inc(p);
|
---|
672 | end;
|
---|
673 | end;
|
---|
674 | //antialiased border
|
---|
675 | mask := TBGRABitmap.Create(width,height,BGRABlack);
|
---|
676 | mask.FillPolyAntialias([PointF(width/2,-0.5),PointF(0,height-0.5),PointF(width-0.5,height-0.5)],BGRAWhite);
|
---|
677 | result.ApplyMask(mask);
|
---|
678 | mask.Free;
|
---|
679 | end;
|
---|
680 |
|
---|
681 | function CreateVerticalCylinderPreciseMap(width, height: integer): TBGRABitmap;
|
---|
682 | var cx,rx,d: single;
|
---|
683 | xb: integer;
|
---|
684 | begin
|
---|
685 | result := TBGRABitmap.Create(width,height);
|
---|
686 | if (height=0) or (width=0) then exit;
|
---|
687 | rx := width/2;
|
---|
688 | cx := (width-1)/2;
|
---|
689 | for xb := 0 to width-1 do
|
---|
690 | begin
|
---|
691 | d := sqr((xb-cx)/(rx+1));
|
---|
692 | result.SetVertLine(xb,0,height-1,MapHeightToBGRA(sqrt(1-d),255));
|
---|
693 | end;
|
---|
694 | end;
|
---|
695 |
|
---|
696 | function CreateHorizontalCylinderPreciseMap(width, height: integer
|
---|
697 | ): TBGRABitmap;
|
---|
698 | var cy,ry,d: single;
|
---|
699 | xb,yb: integer;
|
---|
700 | p: PBGRAPixel;
|
---|
701 | c: TBGRAPixel;
|
---|
702 | begin
|
---|
703 | result := TBGRABitmap.Create(width,height);
|
---|
704 | if (height=0) or (width=0) then exit;
|
---|
705 | ry := height/2;
|
---|
706 | cy := (height-1)/2;
|
---|
707 | for yb := 0 to height-1 do
|
---|
708 | begin
|
---|
709 | p := result.scanline[yb];
|
---|
710 | d := sqr((yb-cy)/(ry+1));
|
---|
711 | c := MapHeightToBGRA(sqrt(1-d),255);
|
---|
712 | for xb := 0 to width-1 do
|
---|
713 | begin
|
---|
714 | p^ := c;
|
---|
715 | inc(p);
|
---|
716 | end;
|
---|
717 | end;
|
---|
718 | end;
|
---|
719 |
|
---|
720 | function CreateSphereMap(width,height: integer): TBGRABitmap;
|
---|
721 | var cx,cy,rx,ry,d: single;
|
---|
722 | xb,yb: integer;
|
---|
723 | p: PBGRAPixel;
|
---|
724 | h: integer;
|
---|
725 | mask: TBGRABitmap;
|
---|
726 | begin
|
---|
727 | result := TBGRABitmap.Create(width,height);
|
---|
728 | cx := (width-1)/2;
|
---|
729 | cy := (height-1)/2;
|
---|
730 | rx := (width-1)/2;
|
---|
731 | ry := (height-1)/2;
|
---|
732 | for yb := 0 to height-1 do
|
---|
733 | begin
|
---|
734 | p := result.scanline[yb];
|
---|
735 | for xb := 0 to width-1 do
|
---|
736 | begin
|
---|
737 | d := sqr((xb-cx)/(rx+1))+sqr((yb-cy)/(ry+1));
|
---|
738 | if d >= 1 then
|
---|
739 | p^ := BGRAPixelTransparent else
|
---|
740 | begin
|
---|
741 | h := round(sqrt(1-d)*255);
|
---|
742 | p^.red := h;
|
---|
743 | p^.green := h;
|
---|
744 | p^.blue := h;
|
---|
745 | p^.alpha := 255;
|
---|
746 | end;
|
---|
747 | inc(p);
|
---|
748 | end;
|
---|
749 | end;
|
---|
750 | //antialiased border
|
---|
751 | mask := TBGRABitmap.Create(width,height,BGRABlack);
|
---|
752 | mask.FillEllipseAntialias(cx,cy,rx,ry,BGRAWhite);
|
---|
753 | result.ApplyMask(mask);
|
---|
754 | mask.Free;
|
---|
755 | end;
|
---|
756 |
|
---|
757 | procedure MapBorderLimit(width,height: integer; options: TRectangleMapOptions; var border: integer);
|
---|
758 | var maxHoriz,maxVert: integer;
|
---|
759 | begin
|
---|
760 | if [rmoNoLeftBorder,rmoNoRightBorder] <= options then maxHoriz := border else
|
---|
761 | if [rmoNoLeftBorder,rmoNoRightBorder] * options = [] then maxHoriz := width div 2 else
|
---|
762 | maxHoriz := width;
|
---|
763 | if border > maxHoriz then border := maxHoriz;
|
---|
764 |
|
---|
765 | if [rmoNoTopBorder,rmoNoBottomBorder] <= options then maxVert := border else
|
---|
766 | if [rmoNoTopBorder,rmoNoBottomBorder] * options = [] then maxVert := height div 2 else
|
---|
767 | maxVert := height;
|
---|
768 | if border > maxVert then border := maxVert;
|
---|
769 | end;
|
---|
770 |
|
---|
771 | procedure MapBorderLimit(width,height: integer; options: TRectangleMapOptions; var borderHoriz,borderVert: integer);
|
---|
772 | var maxHoriz,maxVert: integer;
|
---|
773 | begin
|
---|
774 | if [rmoNoLeftBorder,rmoNoRightBorder] <= options then maxHoriz := borderHoriz else
|
---|
775 | if [rmoNoLeftBorder,rmoNoRightBorder] * options = [] then maxHoriz := width div 2 else
|
---|
776 | maxHoriz := width;
|
---|
777 | if borderHoriz > maxHoriz then borderHoriz := maxHoriz;
|
---|
778 |
|
---|
779 | if [rmoNoTopBorder,rmoNoBottomBorder] <= options then maxVert := borderVert else
|
---|
780 | if [rmoNoTopBorder,rmoNoBottomBorder] * options = [] then maxVert := height div 2 else
|
---|
781 | maxVert := height;
|
---|
782 | if borderVert > maxVert then borderVert := maxVert;
|
---|
783 | end;
|
---|
784 |
|
---|
785 | function CreateSpherePreciseMap(width, height: integer): TBGRABitmap;
|
---|
786 | var cx,cy,rx,ry,d: single;
|
---|
787 | xb,yb: integer;
|
---|
788 | p: PBGRAPixel;
|
---|
789 | mask: TBGRABitmap;
|
---|
790 | begin
|
---|
791 | result := TBGRABitmap.Create(width,height);
|
---|
792 | cx := (width-1)/2;
|
---|
793 | cy := (height-1)/2;
|
---|
794 | rx := (width-1)/2;
|
---|
795 | ry := (height-1)/2;
|
---|
796 | for yb := 0 to height-1 do
|
---|
797 | begin
|
---|
798 | p := result.scanline[yb];
|
---|
799 | for xb := 0 to width-1 do
|
---|
800 | begin
|
---|
801 | d := sqr((xb-cx)/(rx+1))+sqr((yb-cy)/(ry+1));
|
---|
802 | if d >= 1 then
|
---|
803 | p^ := BGRAPixelTransparent else
|
---|
804 | p^ := MapHeightToBGRA(sqrt(1-d),255);
|
---|
805 | inc(p);
|
---|
806 | end;
|
---|
807 | end;
|
---|
808 | //antialiased border
|
---|
809 | mask := TBGRABitmap.Create(width,height,BGRABlack);
|
---|
810 | mask.FillEllipseAntialias(cx,cy,rx,ry,BGRAWhite);
|
---|
811 | result.ApplyMask(mask);
|
---|
812 | mask.Free;
|
---|
813 | end;
|
---|
814 |
|
---|
815 | procedure RectangleMapRemoveCorners(dest: TBGRABitmap; options: TRectangleMapOptions);
|
---|
816 | begin
|
---|
817 | if [rmoNoLeftBorder,rmoNoTopBorder]*Options = [] then
|
---|
818 | begin
|
---|
819 | dest.SetPixel(0,0,BGRAPixelTransparent);
|
---|
820 | dest.ErasePixel(1,0,128);
|
---|
821 | dest.ErasePixel(0,1,128);
|
---|
822 | end;
|
---|
823 |
|
---|
824 | if [rmoNoRightBorder,rmoNoTopBorder]*Options = [] then
|
---|
825 | begin
|
---|
826 | dest.SetPixel(dest.width-1,0,BGRAPixelTransparent);
|
---|
827 | dest.ErasePixel(dest.width-2,0,128);
|
---|
828 | dest.ErasePixel(dest.width-1,1,128);
|
---|
829 | end;
|
---|
830 |
|
---|
831 | if [rmoNoRightBorder,rmoNoBottomBorder]*Options = [] then
|
---|
832 | begin
|
---|
833 | dest.SetPixel(dest.width-1,dest.height-1,BGRAPixelTransparent);
|
---|
834 | dest.ErasePixel(dest.width-2,dest.height-1,128);
|
---|
835 | dest.ErasePixel(dest.width-1,dest.height-2,128);
|
---|
836 | end;
|
---|
837 |
|
---|
838 | if [rmoNoLeftBorder,rmoNoBottomBorder]*Options = [] then
|
---|
839 | begin
|
---|
840 | dest.SetPixel(0,dest.height-1,BGRAPixelTransparent);
|
---|
841 | dest.ErasePixel(1,dest.height-1,128);
|
---|
842 | dest.ErasePixel(0,dest.height-2,128);
|
---|
843 | end;
|
---|
844 | end;
|
---|
845 |
|
---|
846 | function CreateRectangleMap(width,height,border: integer; options: TRectangleMapOptions = []): TBGRABitmap;
|
---|
847 | var xb,yb: integer;
|
---|
848 | p: PBGRAPixel;
|
---|
849 | h: integer;
|
---|
850 | begin
|
---|
851 | MapBorderLimit(width,height,options,border);
|
---|
852 |
|
---|
853 | result := TBGRABitmap.Create(width,height);
|
---|
854 | for yb := 0 to height-1 do
|
---|
855 | begin
|
---|
856 | p := result.scanline[yb];
|
---|
857 | for xb := 0 to width-1 do
|
---|
858 | begin
|
---|
859 | if not (rmoNoLeftBorder in options) and (xb < border) and (yb > xb) and (yb < height-1-xb) then h := xb else
|
---|
860 | if not (rmoNoRightBorder in options) and (xb > width-1-border) and (yb > width-1-xb) and (yb < height-1-(width-1-xb)) then h := width-1-xb else
|
---|
861 | if not (rmoNoTopBorder in options) and (yb < border) and (xb > yb) and (xb < width-1-yb) then h := yb else
|
---|
862 | if not (rmoNoBottomBorder in options) and (yb > height-1-border) and (xb > height-1-yb) and (xb < width-1-(height-1-yb)) then h := height-1-yb else
|
---|
863 | if not (rmoNoLeftBorder in options) and (xb < border) then h := xb else
|
---|
864 | if not (rmoNoRightBorder in options) and (xb > width-1-border) then h := width-1-xb else
|
---|
865 | if not (rmoNoTopBorder in options) and (yb < border) then h := yb else
|
---|
866 | if not (rmoNoBottomBorder in options) and (yb > height-1-border) then h := height-1-yb else
|
---|
867 | begin
|
---|
868 | p^ := BGRAWhite;
|
---|
869 | inc(p);
|
---|
870 | Continue;
|
---|
871 | end;
|
---|
872 |
|
---|
873 | if rmoLinearBorder in options then h := h*256 div border else
|
---|
874 | h := round(sin((h+1/2)/border*Pi/2)*255);
|
---|
875 | p^.red := h;
|
---|
876 | p^.green := h;
|
---|
877 | p^.blue := h;
|
---|
878 | p^.alpha := 255;
|
---|
879 | inc(p);
|
---|
880 | end;
|
---|
881 | end;
|
---|
882 |
|
---|
883 | RectangleMapRemoveCorners(result,options);
|
---|
884 | end;
|
---|
885 |
|
---|
886 | function CreateRectanglePreciseMap(width, height, border: integer;
|
---|
887 | options: TRectangleMapOptions): TBGRABitmap;
|
---|
888 | var xb,yb: integer;
|
---|
889 | p: PBGRAPixel;
|
---|
890 | h: single;
|
---|
891 | begin
|
---|
892 | MapBorderLimit(width,height,options,border);
|
---|
893 |
|
---|
894 | result := TBGRABitmap.Create(width,height);
|
---|
895 | for yb := 0 to height-1 do
|
---|
896 | begin
|
---|
897 | p := result.scanline[yb];
|
---|
898 | for xb := 0 to width-1 do
|
---|
899 | begin
|
---|
900 | if not (rmoNoLeftBorder in options) and (xb < border) and (yb > xb) and (yb < height-1-xb) then h := xb else
|
---|
901 | if not (rmoNoRightBorder in options) and (xb > width-1-border) and (yb > width-1-xb) and (yb < height-1-(width-1-xb)) then h := width-1-xb else
|
---|
902 | if not (rmoNoTopBorder in options) and (yb < border) and (xb > yb) and (xb < width-1-yb) then h := yb else
|
---|
903 | if not (rmoNoBottomBorder in options) and (yb > height-1-border) and (xb > height-1-yb) and (xb < width-1-(height-1-yb)) then h := height-1-yb else
|
---|
904 | if not (rmoNoLeftBorder in options) and (xb < border) then h := xb else
|
---|
905 | if not (rmoNoRightBorder in options) and (xb > width-1-border) then h := width-1-xb else
|
---|
906 | if not (rmoNoTopBorder in options) and (yb < border) then h := yb else
|
---|
907 | if not (rmoNoBottomBorder in options) and (yb > height-1-border) then h := height-1-yb else
|
---|
908 | begin
|
---|
909 | p^ := BGRAWhite;
|
---|
910 | inc(p);
|
---|
911 | Continue;
|
---|
912 | end;
|
---|
913 |
|
---|
914 | if rmoLinearBorder in options then h := h/border else
|
---|
915 | h := sin((h+1/2)/border*Pi/2);
|
---|
916 |
|
---|
917 | p^ := MapHeightToBGRA(h,255);
|
---|
918 |
|
---|
919 | inc(p);
|
---|
920 | end;
|
---|
921 | end;
|
---|
922 |
|
---|
923 | RectangleMapRemoveCorners(result,options);
|
---|
924 | end;
|
---|
925 |
|
---|
926 | function CreateRectanglePreciseMap(width, height, borderWidth, borderHeight: integer;
|
---|
927 | options: TRectangleMapOptions): TBGRABitmap;
|
---|
928 | var xb,yb, minBorder: integer;
|
---|
929 | p: PBGRAPixel;
|
---|
930 | h: single;
|
---|
931 | smallStep: single;
|
---|
932 | begin
|
---|
933 | MapBorderLimit(width,height,options,borderWidth,borderHeight);
|
---|
934 |
|
---|
935 | minBorder := min(borderWidth,borderHeight);
|
---|
936 | if minBorder > 0 then smallStep := 1/minBorder else smallStep:= 0;
|
---|
937 |
|
---|
938 | result := TBGRABitmap.Create(width,height);
|
---|
939 | for yb := 0 to height-1 do
|
---|
940 | begin
|
---|
941 | p := result.scanline[yb];
|
---|
942 | for xb := 0 to width-1 do
|
---|
943 | begin
|
---|
944 | if not (rmoNoLeftBorder in options) and (xb < borderWidth) and (yb < borderHeight) then
|
---|
945 | h := min(xb/borderWidth, yb/borderHeight) else
|
---|
946 | if not (rmoNoRightBorder in options) and (xb > width-1-borderWidth) and (yb < borderHeight) then
|
---|
947 | h := min((width-1-xb)/borderWidth, yb/borderHeight) else
|
---|
948 | if not (rmoNoTopBorder in options) and (xb < borderWidth) and (yb > height-1-borderHeight) then
|
---|
949 | h := min(xb/borderWidth, (height-1-yb)/borderHeight) else
|
---|
950 | if not (rmoNoBottomBorder in options) and (xb > width-1-borderWidth) and (yb > height-1-borderHeight) then
|
---|
951 | h := min((width-1-xb)/borderWidth, (height-1-yb)/borderHeight) else
|
---|
952 | if not (rmoNoLeftBorder in options) and (xb < borderWidth) then h := xb/borderWidth else
|
---|
953 | if not (rmoNoRightBorder in options) and (xb > width-1-borderWidth) then h := (width-1-xb)/borderWidth else
|
---|
954 | if not (rmoNoTopBorder in options) and (yb < borderHeight) then h := yb/borderHeight else
|
---|
955 | if not (rmoNoBottomBorder in options) and (yb > height-1-borderHeight) then h := (height-1-yb)/borderHeight else
|
---|
956 | begin
|
---|
957 | p^ := BGRAWhite;
|
---|
958 | inc(p);
|
---|
959 | Continue;
|
---|
960 | end;
|
---|
961 |
|
---|
962 | if not (rmoLinearBorder in options) then
|
---|
963 | h := sin((h+smallStep*0.5)*Pi*0.5);
|
---|
964 |
|
---|
965 | p^ := MapHeightToBGRA(h,255);
|
---|
966 |
|
---|
967 | inc(p);
|
---|
968 | end;
|
---|
969 | end;
|
---|
970 |
|
---|
971 | RectangleMapRemoveCorners(result,options);
|
---|
972 | end;
|
---|
973 |
|
---|
974 | function CreateRoundRectangleMap(width,height,border: integer; options: TRectangleMapOptions = []): TBGRABitmap;
|
---|
975 | var d: single;
|
---|
976 | xb,yb: integer;
|
---|
977 | p: PBGRAPixel;
|
---|
978 | h: integer;
|
---|
979 | begin
|
---|
980 | MapBorderLimit(width,height,options,border);
|
---|
981 |
|
---|
982 | result := TBGRABitmap.Create(width,height);
|
---|
983 | for yb := 0 to height-1 do
|
---|
984 | begin
|
---|
985 | p := result.scanline[yb];
|
---|
986 | for xb := 0 to width-1 do
|
---|
987 | begin
|
---|
988 | if not (rmoNoLeftBorder in options) and not (rmoNoTopBorder in options) and (xb < border) and (yb < border) then d := border-sqrt(sqr(border-xb)+sqr(border-yb)) else
|
---|
989 | if not (rmoNoLeftBorder in options) and not (rmoNoBottomBorder in options) and (xb < border) and (yb > height-1-border) then d := border-sqrt(sqr(border-xb)+sqr(border-(height-1-yb))) else
|
---|
990 | if not (rmoNoRightBorder in options) and not (rmoNoTopBorder in options) and (xb > width-1-border) and (yb < border) then d := border-sqrt(sqr(border-(width-1-xb))+sqr(border-yb)) else
|
---|
991 | if not (rmoNoRightBorder in options) and not (rmoNoBottomBorder in options) and (xb > width-1-border) and (yb > height-1-border) then d := border-sqrt(sqr(border-(width-1-xb))+sqr(border-(height-1-yb))) else
|
---|
992 | if not (rmoNoLeftBorder in options) and (xb < border) then d := xb else
|
---|
993 | if not (rmoNoRightBorder in options) and (xb > width-1-border) then d := width-1-xb else
|
---|
994 | if not (rmoNoTopBorder in options) and (yb < border) then d := yb else
|
---|
995 | if not (rmoNoBottomBorder in options) and (yb > height-1-border) then d := height-1-yb else
|
---|
996 | begin
|
---|
997 | p^ := BGRAWhite;
|
---|
998 | inc(p);
|
---|
999 | Continue;
|
---|
1000 | end;
|
---|
1001 |
|
---|
1002 | d := (d+1)*border/(border+1);
|
---|
1003 |
|
---|
1004 | if d < 0 then
|
---|
1005 | p^ := BGRAPixelTransparent else
|
---|
1006 | begin
|
---|
1007 | if rmoLinearBorder in options then h := trunc(d*256/border) else
|
---|
1008 | h := round(sin((d+1/2)/border*Pi/2)*255);
|
---|
1009 |
|
---|
1010 | p^.red := h;
|
---|
1011 | p^.green := h;
|
---|
1012 | p^.blue := h;
|
---|
1013 | if d < 1 then p^.alpha := round(d*255) else
|
---|
1014 | p^.alpha := 255;
|
---|
1015 | end;
|
---|
1016 | inc(p);
|
---|
1017 | end;
|
---|
1018 | end;
|
---|
1019 | end;
|
---|
1020 |
|
---|
1021 | function CreatePerlinNoiseMap(AWidth, AHeight: integer; HorizontalPeriod: Single;
|
---|
1022 | VerticalPeriod: Single; Exponent: Double = 1; ResampleFilter: TResampleFilter = rfCosine): TBGRABitmap;
|
---|
1023 |
|
---|
1024 | procedure AddNoise(frequencyH, frequencyV: integer; amplitude: byte; dest: TBGRABitmap);
|
---|
1025 | var small,resampled: TBGRABitmap;
|
---|
1026 | p: PBGRAPixel;
|
---|
1027 | i: Integer;
|
---|
1028 | begin
|
---|
1029 | if (frequencyH = 0) or (frequencyV = 0) then exit;
|
---|
1030 | small := TBGRABitmap.Create(frequencyH,frequencyV);
|
---|
1031 | p := small.data;
|
---|
1032 | for i := 0 to small.NbPixels-1 do
|
---|
1033 | begin
|
---|
1034 | p^.red := random(amplitude);
|
---|
1035 | p^.green := p^.red;
|
---|
1036 | p^.blue := p^.green;
|
---|
1037 | p^.alpha := 255;
|
---|
1038 | inc(p);
|
---|
1039 | end;
|
---|
1040 | small.ResampleFilter := ResampleFilter;
|
---|
1041 | resampled := small.Resample(dest.Width,dest.Height) as TBGRABitmap;
|
---|
1042 | dest.BlendImage(0,0,resampled,boAdditive);
|
---|
1043 | resampled.Free;
|
---|
1044 | small.Free;
|
---|
1045 | end;
|
---|
1046 |
|
---|
1047 | var
|
---|
1048 | i: Integer;
|
---|
1049 | temp: TBGRABitmap;
|
---|
1050 |
|
---|
1051 | begin
|
---|
1052 | result := TBGRABitmap.Create(AWidth,AHeight);
|
---|
1053 | for i := 0 to 5 do
|
---|
1054 | AddNoise(round(AWidth / HorizontalPeriod / (32 shr i)),round(AHeight / VerticalPeriod / (32 shr i)), round(exp(ln((128 shr i)/128)*Exponent)*128),result);
|
---|
1055 |
|
---|
1056 | temp := result.FilterNormalize(False) as TBGRABitmap;
|
---|
1057 | result.Free;
|
---|
1058 | result := temp;
|
---|
1059 |
|
---|
1060 | temp := result.FilterBlurRadial(1,rbNormal) as TBGRABitmap;
|
---|
1061 | result.Free;
|
---|
1062 | result := temp;
|
---|
1063 | end;
|
---|
1064 |
|
---|
1065 | function CreateCyclicPerlinNoiseMap(AWidth, AHeight: integer; HorizontalPeriod: Single = 1;
|
---|
1066 | VerticalPeriod: Single = 1; Exponent: Double = 1; ResampleFilter: TResampleFilter = rfCosine): TBGRABitmap;
|
---|
1067 |
|
---|
1068 | procedure AddNoise(frequencyH, frequencyV: integer; amplitude: byte; dest: TBGRABitmap);
|
---|
1069 | var small,cycled,resampled: TBGRABitmap;
|
---|
1070 | p: PBGRAPixel;
|
---|
1071 | i: Integer;
|
---|
1072 | begin
|
---|
1073 | if (frequencyH = 0) or (frequencyV = 0) then exit;
|
---|
1074 | small := TBGRABitmap.Create(frequencyH,frequencyV);
|
---|
1075 | p := small.data;
|
---|
1076 | for i := 0 to small.NbPixels-1 do
|
---|
1077 | begin
|
---|
1078 | p^.red := random(amplitude);
|
---|
1079 | p^.green := p^.red;
|
---|
1080 | p^.blue := p^.green;
|
---|
1081 | p^.alpha := 255;
|
---|
1082 | inc(p);
|
---|
1083 | end;
|
---|
1084 | cycled := small.GetPart(rect(-2,-2,small.Width+2,small.Height+2)) as TBGRABitmap;
|
---|
1085 | cycled.ResampleFilter := ResampleFilter;
|
---|
1086 | resampled := cycled.Resample(round((cycled.Width-1)*(dest.Width/frequencyH)),round((cycled.Height-1)*(dest.Height/frequencyV))) as TBGRABitmap;
|
---|
1087 | dest.BlendImage(round(-2*(dest.Width/frequencyH)),round(-2*(dest.Height/frequencyV)),resampled,boAdditive);
|
---|
1088 | resampled.Free;
|
---|
1089 | cycled.Free;
|
---|
1090 | small.Free;
|
---|
1091 | end;
|
---|
1092 |
|
---|
1093 | var
|
---|
1094 | i: Integer;
|
---|
1095 | temp: TBGRABitmap;
|
---|
1096 |
|
---|
1097 | begin
|
---|
1098 | result := TBGRABitmap.Create(AWidth,AHeight);
|
---|
1099 | for i := 0 to 5 do
|
---|
1100 | AddNoise(round(AWidth / HorizontalPeriod / (32 shr i)),round(AHeight / VerticalPeriod / (32 shr i)), round(exp(ln((128 shr i)/128)*Exponent)*128),result);
|
---|
1101 |
|
---|
1102 | temp := result.FilterNormalize(False) as TBGRABitmap;
|
---|
1103 | result.Free;
|
---|
1104 | result := temp;
|
---|
1105 |
|
---|
1106 | temp := result.FilterBlurRadial(1,rbNormal) as TBGRABitmap;
|
---|
1107 | result.Free;
|
---|
1108 | result := temp;
|
---|
1109 | end;
|
---|
1110 |
|
---|
1111 | function CreateRoundRectanglePreciseMap(width, height, border: integer;
|
---|
1112 | options: TRectangleMapOptions): TBGRABitmap;
|
---|
1113 | var d: single;
|
---|
1114 | xb,yb: integer;
|
---|
1115 | p: PBGRAPixel;
|
---|
1116 | h: single;
|
---|
1117 | begin
|
---|
1118 | MapBorderLimit(width,height,options,border);
|
---|
1119 |
|
---|
1120 | result := TBGRABitmap.Create(width,height);
|
---|
1121 | for yb := 0 to height-1 do
|
---|
1122 | begin
|
---|
1123 | p := result.scanline[yb];
|
---|
1124 | for xb := 0 to width-1 do
|
---|
1125 | begin
|
---|
1126 | if not (rmoNoLeftBorder in options) and not (rmoNoTopBorder in options) and (xb < border) and (yb < border) then d := border-sqrt(sqr(border-xb)+sqr(border-yb)) else
|
---|
1127 | if not (rmoNoLeftBorder in options) and not (rmoNoBottomBorder in options) and (xb < border) and (yb > height-1-border) then d := border-sqrt(sqr(border-xb)+sqr(border-(height-1-yb))) else
|
---|
1128 | if not (rmoNoRightBorder in options) and not (rmoNoTopBorder in options) and (xb > width-1-border) and (yb < border) then d := border-sqrt(sqr(border-(width-1-xb))+sqr(border-yb)) else
|
---|
1129 | if not (rmoNoRightBorder in options) and not (rmoNoBottomBorder in options) and (xb > width-1-border) and (yb > height-1-border) then d := border-sqrt(sqr(border-(width-1-xb))+sqr(border-(height-1-yb))) else
|
---|
1130 | if not (rmoNoLeftBorder in options) and (xb < border) then d := xb else
|
---|
1131 | if not (rmoNoRightBorder in options) and (xb > width-1-border) then d := width-1-xb else
|
---|
1132 | if not (rmoNoTopBorder in options) and (yb < border) then d := yb else
|
---|
1133 | if not (rmoNoBottomBorder in options) and (yb > height-1-border) then d := height-1-yb else
|
---|
1134 | begin
|
---|
1135 | p^ := BGRAWhite;
|
---|
1136 | inc(p);
|
---|
1137 | Continue;
|
---|
1138 | end;
|
---|
1139 |
|
---|
1140 | d := (d+1)*border/(border+1);
|
---|
1141 |
|
---|
1142 | if d < 0 then
|
---|
1143 | p^ := BGRAPixelTransparent else
|
---|
1144 | begin
|
---|
1145 | if rmoLinearBorder in options then h := d/border else
|
---|
1146 | h := sin((d+1/2)/border*Pi/2);
|
---|
1147 |
|
---|
1148 | if d < 1 then p^:= MapHeightToBGRA(h,round(d*255)) else
|
---|
1149 | p^ := MapHeightToBGRA(h,255);
|
---|
1150 | end;
|
---|
1151 | inc(p);
|
---|
1152 | end;
|
---|
1153 | end;
|
---|
1154 | end;
|
---|
1155 |
|
---|
1156 | function CreateRoundRectanglePreciseMap(width, height, borderWidth,
|
---|
1157 | borderHeight: integer; options: TRectangleMapOptions): TBGRABitmap;
|
---|
1158 | var d: single;
|
---|
1159 | xb,yb: integer;
|
---|
1160 | p: PBGRAPixel;
|
---|
1161 | h,smallStep,factor: single;
|
---|
1162 | minBorder: integer;
|
---|
1163 | begin
|
---|
1164 | MapBorderLimit(width,height,options,borderWidth,borderHeight);
|
---|
1165 |
|
---|
1166 | minBorder := min(borderWidth,borderHeight);
|
---|
1167 | if minBorder > 0 then smallStep := 1/minBorder else smallStep:= 0;
|
---|
1168 | factor := minBorder/(minBorder+1);
|
---|
1169 | result := TBGRABitmap.Create(width,height);
|
---|
1170 | for yb := 0 to height-1 do
|
---|
1171 | begin
|
---|
1172 | p := result.scanline[yb];
|
---|
1173 | for xb := 0 to width-1 do
|
---|
1174 | begin
|
---|
1175 | if not (rmoNoLeftBorder in options) and not (rmoNoTopBorder in options) and (xb < borderWidth) and (yb < borderHeight) then
|
---|
1176 | d := 1-sqrt(sqr((borderWidth-xb)/borderWidth)+sqr((borderHeight-yb)/borderHeight)) else
|
---|
1177 | if not (rmoNoLeftBorder in options) and not (rmoNoBottomBorder in options) and (xb < borderWidth) and (yb > height-1-borderHeight) then
|
---|
1178 | d := 1-sqrt(sqr((borderWidth-xb)/borderWidth)+sqr((borderHeight-(height-1-yb))/borderHeight)) else
|
---|
1179 | if not (rmoNoRightBorder in options) and not (rmoNoTopBorder in options) and (xb > width-1-borderWidth) and (yb < borderHeight) then
|
---|
1180 | d := 1-sqrt(sqr((borderWidth-(width-1-xb))/borderWidth)+sqr((borderHeight-yb)/borderHeight)) else
|
---|
1181 | if not (rmoNoRightBorder in options) and not (rmoNoBottomBorder in options) and (xb > width-1-borderWidth) and (yb > height-1-borderHeight) then
|
---|
1182 | d := 1-sqrt(sqr((borderWidth-(width-1-xb))/borderWidth)+sqr((borderHeight-(height-1-yb))/borderHeight)) else
|
---|
1183 | if not (rmoNoLeftBorder in options) and (xb < borderWidth) then d := xb/borderWidth else
|
---|
1184 | if not (rmoNoRightBorder in options) and (xb > width-1-borderWidth) then d := (width-1-xb)/borderWidth else
|
---|
1185 | if not (rmoNoTopBorder in options) and (yb < borderHeight) then d := yb/borderHeight else
|
---|
1186 | if not (rmoNoBottomBorder in options) and (yb > height-1-borderHeight) then d := (height-1-yb)/borderHeight else
|
---|
1187 | begin
|
---|
1188 | p^ := BGRAWhite;
|
---|
1189 | inc(p);
|
---|
1190 | Continue;
|
---|
1191 | end;
|
---|
1192 |
|
---|
1193 | d := (d + smallStep)*factor;
|
---|
1194 |
|
---|
1195 | if d < 0 then
|
---|
1196 | p^ := BGRAPixelTransparent else
|
---|
1197 | begin
|
---|
1198 | if rmoLinearBorder in options then h := d else
|
---|
1199 | h := sin((d+smallStep*0.5)*Pi*0.5);
|
---|
1200 |
|
---|
1201 | if d < smallStep then p^:= MapHeightToBGRA(h,round(d/smallStep*255)) else
|
---|
1202 | p^ := MapHeightToBGRA(h,255);
|
---|
1203 | end;
|
---|
1204 | inc(p);
|
---|
1205 | end;
|
---|
1206 | end;
|
---|
1207 | end;
|
---|
1208 |
|
---|
1209 | initialization
|
---|
1210 |
|
---|
1211 | Randomize;
|
---|
1212 |
|
---|
1213 | end.
|
---|
1214 |
|
---|