source: trunk/Packages/Graphics32/GR32_Polygons.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 63.5 KB
Line 
1unit GR32_Polygons;
2
3(* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1 or LGPL 2.1 with linking exception
5 *
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
10 *
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
15 *
16 * Alternatively, the contents of this file may be used under the terms of the
17 * Free Pascal modified version of the GNU Lesser General Public License
18 * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
19 * of this license are applicable instead of those above.
20 * Please see the file LICENSE.txt for additional information concerning this
21 * license.
22 *
23 * The Original Code is Vectorial Polygon Rasterizer for Graphics32
24 *
25 * The Initial Developer of the Original Code is
26 * Mattias Andersson <mattias@centaurix.com>
27 *
28 * Portions created by the Initial Developer are Copyright (C) 2008-2012
29 * the Initial Developer. All Rights Reserved.
30 *
31 * Contributor(s):
32 *
33 * ***** END LICENSE BLOCK ***** *)
34
35interface
36
37{$I GR32.inc}
38
39uses
40 Types, GR32, GR32_Containers, GR32_VPR, GR32_Transforms, GR32_Resamplers;
41
42type
43 { Polygon join style - used by GR32_VectorUtils.Grow(). }
44 { nb: jsRoundEx rounds both convex and concave joins unlike jsRound which
45 only rounds convex joins. The depth of convex join rounding is controlled
46 by Grow's MiterLimit parameter }
47 TJoinStyle = (jsMiter, jsBevel, jsRound, jsRoundEx);
48
49 { Polygon end style }
50 TEndStyle = (esButt, esSquare, esRound);
51
52 { Polygon fill mode }
53 TPolyFillMode = (pfAlternate, pfWinding, pfEvenOdd = 0, pfNonZero);
54
55 { TCustomPolygonRenderer }
56 TCustomPolygonRenderer = class(TThreadPersistent)
57 public
58 procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint;
59 const ClipRect: TFloatRect; Transformation: TTransformation); overload; virtual;
60 procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint;
61 const ClipRect: TFloatRect); overload; virtual;
62 procedure PolygonFS(const Points: TArrayOfFloatPoint;
63 const ClipRect: TFloatRect; Transformation: TTransformation); overload; virtual;
64 procedure PolygonFS(const Points: TArrayOfFloatPoint;
65 const ClipRect: TFloatRect); overload; virtual;
66
67 // procedure PolyPolygonXS(const Points: TArrayOfArrayOfFixedPoint; const ClipRect: TFixedRect; Transformation: TTransformation); virtual; overload;
68 // procedure PolyPolygonXS(const Points: TArrayOfArrayOfFixedPoint; const ClipRect: TFixedRect); virtual; overload;
69 end;
70 TCustomPolygonRendererClass = class of TCustomPolygonRenderer;
71
72 TCustomPolygonFiller = class;
73
74 { TPolygonRenderer32 }
75 TPolygonRenderer32 = class(TCustomPolygonRenderer)
76 private
77 FBitmap: TBitmap32;
78 FFillMode: TPolyFillMode;
79 FColor: TColor32;
80 FFiller: TCustomPolygonFiller;
81 procedure SetColor(const Value: TColor32);
82 procedure SetFillMode(const Value: TPolyFillMode);
83 procedure SetFiller(const Value: TCustomPolygonFiller);
84 protected
85 procedure SetBitmap(const Value: TBitmap32); virtual;
86 public
87 constructor Create(Bitmap: TBitmap32; Fillmode: TPolyFillMode = pfWinding); reintroduce; overload;
88 procedure PolygonFS(const Points: TArrayOfFloatPoint); overload; virtual;
89 procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint); overload; virtual;
90
91 property Bitmap: TBitmap32 read FBitmap write SetBitmap;
92 property FillMode: TPolyFillMode read FFillMode write SetFillMode;
93 property Color: TColor32 read FColor write SetColor;
94 property Filler: TCustomPolygonFiller read FFiller write SetFiller;
95 end;
96 TPolygonRenderer32Class = class of TPolygonRenderer32;
97
98 { TPolygonRenderer32VPR }
99 { Polygon renderer based on VPR. Computes exact coverages for optimal anti-aliasing. }
100 TFillProc = procedure(Coverage: PSingleArray; AlphaValues: PColor32Array; Count: Integer; Color: TColor32);
101
102 TPolygonRenderer32VPR = class(TPolygonRenderer32)
103 private
104 FFillProc: TFillProc;
105 procedure UpdateFillProcs;
106 protected
107 procedure RenderSpan(const Span: TValueSpan; DstY: Integer); virtual;
108 procedure FillSpan(const Span: TValueSpan; DstY: Integer); virtual;
109 function GetRenderSpan: TRenderSpanEvent; virtual;
110 public
111 procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint;
112 const ClipRect: TFloatRect); override;
113 end;
114
115 { TPolygonRenderer32LCD }
116 TPolygonRenderer32LCD = class(TPolygonRenderer32VPR)
117 protected
118 procedure RenderSpan(const Span: TValueSpan; DstY: Integer); override;
119 public
120 procedure PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint;
121 const ClipRect: TFloatRect); override;
122 end;
123
124 { TPolygonRenderer32LCD2 }
125 TPolygonRenderer32LCD2 = class(TPolygonRenderer32LCD)
126 public
127 procedure RenderSpan(const Span: TValueSpan; DstY: Integer); override;
128 end;
129
130 { TCustomPolygonFiller }
131
132 TFillLineEvent = procedure(Dst: PColor32; DstX, DstY, Length: Integer;
133 AlphaValues: PColor32; CombineMode: TCombineMode) of object;
134
135 TCustomPolygonFiller = class
136 protected
137 function GetFillLine: TFillLineEvent; virtual; abstract;
138 public
139 procedure BeginRendering; virtual;
140 procedure EndRendering; virtual;
141
142 property FillLine: TFillLineEvent read GetFillLine;
143 end;
144
145 { TCallbackPolygonFiller }
146 TCallbackPolygonFiller = class(TCustomPolygonFiller)
147 private
148 FFillLineEvent: TFillLineEvent;
149 protected
150 function GetFillLine: TFillLineEvent; override;
151 public
152 property FillLineEvent: TFillLineEvent read FFillLineEvent write FFillLineEvent;
153 end;
154
155 { TInvertPolygonFiller }
156 TInvertPolygonFiller = class(TCustomPolygonFiller)
157 protected
158 function GetFillLine: TFillLineEvent; override;
159 procedure FillLineBlend(Dst: PColor32; DstX, DstY, Length: Integer;
160 AlphaValues: PColor32; CombineMode: TCombineMode);
161 end;
162
163 { TClearPolygonFiller }
164 TClearPolygonFiller = class(TCustomPolygonFiller)
165 private
166 FColor: TColor32;
167 protected
168 function GetFillLine: TFillLineEvent; override;
169 procedure FillLineClear(Dst: PColor32; DstX, DstY,
170 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
171 public
172 constructor Create(Color: TColor32 = $00808080); reintroduce; virtual;
173
174 property Color: TColor32 read FColor write FColor;
175 end;
176
177 { TBitmapPolygonFiller }
178 TBitmapPolygonFiller = class(TCustomPolygonFiller)
179 private
180 FPattern: TCustomBitmap32;
181 FOffsetY: Integer;
182 FOffsetX: Integer;
183 protected
184 function GetFillLine: TFillLineEvent; override;
185 procedure FillLineOpaque(Dst: PColor32; DstX, DstY,
186 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
187 procedure FillLineBlend(Dst: PColor32; DstX, DstY,
188 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
189 procedure FillLineBlendMasterAlpha(Dst: PColor32; DstX, DstY,
190 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
191 procedure FillLineCustomCombine(Dst: PColor32; DstX, DstY,
192 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
193 public
194 property Pattern: TCustomBitmap32 read FPattern write FPattern;
195 property OffsetX: Integer read FOffsetX write FOffsetX;
196 property OffsetY: Integer read FOffsetY write FOffsetY;
197 end;
198
199 { TSamplerFiller }
200 TSamplerFiller = class(TCustomPolygonFiller)
201 private
202 FSampler: TCustomSampler;
203 FGetSample: TGetSampleInt;
204 procedure SetSampler(const Value: TCustomSampler);
205 protected
206 procedure SamplerChanged; virtual;
207 function GetFillLine: TFillLineEvent; override;
208 procedure SampleLineOpaque(Dst: PColor32; DstX, DstY, Length: Integer;
209 AlphaValues: PColor32; CombineMode: TCombineMode);
210 public
211 constructor Create(Sampler: TCustomSampler = nil); reintroduce; virtual;
212 procedure BeginRendering; override;
213 procedure EndRendering; override;
214 property Sampler: TCustomSampler read FSampler write SetSampler;
215 end;
216
217procedure PolyPolygonFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
218 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
219 Transformation: TTransformation = nil); overload;
220procedure PolygonFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
221 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
222 Transformation: TTransformation = nil); overload;
223procedure PolyPolygonFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
224 Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
225 Transformation: TTransformation = nil); overload;
226procedure PolygonFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
227 Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
228 Transformation: TTransformation = nil); overload;
229procedure PolyPolygonFS_LCD(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
230 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
231 Transformation: TTransformation = nil); overload;
232procedure PolygonFS_LCD(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
233 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
234 Transformation: TTransformation = nil); overload;
235procedure PolyPolygonFS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
236 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
237 Transformation: TTransformation = nil); overload;
238procedure PolygonFS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
239 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
240 Transformation: TTransformation = nil); overload;
241
242procedure PolyPolygonFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
243 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
244 Transformation: TTransformation = nil); overload;
245procedure PolygonFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
246 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
247 Transformation: TTransformation = nil); overload;
248procedure PolyPolygonFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
249 ClipRect: TRect; Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
250 Transformation: TTransformation = nil); overload;
251procedure PolygonFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
252 ClipRect: TRect; Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
253 Transformation: TTransformation = nil); overload;
254procedure PolyPolygonFS_LCD(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
255 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
256 Transformation: TTransformation = nil); overload;
257procedure PolygonFS_LCD(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
258 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
259 Transformation: TTransformation = nil); overload;
260procedure PolyPolygonFS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
261 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
262 Transformation: TTransformation = nil); overload;
263procedure PolygonFS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
264 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
265 Transformation: TTransformation = nil); overload;
266
267
268procedure PolyPolylineFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
269 Color: TColor32; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
270 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
271 MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil); overload;
272procedure PolyPolylineFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
273 Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
274 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
275 MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil); overload;
276
277procedure PolylineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
278 Color: TColor32; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
279 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
280 MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil); overload;
281procedure PolylineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
282 Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
283 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
284 MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil); overload;
285
286//Filled only Dashes ...
287procedure DashLineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
288 const Dashes: TArrayOfFloat; Color: TColor32;
289 Closed: Boolean = False; Width: TFloat = 1.0); overload;
290procedure DashLineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
291 const Dashes: TArrayOfFloat; FillColor, StrokeColor: TColor32;
292 Closed: Boolean; Width: TFloat; StrokeWidth: TFloat = 2.0); overload;
293//Filled and stroked Dashes ...
294procedure DashLineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
295 const Dashes: TArrayOfFloat; Filler: TCustomPolygonFiller;
296 Closed: Boolean = False; Width: TFloat = 1.0); overload;
297procedure DashLineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
298 const Dashes: TArrayOfFloat; Filler: TCustomPolygonFiller; StrokeColor: TColor32;
299 Closed: Boolean; Width: TFloat; StrokeWidth: TFloat = 2.0); overload;
300
301procedure PolyPolygonXS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
302 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
303 Transformation: TTransformation = nil); overload;
304procedure PolygonXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
305 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
306 Transformation: TTransformation = nil); overload;
307procedure PolyPolygonXS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
308 Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
309 Transformation: TTransformation = nil); overload;
310procedure PolygonXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
311 Filler: TCustomPolygonFiller; FillMode: TPolyFillMode = pfAlternate;
312 Transformation: TTransformation = nil); overload;
313procedure PolyPolygonXS_LCD(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
314 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
315 Transformation: TTransformation = nil); overload;
316procedure PolygonXS_LCD(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
317 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
318 Transformation: TTransformation = nil);
319procedure PolyPolygonXS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
320 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
321 Transformation: TTransformation = nil); overload;
322procedure PolygonXS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
323 Color: TColor32; FillMode: TPolyFillMode = pfAlternate;
324 Transformation: TTransformation = nil);
325
326procedure PolyPolylineXS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
327 Color: TColor32; Closed: Boolean = False; StrokeWidth: TFixed = $10000;
328 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
329 MiterLimit: TFixed = $40000; Transformation: TTransformation = nil); overload;
330procedure PolyPolylineXS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
331 Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFixed = $10000;
332 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
333 MiterLimit: TFixed = $40000; Transformation: TTransformation = nil); overload;
334
335procedure PolylineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
336 Color: TColor32; Closed: Boolean = False; StrokeWidth: TFixed = $10000;
337 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
338 MiterLimit: TFixed = $40000; Transformation: TTransformation = nil); overload;
339procedure PolylineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
340 Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFixed = $10000;
341 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
342 MiterLimit: TFixed = $40000; Transformation: TTransformation = nil); overload;
343
344//Filled only Dashes ...
345procedure DashLineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
346 const Dashes: TArrayOfFixed; Color: TColor32;
347 Closed: Boolean = False; Width: TFixed = $10000); overload;
348procedure DashLineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
349 const Dashes: TArrayOfFixed; FillColor, StrokeColor: TColor32;
350 Closed: Boolean; Width: TFixed; StrokeWidth: TFixed = $20000); overload;
351//Filled and stroked Dashes ...
352procedure DashLineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
353 const Dashes: TArrayOfFixed; Filler: TCustomPolygonFiller;
354 Closed: Boolean = False; Width: TFixed = $10000); overload;
355procedure DashLineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
356 const Dashes: TArrayOfFixed; Filler: TCustomPolygonFiller; StrokeColor: TColor32;
357 Closed: Boolean; Width: TFixed; StrokeWidth: TFixed = $20000); overload;
358
359// fill entire bitmap with a given polygon filler
360procedure FillBitmap(Bitmap: TBitmap32; Filler: TCustomPolygonFiller);
361
362{ Registration routines }
363procedure RegisterPolygonRenderer(PolygonRendererClass: TCustomPolygonRendererClass);
364
365var
366 PolygonRendererList: TClassList;
367 DefaultPolygonRendererClass: TPolygonRenderer32Class = TPolygonRenderer32VPR;
368
369implementation
370
371uses
372 Math, SysUtils, GR32_Math, GR32_LowLevel, GR32_Blend, GR32_Gamma,
373 GR32_VectorUtils;
374
375resourcestring
376 RCStrNoSamplerSpecified = 'No sampler specified!';
377
378type
379 TBitmap32Access = class(TBitmap32);
380
381procedure RegisterPolygonRenderer(PolygonRendererClass: TCustomPolygonRendererClass);
382begin
383 if not Assigned(PolygonRendererList) then PolygonRendererList := TClassList.Create;
384 PolygonRendererList.Add(PolygonRendererClass);
385end;
386
387// routines for color filling:
388
389procedure MakeAlphaNonZeroUP(Coverage: PSingleArray; AlphaValues: PColor32Array;
390 Count: Integer; Color: TColor32);
391var
392 I: Integer;
393 M, V: Cardinal;
394 Last: TFloat;
395 C: TColor32Entry absolute Color;
396begin
397 M := C.A * $101;
398 Last := Infinity;
399 for I := 0 to Count - 1 do
400 begin
401 if PInteger(@Last)^ <> PInteger(@Coverage[I])^ then
402 begin
403 Last := Coverage[I];
404 V := Abs(Round(Last * $10000));
405 if V > $10000 then V := $10000;
406 V := V * M shr 24;
407{$IFDEF USEGR32GAMMA}
408 V := GAMMA_ENCODING_TABLE[V];
409{$ENDIF}
410 C.A := V;
411 end;
412 AlphaValues[I] := Color;
413 end;
414end;
415
416(*
417procedure MakeAlphaNonZeroUP(Coverage: PSingleArray; AlphaValues: PColor32Array;
418 Count: Integer; Color: TColor32);
419var
420 I: Integer;
421 M, V, C: Cardinal;
422begin
423 M := Color shr 24 * $101;
424 C := Color and $00ffffff;
425 for I := 0 to Count - 1 do
426 begin
427 V := Abs(Round(Coverage[I] * $10000));
428 if V > $10000 then V := $10000;
429{$IFDEF USEGR32GAMMA}
430 V := GAMMA_ENCODING_TABLE[V * M shr 24];
431 AlphaValues[I] := (V shl 24) or C;
432{$ELSE}
433 AlphaValues[I] := (V * M and $ff000000) or C;
434{$ENDIF}
435 end;
436end;
437*)
438
439procedure MakeAlphaEvenOddUP(Coverage: PSingleArray; AlphaValues: PColor32Array;
440 Count: Integer; Color: TColor32);
441var
442 I: Integer;
443 M, V: Cardinal;
444 Last: TFloat;
445 C: TColor32Entry absolute Color;
446begin
447 M := C.A * $101;
448 Last := Infinity;
449 for I := 0 to Count - 1 do
450 begin
451 if PInteger(@Last)^ <> PInteger(@Coverage[I])^ then
452 begin
453 Last := Coverage[I];
454 V := Abs(Round(Coverage[I] * $10000));
455 V := V and $01ffff;
456 if V >= $10000 then
457 V := V xor $1ffff;
458 V := V * M shr 24;
459{$IFDEF USEGR32GAMMA}
460 V := GAMMA_ENCODING_TABLE[V];
461{$ENDIF}
462 C.A := V;
463 end;
464 AlphaValues[I] := Color;
465 end;
466end;
467
468procedure MakeAlphaNonZeroP(Value: Single; AlphaValues: PColor32Array;
469 Count: Integer; Color: TColor32);
470var
471 M, V: Cardinal;
472 C: TColor32Entry absolute Color;
473begin
474 M := C.A * $101;
475 V := Abs(Round(Value * $10000));
476 if V > $10000 then V := $10000;
477 V := V * M shr 24;
478{$IFDEF USEGR32GAMMA}
479 V := GAMMA_ENCODING_TABLE[V];
480{$ENDIF}
481 C.A := V;
482 FillLongWord(AlphaValues[0], Count, Color);
483end;
484
485procedure MakeAlphaEvenOddP(Value: Single; AlphaValues: PColor32Array;
486 Count: Integer; Color: TColor32);
487var
488 M, V: Cardinal;
489 C: TColor32Entry absolute Color;
490begin
491 M := C.A * $101;
492 V := Abs(Round(Value * $10000));
493 V := V and $01ffff;
494 if V > $10000 then V := V xor $1ffff;
495 V := V * M shr 24;
496{$IFDEF USEGR32GAMMA}
497 V := GAMMA_ENCODING_TABLE[V];
498{$ENDIF}
499 C.A := V;
500 FillLongWord(AlphaValues[0], Count, Color);
501end;
502
503
504// polygon filler routines (extract alpha only):
505
506procedure MakeAlphaNonZeroUPF(Coverage: PSingleArray; AlphaValues: PColor32Array;
507 Count: Integer; Color: TColor32);
508var
509 I: Integer;
510 V: Integer;
511begin
512 for I := 0 to Count - 1 do
513 begin
514 V := Clamp(Round(Abs(Coverage[I]) * 256));
515{$IFDEF USEGR32GAMMA}
516 V := GAMMA_ENCODING_TABLE[V];
517{$ENDIF}
518 AlphaValues[I] := V;
519 end;
520end;
521
522procedure MakeAlphaEvenOddUPF(Coverage: PSingleArray; AlphaValues: PColor32Array;
523 Count: Integer; Color: TColor32);
524var
525 I: Integer;
526 V: Integer;
527begin
528 for I := 0 to Count - 1 do
529 begin
530 V := Round(Abs(Coverage[I]) * 256);
531 V := V and $000001ff;
532 if V >= $100 then V := V xor $1ff;
533{$IFDEF USEGR32GAMMA}
534 V := GAMMA_ENCODING_TABLE[V];
535{$ENDIF}
536 AlphaValues[I] := V;
537 end;
538end;
539
540procedure MakeAlphaNonZeroPF(Value: Single; AlphaValues: PColor32Array;
541 Count: Integer; Color: TColor32);
542var
543 V: Integer;
544begin
545 V := Clamp(Round(Abs(Value) * 256));
546{$IFDEF USEGR32GAMMA}
547 V := GAMMA_ENCODING_TABLE[V];
548{$ENDIF}
549 FillLongWord(AlphaValues[0], Count, V);
550end;
551
552procedure MakeAlphaEvenOddPF(Value: Single; AlphaValues: PColor32Array;
553 Count: Integer; Color: TColor32);
554var
555 V: Integer;
556begin
557 V := Round(Abs(Value) * 256);
558 V := V and $000001ff;
559 if V >= $100 then V := V xor $1ff;
560{$IFDEF USEGR32GAMMA}
561 V := GAMMA_ENCODING_TABLE[V];
562{$ENDIF}
563 FillLongWord(AlphaValues[0], Count, V);
564end;
565
566procedure PolyPolygonFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
567 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
568var
569 Renderer: TPolygonRenderer32VPR;
570begin
571 Renderer := TPolygonRenderer32VPR.Create;
572 try
573 Renderer.Bitmap := Bitmap;
574 Renderer.Color := Color;
575 Renderer.FillMode := FillMode;
576 Renderer.PolyPolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
577 finally
578 Renderer.Free;
579 end;
580end;
581
582procedure PolygonFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
583 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
584var
585 Renderer: TPolygonRenderer32VPR;
586begin
587 Renderer := TPolygonRenderer32VPR.Create;
588 try
589 Renderer.Bitmap := Bitmap;
590 Renderer.Color := Color;
591 Renderer.FillMode := FillMode;
592 Renderer.PolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
593 finally
594 Renderer.Free;
595 end;
596end;
597
598procedure PolyPolygonFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
599 Filler: TCustomPolygonFiller; FillMode: TPolyFillMode; Transformation: TTransformation);
600var
601 Renderer: TPolygonRenderer32VPR;
602begin
603 if not Assigned(Filler) then Exit;
604 Renderer := TPolygonRenderer32VPR.Create;
605 try
606 Renderer.Bitmap := Bitmap;
607 Renderer.Filler := Filler;
608 Renderer.FillMode := FillMode;
609 Renderer.PolyPolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
610 finally
611 Renderer.Free;
612 end;
613end;
614
615procedure PolygonFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
616 Filler: TCustomPolygonFiller; FillMode: TPolyFillMode; Transformation: TTransformation);
617var
618 Renderer: TPolygonRenderer32VPR;
619begin
620 if not Assigned(Filler) then Exit;
621 Renderer := TPolygonRenderer32VPR.Create;
622 try
623 Renderer.Bitmap := Bitmap;
624 Renderer.Filler := Filler;
625 Renderer.FillMode := FillMode;
626 Renderer.PolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
627 finally
628 Renderer.Free;
629 end;
630end;
631
632procedure PolygonFS_LCD(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
633 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
634var
635 Renderer: TPolygonRenderer32LCD;
636begin
637 Renderer := TPolygonRenderer32LCD.Create;
638 try
639 Renderer.Bitmap := Bitmap;
640 Renderer.FillMode := FillMode;
641 Renderer.Color := Color;
642 Renderer.PolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
643 finally
644 Renderer.Free;
645 end;
646end;
647
648procedure PolyPolygonFS_LCD(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
649 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
650var
651 Renderer: TPolygonRenderer32LCD;
652begin
653 Renderer := TPolygonRenderer32LCD.Create;
654 try
655 Renderer.Bitmap := Bitmap;
656 Renderer.FillMode := FillMode;
657 Renderer.Color := Color;
658 Renderer.PolyPolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
659 finally
660 Renderer.Free;
661 end;
662end;
663
664procedure PolygonFS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
665 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
666var
667 Renderer: TPolygonRenderer32LCD2;
668begin
669 Renderer := TPolygonRenderer32LCD2.Create;
670 try
671 Renderer.Bitmap := Bitmap;
672 Renderer.FillMode := FillMode;
673 Renderer.Color := Color;
674 Renderer.PolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
675 finally
676 Renderer.Free;
677 end;
678end;
679
680procedure PolyPolygonFS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
681 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
682var
683 Renderer: TPolygonRenderer32LCD2;
684begin
685 Renderer := TPolygonRenderer32LCD2.Create;
686 try
687 Renderer.Bitmap := Bitmap;
688 Renderer.FillMode := FillMode;
689 Renderer.Color := Color;
690 Renderer.PolyPolygonFS(Points, FloatRect(Bitmap.ClipRect), Transformation);
691 finally
692 Renderer.Free;
693 end;
694end;
695
696procedure PolyPolygonFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
697 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode;
698 Transformation: TTransformation);
699var
700 Renderer: TPolygonRenderer32VPR;
701 IntersectedClipRect: TRect;
702begin
703 Renderer := TPolygonRenderer32VPR.Create;
704 try
705 Renderer.Bitmap := Bitmap;
706 Renderer.Color := Color;
707 Renderer.FillMode := FillMode;
708 GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
709 Renderer.PolyPolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
710 finally
711 Renderer.Free;
712 end;
713end;
714
715procedure PolygonFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
716 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode;
717 Transformation: TTransformation);
718var
719 Renderer: TPolygonRenderer32VPR;
720 IntersectedClipRect: TRect;
721begin
722 Renderer := TPolygonRenderer32VPR.Create;
723 try
724 Renderer.Bitmap := Bitmap;
725 Renderer.Color := Color;
726 Renderer.FillMode := FillMode;
727 GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
728 Renderer.PolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
729 finally
730 Renderer.Free;
731 end;
732end;
733
734procedure PolyPolygonFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
735 ClipRect: TRect; Filler: TCustomPolygonFiller; FillMode: TPolyFillMode;
736 Transformation: TTransformation);
737var
738 Renderer: TPolygonRenderer32VPR;
739 IntersectedClipRect: TRect;
740begin
741 if not Assigned(Filler) then Exit;
742 Renderer := TPolygonRenderer32VPR.Create;
743 try
744 Renderer.Bitmap := Bitmap;
745 Renderer.Filler := Filler;
746 Renderer.FillMode := FillMode;
747 GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
748 Renderer.PolyPolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
749 finally
750 Renderer.Free;
751 end;
752end;
753
754procedure PolygonFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
755 ClipRect: TRect; Filler: TCustomPolygonFiller; FillMode: TPolyFillMode;
756 Transformation: TTransformation);
757var
758 Renderer: TPolygonRenderer32VPR;
759 IntersectedClipRect: TRect;
760begin
761 if not Assigned(Filler) then Exit;
762 Renderer := TPolygonRenderer32VPR.Create;
763 try
764 Renderer.Bitmap := Bitmap;
765 Renderer.Filler := Filler;
766 Renderer.FillMode := FillMode;
767 GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
768 Renderer.PolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
769 finally
770 Renderer.Free;
771 end;
772end;
773
774procedure PolygonFS_LCD(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
775 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode;
776 Transformation: TTransformation);
777var
778 Renderer: TPolygonRenderer32LCD;
779 IntersectedClipRect: TRect;
780begin
781 Renderer := TPolygonRenderer32LCD.Create;
782 try
783 Renderer.Bitmap := Bitmap;
784 Renderer.FillMode := FillMode;
785 Renderer.Color := Color;
786 GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
787 Renderer.PolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
788 finally
789 Renderer.Free;
790 end;
791end;
792
793procedure PolyPolygonFS_LCD(Bitmap: TBitmap32;
794 const Points: TArrayOfArrayOfFloatPoint; ClipRect: TRect; Color: TColor32;
795 FillMode: TPolyFillMode; Transformation: TTransformation);
796var
797 Renderer: TPolygonRenderer32LCD;
798 IntersectedClipRect: TRect;
799begin
800 Renderer := TPolygonRenderer32LCD.Create;
801 try
802 Renderer.Bitmap := Bitmap;
803 Renderer.FillMode := FillMode;
804 Renderer.Color := Color;
805 GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
806 Renderer.PolyPolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
807 finally
808 Renderer.Free;
809 end;
810end;
811
812procedure PolygonFS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
813 ClipRect: TRect; Color: TColor32; FillMode: TPolyFillMode;
814 Transformation: TTransformation);
815var
816 Renderer: TPolygonRenderer32LCD2;
817 IntersectedClipRect: TRect;
818begin
819 Renderer := TPolygonRenderer32LCD2.Create;
820 try
821 Renderer.Bitmap := Bitmap;
822 Renderer.FillMode := FillMode;
823 Renderer.Color := Color;
824 GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
825 Renderer.PolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
826 finally
827 Renderer.Free;
828 end;
829end;
830
831procedure PolyPolygonFS_LCD2(Bitmap: TBitmap32;
832 const Points: TArrayOfArrayOfFloatPoint; ClipRect: TRect; Color: TColor32;
833 FillMode: TPolyFillMode; Transformation: TTransformation);
834var
835 Renderer: TPolygonRenderer32LCD2;
836 IntersectedClipRect: TRect;
837begin
838 Renderer := TPolygonRenderer32LCD2.Create;
839 try
840 Renderer.Bitmap := Bitmap;
841 Renderer.FillMode := FillMode;
842 Renderer.Color := Color;
843 GR32.IntersectRect(IntersectedClipRect, Bitmap.ClipRect, ClipRect);
844 Renderer.PolyPolygonFS(Points, FloatRect(IntersectedClipRect), Transformation);
845 finally
846 Renderer.Free;
847 end;
848end;
849
850procedure PolyPolylineFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
851 Color: TColor32; Closed: Boolean; StrokeWidth: TFloat;
852 JoinStyle: TJoinStyle; EndStyle: TEndStyle;
853 MiterLimit: TFloat; Transformation: TTransformation);
854var
855 Dst: TArrayOfArrayOfFloatPoint;
856begin
857 Dst := BuildPolyPolyLine(Points, Closed, StrokeWidth, JoinStyle, EndStyle, MiterLimit);
858 PolyPolygonFS(Bitmap, Dst, Color, pfWinding, Transformation);
859end;
860
861procedure PolyPolylineFS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFloatPoint;
862 Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
863 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
864 MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil);
865var
866 Dst: TArrayOfArrayOfFloatPoint;
867begin
868 Dst := BuildPolyPolyLine(Points, Closed, StrokeWidth, JoinStyle, EndStyle, MiterLimit);
869 PolyPolygonFS(Bitmap, Dst, Filler, pfWinding, Transformation);
870end;
871
872procedure PolylineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
873 Color: TColor32; Closed: Boolean; StrokeWidth: TFloat;
874 JoinStyle: TJoinStyle; EndStyle: TEndStyle;
875 MiterLimit: TFloat; Transformation: TTransformation);
876begin
877 PolyPolylineFS(Bitmap, PolyPolygon(Points), Color, Closed, StrokeWidth,
878 JoinStyle, EndStyle, MiterLimit, Transformation);
879end;
880
881procedure PolylineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
882 Filler: TCustomPolygonFiller; Closed: Boolean = False; StrokeWidth: TFloat = 1.0;
883 JoinStyle: TJoinStyle = jsMiter; EndStyle: TEndStyle = esButt;
884 MiterLimit: TFloat = 4.0; Transformation: TTransformation = nil);
885begin
886 PolyPolylineFS(Bitmap, PolyPolygon(Points), Filler, Closed, StrokeWidth,
887 JoinStyle, EndStyle, MiterLimit, Transformation);
888end;
889
890procedure DashLineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
891 const Dashes: TArrayOfFloat; Color: TColor32;
892 Closed: Boolean = False; Width: TFloat = 1.0);
893var
894 MultiPoly: TArrayOfArrayOfFloatPoint;
895begin
896 MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
897 PolyPolylineFS(Bitmap, MultiPoly, Color, False, Width);
898end;
899
900procedure DashLineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
901 const Dashes: TArrayOfFloat; FillColor, StrokeColor: TColor32;
902 Closed: Boolean; Width: TFloat; StrokeWidth: TFloat = 2.0);
903var
904 MultiPoly: TArrayOfArrayOfFloatPoint;
905begin
906 MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
907 MultiPoly := BuildPolyPolyLine(MultiPoly, False, Width);
908 PolyPolygonFS(Bitmap, MultiPoly, FillColor);
909 PolyPolylineFS(Bitmap, MultiPoly, StrokeColor, True, StrokeWidth);
910end;
911
912procedure DashLineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
913 const Dashes: TArrayOfFloat; Filler: TCustomPolygonFiller;
914 Closed: Boolean = False; Width: TFloat = 1.0);
915var
916 MultiPoly: TArrayOfArrayOfFloatPoint;
917begin
918 MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
919 PolyPolylineFS(Bitmap, MultiPoly, Filler, False, Width);
920end;
921
922procedure DashLineFS(Bitmap: TBitmap32; const Points: TArrayOfFloatPoint;
923 const Dashes: TArrayOfFloat; Filler: TCustomPolygonFiller; StrokeColor: TColor32;
924 Closed: Boolean; Width: TFloat; StrokeWidth: TFloat = 2.0);
925var
926 MultiPoly: TArrayOfArrayOfFloatPoint;
927begin
928 MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
929 MultiPoly := BuildPolyPolyLine(MultiPoly, False, Width);
930 PolyPolygonFS(Bitmap, MultiPoly, Filler);
931 PolyPolylineFS(Bitmap, MultiPoly, StrokeColor, True, StrokeWidth);
932end;
933
934
935procedure PolyPolygonXS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
936 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
937var
938 Renderer: TPolygonRenderer32VPR;
939begin
940 Renderer := TPolygonRenderer32VPR.Create;
941 try
942 Renderer.Bitmap := Bitmap;
943 Renderer.Color := Color;
944 Renderer.FillMode := FillMode;
945 Renderer.PolyPolygonFS(FixedPointToFloatPoint(Points),
946 FloatRect(Bitmap.ClipRect), Transformation);
947 finally
948 Renderer.Free;
949 end;
950end;
951
952procedure PolygonXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
953 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
954var
955 Renderer: TPolygonRenderer32VPR;
956begin
957 Renderer := TPolygonRenderer32VPR.Create;
958 try
959 Renderer.Bitmap := Bitmap;
960 Renderer.Color := Color;
961 Renderer.FillMode := FillMode;
962 Renderer.PolygonFS(FixedPointToFloatPoint(Points),
963 FloatRect(Bitmap.ClipRect), Transformation);
964 finally
965 Renderer.Free;
966 end;
967end;
968
969procedure PolyPolygonXS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
970 Filler: TCustomPolygonFiller; FillMode: TPolyFillMode; Transformation: TTransformation);
971var
972 Renderer: TPolygonRenderer32VPR;
973begin
974 Renderer := TPolygonRenderer32VPR.Create;
975 try
976 Renderer.Bitmap := Bitmap;
977 Renderer.Filler := Filler;
978 Renderer.FillMode := FillMode;
979 Renderer.PolyPolygonFS(FixedPointToFloatPoint(Points),
980 FloatRect(Bitmap.ClipRect), Transformation);
981 finally
982 Renderer.Free;
983 end;
984end;
985
986procedure PolygonXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
987 Filler: TCustomPolygonFiller; FillMode: TPolyFillMode; Transformation: TTransformation);
988var
989 Renderer: TPolygonRenderer32VPR;
990begin
991 Renderer := TPolygonRenderer32VPR.Create;
992 try
993 Renderer.Bitmap := Bitmap;
994 Renderer.Filler := Filler;
995 Renderer.FillMode := FillMode;
996 Renderer.PolygonFS(FixedPointToFloatPoint(Points),
997 FloatRect(Bitmap.ClipRect), Transformation);
998 finally
999 Renderer.Free;
1000 end;
1001end;
1002
1003procedure PolygonXS_LCD(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
1004 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
1005var
1006 Renderer: TPolygonRenderer32LCD;
1007begin
1008 Renderer := TPolygonRenderer32LCD.Create;
1009 try
1010 Renderer.Bitmap := Bitmap;
1011 Renderer.FillMode := FillMode;
1012 Renderer.Color := Color;
1013 Renderer.PolygonFS(FixedPointToFloatPoint(Points),
1014 FloatRect(Bitmap.ClipRect), Transformation);
1015 finally
1016 Renderer.Free;
1017 end;
1018end;
1019
1020procedure PolyPolygonXS_LCD(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
1021 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
1022var
1023 Renderer: TPolygonRenderer32LCD;
1024begin
1025 Renderer := TPolygonRenderer32LCD.Create;
1026 try
1027 Renderer.Bitmap := Bitmap;
1028 Renderer.FillMode := FillMode;
1029 Renderer.Color := Color;
1030 Renderer.PolyPolygonFS(FixedPointToFloatPoint(Points),
1031 FloatRect(Bitmap.ClipRect), Transformation);
1032 finally
1033 Renderer.Free;
1034 end;
1035end;
1036
1037procedure PolygonXS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
1038 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
1039var
1040 Renderer: TPolygonRenderer32LCD2;
1041begin
1042 Renderer := TPolygonRenderer32LCD2.Create;
1043 try
1044 Renderer.Bitmap := Bitmap;
1045 Renderer.FillMode := FillMode;
1046 Renderer.Color := Color;
1047 Renderer.PolygonFS(FixedPointToFloatPoint(Points),
1048 FloatRect(Bitmap.ClipRect), Transformation);
1049 finally
1050 Renderer.Free;
1051 end;
1052end;
1053
1054procedure PolyPolygonXS_LCD2(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
1055 Color: TColor32; FillMode: TPolyFillMode; Transformation: TTransformation);
1056var
1057 Renderer: TPolygonRenderer32LCD2;
1058begin
1059 Renderer := TPolygonRenderer32LCD2.Create;
1060 try
1061 Renderer.Bitmap := Bitmap;
1062 Renderer.FillMode := FillMode;
1063 Renderer.Color := Color;
1064 Renderer.PolyPolygonFS(FixedPointToFloatPoint(Points),
1065 FloatRect(Bitmap.ClipRect), Transformation);
1066 finally
1067 Renderer.Free;
1068 end;
1069end;
1070
1071procedure PolyPolylineXS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
1072 Color: TColor32; Closed: Boolean; StrokeWidth: TFixed;
1073 JoinStyle: TJoinStyle; EndStyle: TEndStyle;
1074 MiterLimit: TFixed; Transformation: TTransformation);
1075var
1076 Dst: TArrayOfArrayOfFixedPoint;
1077begin
1078 Dst := BuildPolyPolyLine(Points, Closed, StrokeWidth, JoinStyle, EndStyle,
1079 MiterLimit);
1080 PolyPolygonXS(Bitmap, Dst, Color, pfWinding, Transformation);
1081end;
1082
1083procedure PolyPolylineXS(Bitmap: TBitmap32; const Points: TArrayOfArrayOfFixedPoint;
1084 Filler: TCustomPolygonFiller; Closed: Boolean = False;
1085 StrokeWidth: TFixed = $10000; JoinStyle: TJoinStyle = jsMiter;
1086 EndStyle: TEndStyle = esButt; MiterLimit: TFixed = $40000;
1087 Transformation: TTransformation = nil);
1088var
1089 Dst: TArrayOfArrayOfFixedPoint;
1090begin
1091 Dst := BuildPolyPolyLine(Points, Closed, StrokeWidth, JoinStyle, EndStyle,
1092 MiterLimit);
1093 PolyPolygonXS(Bitmap, Dst, Filler, pfWinding, Transformation);
1094end;
1095
1096procedure PolylineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
1097 Color: TColor32; Closed: Boolean; StrokeWidth: TFixed;
1098 JoinStyle: TJoinStyle; EndStyle: TEndStyle;
1099 MiterLimit: TFixed; Transformation: TTransformation);
1100begin
1101 PolyPolylineXS(Bitmap, PolyPolygon(Points), Color,
1102 Closed, StrokeWidth, JoinStyle, EndStyle,
1103 MiterLimit, Transformation);
1104end;
1105
1106procedure PolylineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
1107 Filler: TCustomPolygonFiller; Closed: Boolean = False;
1108 StrokeWidth: TFixed = $10000; JoinStyle: TJoinStyle = jsMiter;
1109 EndStyle: TEndStyle = esButt; MiterLimit: TFixed = $40000;
1110 Transformation: TTransformation = nil);
1111begin
1112 PolyPolylineXS(Bitmap, PolyPolygon(Points), Filler, Closed, StrokeWidth,
1113 JoinStyle, EndStyle, MiterLimit, Transformation);
1114end;
1115
1116procedure DashLineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
1117 const Dashes: TArrayOfFixed; Color: TColor32;
1118 Closed: Boolean = False; Width: TFixed = $10000);
1119var
1120 MultiPoly: TArrayOfArrayOfFixedPoint;
1121begin
1122 MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
1123 PolyPolylineXS(Bitmap, MultiPoly, Color, False, Width);
1124end;
1125
1126procedure DashLineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
1127 const Dashes: TArrayOfFixed; FillColor, StrokeColor: TColor32;
1128 Closed: Boolean; Width: TFixed; StrokeWidth: TFixed = $20000);
1129var
1130 MultiPoly: TArrayOfArrayOfFixedPoint;
1131begin
1132 MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
1133 PolyPolylineXS(Bitmap, MultiPoly, FillColor, False, Width);
1134 MultiPoly := BuildPolyPolyLine(MultiPoly, False, Width);
1135 PolyPolylineXS(Bitmap, MultiPoly, StrokeColor, True, strokeWidth);
1136end;
1137
1138procedure DashLineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
1139 const Dashes: TArrayOfFixed; Filler: TCustomPolygonFiller;
1140 Closed: Boolean = False; Width: TFixed = $10000);
1141var
1142 MultiPoly: TArrayOfArrayOfFixedPoint;
1143begin
1144 MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
1145 PolyPolylineXS(Bitmap, MultiPoly, Filler, False, Width);
1146end;
1147
1148procedure DashLineXS(Bitmap: TBitmap32; const Points: TArrayOfFixedPoint;
1149 const Dashes: TArrayOfFixed; Filler: TCustomPolygonFiller; StrokeColor: TColor32;
1150 Closed: Boolean; Width: TFixed; StrokeWidth: TFixed = $20000);
1151var
1152 MultiPoly: TArrayOfArrayOfFixedPoint;
1153begin
1154 MultiPoly := GR32_VectorUtils.BuildDashedLine(Points, Dashes, 0, Closed);
1155 PolyPolylineXS(Bitmap, MultiPoly, Filler, False, Width);
1156 MultiPoly := BuildPolyPolyLine(MultiPoly, False, Width);
1157 PolyPolylineXS(Bitmap, MultiPoly, StrokeColor, True, StrokeWidth);
1158end;
1159
1160procedure FillBitmap(Bitmap: TBitmap32; Filler: TCustomPolygonFiller);
1161var
1162 AlphaValues: PColor32;
1163 Y: Integer;
1164begin
1165 {$IFDEF USESTACKALLOC}
1166 AlphaValues := StackAlloc(Bitmap.Width * SizeOf(TColor32));
1167 {$ELSE}
1168 GetMem(AlphaValues, Bitmap.Width * SizeOf(TColor32));
1169 {$ENDIF}
1170 FillLongword(AlphaValues^, Bitmap.Width, $FF);
1171 Filler.BeginRendering;
1172 for Y := 0 to Bitmap.Height - 1 do
1173 Filler.FillLine(PColor32(Bitmap.ScanLine[y]), 0, y, Bitmap.Width,
1174 AlphaValues, Bitmap.CombineMode);
1175 Filler.EndRendering;
1176 {$IFDEF USESTACKALLOC}
1177 StackFree(AlphaValues);
1178 {$ELSE}
1179 FreeMem(AlphaValues);
1180 {$ENDIF}
1181end;
1182
1183
1184{ LCD sub-pixel rendering (see http://www.grc.com/cttech.htm) }
1185
1186type
1187 PRGBTriple = ^TRGBTriple;
1188 TRGBTriple = packed record
1189 B, G, R: Byte;
1190 end;
1191
1192 PRGBTripleArray = ^TRGBTripleArray;
1193 TRGBTripleArray = array [0..0] of TRGBTriple;
1194
1195 TMakeAlphaProcLCD = procedure(Coverage: PSingleArray; AlphaValues: SysUtils.PByteArray;
1196 Count: Integer; Color: TColor32);
1197
1198procedure MakeAlphaNonZeroLCD(Coverage: PSingleArray; AlphaValues: SysUtils.PByteArray;
1199 Count: Integer; Color: TColor32);
1200var
1201 I: Integer;
1202 M, V: Cardinal;
1203 Last: TFloat;
1204 C: TColor32Entry absolute Color;
1205begin
1206 M := C.A * 86; // 86 = 258 / 3
1207
1208 Last := Infinity;
1209 V := 0;
1210 AlphaValues[0] := 0;
1211 AlphaValues[1] := 0;
1212 for I := 0 to Count - 1 do
1213 begin
1214 if PInteger(@Last)^ <> PInteger(@Coverage[I])^ then
1215 begin
1216 Last := Coverage[I];
1217 V := Abs(Round(Last * $10000));
1218 if V > $10000 then V := $10000;
1219 V := V * M shr 24;
1220 end;
1221 Inc(AlphaValues[I], V);
1222{$IFDEF USEGR32GAMMA}
1223 AlphaValues[I] := GAMMA_ENCODING_TABLE[AlphaValues[I]];
1224{$ENDIF}
1225 Inc(AlphaValues[I + 1], V);
1226 AlphaValues[I + 2] := V;
1227 end;
1228 AlphaValues[Count + 2] := 0;
1229 AlphaValues[Count + 3] := 0;
1230end;
1231
1232procedure MakeAlphaEvenOddLCD(Coverage: PSingleArray; AlphaValues: SysUtils.PByteArray;
1233 Count: Integer; Color: TColor32);
1234var
1235 I: Integer;
1236 M, V: Cardinal;
1237 Last: TFloat;
1238begin
1239 M := Color shr 24 * 86; // 86 = 258 / 3
1240
1241 Last := Infinity;
1242 V := 0;
1243 AlphaValues[0] := 0;
1244 AlphaValues[1] := 0;
1245 for I := 0 to Count - 1 do
1246 begin
1247 if PInteger(@Last)^ <> PInteger(@Coverage[I])^ then
1248 begin
1249 Last := Coverage[I];
1250 V := Abs(Round(Coverage[I] * $10000));
1251 V := V and $01ffff;
1252 if V >= $10000 then V := V xor $1ffff;
1253 V := V * M shr 24;
1254 end;
1255 Inc(AlphaValues[I], V);
1256{$IFDEF USEGR32GAMMA}
1257 AlphaValues[I] := GAMMA_ENCODING_TABLE[AlphaValues[I]];
1258{$ENDIF}
1259 Inc(AlphaValues[I + 1], V);
1260 AlphaValues[I + 2] := V;
1261 end;
1262 AlphaValues[Count + 2] := 0;
1263 AlphaValues[Count + 3] := 0;
1264end;
1265
1266procedure MakeAlphaNonZeroLCD2(Coverage: PSingleArray; AlphaValues: SysUtils.PByteArray;
1267 Count: Integer; Color: TColor32);
1268var
1269 I: Integer;
1270begin
1271 MakeAlphaNonZeroLCD(Coverage, AlphaValues, Count, Color);
1272 AlphaValues[Count + 2] := (AlphaValues[Count] + AlphaValues[Count + 1]) div 3;
1273 AlphaValues[Count + 3] := AlphaValues[Count + 1] div 3;
1274 for I := Count + 1 downto 2 do
1275 begin
1276 AlphaValues[I] := (AlphaValues[I] + AlphaValues[I - 1] + AlphaValues[I - 2]) div 3;
1277 end;
1278 AlphaValues[1] := (AlphaValues[0] + AlphaValues[1]) div 3;
1279 AlphaValues[0] := AlphaValues[0] div 3;
1280end;
1281
1282procedure MakeAlphaEvenOddLCD2(Coverage: PSingleArray; AlphaValues: SysUtils.PByteArray;
1283 Count: Integer; Color: TColor32);
1284var
1285 I: Integer;
1286begin
1287 MakeAlphaEvenOddLCD(Coverage, AlphaValues, Count, Color);
1288 AlphaValues[Count + 2] := (AlphaValues[Count] + AlphaValues[Count + 1]) div 3;
1289 AlphaValues[Count + 3] := AlphaValues[Count + 1] div 3;
1290 for I := Count + 1 downto 2 do
1291 begin
1292 AlphaValues[I] := (AlphaValues[I] + AlphaValues[I - 1] + AlphaValues[I - 2]) div 3;
1293 end;
1294 AlphaValues[1] := (AlphaValues[0] + AlphaValues[1]) div 3;
1295 AlphaValues[0] := AlphaValues[0] div 3;
1296end;
1297
1298procedure CombineLineLCD(Weights: PRGBTripleArray; Dst: PColor32Array; Color: TColor32; Count: Integer);
1299var
1300 I: Integer;
1301 {$IFDEF TEST_BLENDMEMRGB128SSE4}
1302 Weights64: UInt64;
1303 {$ENDIF}
1304begin
1305 I := 0;
1306 while Count <> 0 do
1307 {$IFDEF TEST_BLENDMEMRGB128SSE4}
1308 if (Count shr 1) = 0 then
1309 {$ENDIF}
1310 begin
1311 if PColor32(@Weights[I])^ = $FFFFFFFF then
1312 Dst[I] := Color
1313 else
1314 BlendMemRGB(Color, Dst[I], PColor32(@Weights[I])^);
1315 Dec(Count);
1316 Inc(I);
1317 end
1318 {$IFDEF TEST_BLENDMEMRGB128SSE4}
1319 else
1320 begin
1321 Weights64 := (UInt64(PColor32(@Weights[I + 1])^) shl 32) or
1322 PColor32(@Weights[I])^;
1323 if Weights64 = $FFFFFFFFFFFFFFFF then
1324 begin
1325 Dst[I] := Color;
1326 Dst[I + 1] := Color;
1327 end
1328 else
1329 BlendMemRGB128(Color, Dst[I], Weights64);
1330 Dec(Count, 2);
1331 Inc(I, 2);
1332 end
1333 {$ENDIF};
1334 EMMS;
1335end;
1336
1337{ TCustomPolygonFiller }
1338
1339procedure TCustomPolygonFiller.BeginRendering;
1340begin
1341 // implemented by descendants
1342end;
1343
1344procedure TCustomPolygonFiller.EndRendering;
1345begin
1346 // implemented by descendants
1347end;
1348
1349{ TCallbackPolygonFiller }
1350
1351function TCallbackPolygonFiller.GetFillLine: TFillLineEvent;
1352begin
1353 Result := FFillLineEvent;
1354end;
1355
1356
1357{ TInvertPolygonFiller }
1358
1359procedure TInvertPolygonFiller.FillLineBlend(Dst: PColor32; DstX, DstY,
1360 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
1361var
1362 X: Integer;
1363 BlendMemEx: TBlendMemEx;
1364begin
1365 BlendMemEx := BLEND_MEM_EX[CombineMode]^;
1366 for X := DstX to DstX + Length - 1 do
1367 begin
1368 BlendMemEx(InvertColor(Dst^), Dst^, AlphaValues^);
1369 EMMS;
1370 Inc(Dst);
1371 Inc(AlphaValues);
1372 end;
1373end;
1374
1375function TInvertPolygonFiller.GetFillLine: TFillLineEvent;
1376begin
1377 Result := FillLineBlend;
1378end;
1379
1380
1381{ TClearPolygonFiller }
1382
1383constructor TClearPolygonFiller.Create(Color: TColor32 = $00808080);
1384begin
1385 inherited Create;
1386 FColor := Color;
1387end;
1388
1389procedure TClearPolygonFiller.FillLineClear(Dst: PColor32; DstX, DstY,
1390 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
1391begin
1392 FillLongword(Dst^, Length, FColor);
1393end;
1394
1395function TClearPolygonFiller.GetFillLine: TFillLineEvent;
1396begin
1397 Result := FillLineClear;
1398end;
1399
1400
1401{ TBitmapPolygonFiller }
1402
1403procedure TBitmapPolygonFiller.FillLineOpaque(Dst: PColor32; DstX, DstY,
1404 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
1405var
1406 PatternX, PatternY, X: Integer;
1407 OpaqueAlpha: TColor32;
1408 Src: PColor32;
1409 BlendMemEx: TBlendMemEx;
1410begin
1411 PatternX := (DstX - OffsetX) mod FPattern.Width;
1412 if PatternX < 0 then PatternX := (FPattern.Width + PatternX) mod FPattern.Width;
1413 PatternY := (DstY - OffsetY) mod FPattern.Height;
1414 if PatternY < 0 then PatternY := (FPattern.Height + PatternY) mod FPattern.Height;
1415
1416 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1417
1418 if Assigned(AlphaValues) then
1419 begin
1420 OpaqueAlpha := TColor32($FF shl 24);
1421 BlendMemEx := BLEND_MEM_EX[FPattern.CombineMode]^;
1422 for X := DstX to DstX + Length - 1 do
1423 begin
1424 BlendMemEx(Src^ and $00FFFFFF or OpaqueAlpha, Dst^, AlphaValues^);
1425 Inc(Dst); Inc(Src); Inc(PatternX);
1426 if PatternX >= FPattern.Width then
1427 begin
1428 PatternX := 0;
1429 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1430 end;
1431 Inc(AlphaValues);
1432 end
1433 end
1434 else
1435 for X := DstX to DstX + Length - 1 do
1436 begin
1437 Dst^ := Src^;
1438 Inc(Dst); Inc(Src); Inc(PatternX);
1439 if PatternX >= FPattern.Width then
1440 begin
1441 PatternX := 0;
1442 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1443 end;
1444 end;
1445end;
1446
1447procedure TBitmapPolygonFiller.FillLineBlend(Dst: PColor32; DstX, DstY,
1448 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
1449var
1450 PatternX, PatternY, X: Integer;
1451 Src: PColor32;
1452 BlendMemEx: TBlendMemEx;
1453 BlendMem: TBlendMem;
1454begin
1455 PatternX := (DstX - OffsetX) mod FPattern.Width;
1456 if PatternX < 0 then PatternX := (FPattern.Width + PatternX) mod FPattern.Width;
1457 PatternY := (DstY - OffsetY) mod FPattern.Height;
1458 if PatternY < 0 then PatternY := (FPattern.Height + PatternY) mod FPattern.Height;
1459
1460 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1461
1462 if Assigned(AlphaValues) then
1463 begin
1464 BlendMemEx := BLEND_MEM_EX[FPattern.CombineMode]^;
1465 for X := DstX to DstX + Length - 1 do
1466 begin
1467 BlendMemEx(Src^, Dst^, AlphaValues^);
1468 Inc(Dst); Inc(Src); Inc(PatternX);
1469 if PatternX >= FPattern.Width then
1470 begin
1471 PatternX := 0;
1472 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1473 end;
1474 Inc(AlphaValues);
1475 end
1476 end
1477 else
1478 begin
1479 BlendMem := BLEND_MEM[FPattern.CombineMode]^;
1480 for X := DstX to DstX + Length - 1 do
1481 begin
1482 BlendMem(Src^, Dst^);
1483 Inc(Dst); Inc(Src); Inc(PatternX);
1484 if PatternX >= FPattern.Width then
1485 begin
1486 PatternX := 0;
1487 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1488 end;
1489 end;
1490 end;
1491end;
1492
1493procedure TBitmapPolygonFiller.FillLineBlendMasterAlpha(Dst: PColor32;
1494 DstX, DstY, Length: Integer; AlphaValues: PColor32;
1495 CombineMode: TCombineMode);
1496var
1497 PatternX, PatternY, X: Integer;
1498 Src: PColor32;
1499 BlendMemEx: TBlendMemEx;
1500begin
1501 PatternX := (DstX - OffsetX) mod FPattern.Width;
1502 if PatternX < 0 then PatternX := (FPattern.Width + PatternX) mod FPattern.Width;
1503 PatternY := (DstY - OffsetY) mod FPattern.Height;
1504 if PatternY < 0 then PatternY := (FPattern.Height + PatternY) mod FPattern.Height;
1505
1506 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1507
1508 BlendMemEx := BLEND_MEM_EX[FPattern.CombineMode]^;
1509
1510 if Assigned(AlphaValues) then
1511 for X := DstX to DstX + Length - 1 do
1512 begin
1513 BlendMemEx(Src^, Dst^, Div255(AlphaValues^ * FPattern.MasterAlpha));
1514 Inc(Dst); Inc(Src); Inc(PatternX);
1515 if PatternX >= FPattern.Width then
1516 begin
1517 PatternX := 0;
1518 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1519 end;
1520 Inc(AlphaValues);
1521 end
1522 else
1523 for X := DstX to DstX + Length - 1 do
1524 begin
1525 BlendMemEx(Src^, Dst^, FPattern.MasterAlpha);
1526 Inc(Dst); Inc(Src); Inc(PatternX);
1527 if PatternX >= FPattern.Width then
1528 begin
1529 PatternX := 0;
1530 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1531 end;
1532 end;
1533end;
1534
1535procedure TBitmapPolygonFiller.FillLineCustomCombine(Dst: PColor32;
1536 DstX, DstY, Length: Integer; AlphaValues: PColor32;
1537 CombineMode: TCombineMode);
1538var
1539 PatternX, PatternY, X: Integer;
1540 Src: PColor32;
1541begin
1542 PatternX := (DstX - OffsetX) mod FPattern.Width;
1543 if PatternX < 0 then PatternX := (FPattern.Width + PatternX) mod FPattern.Width;
1544 PatternY := (DstY - OffsetY) mod FPattern.Height;
1545 if PatternY < 0 then PatternY := (FPattern.Height + PatternY) mod FPattern.Height;
1546
1547 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1548
1549 if Assigned(AlphaValues) then
1550 for X := DstX to DstX + Length - 1 do
1551 begin
1552 FPattern.OnPixelCombine(Src^, Dst^, Div255(AlphaValues^ * FPattern.MasterAlpha));
1553 Inc(Dst); Inc(Src); Inc(PatternX);
1554 if PatternX >= FPattern.Width then
1555 begin
1556 PatternX := 0;
1557 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1558 end;
1559 Inc(AlphaValues);
1560 end
1561 else
1562 for X := DstX to DstX + Length - 1 do
1563 begin
1564 FPattern.OnPixelCombine(Src^, Dst^, FPattern.MasterAlpha);
1565 Inc(Dst); Inc(Src); Inc(PatternX);
1566 if PatternX >= FPattern.Width then
1567 begin
1568 PatternX := 0;
1569 Src := @FPattern.Bits[PatternX + PatternY * FPattern.Width];
1570 end;
1571 end;
1572end;
1573
1574function TBitmapPolygonFiller.GetFillLine: TFillLineEvent;
1575begin
1576 if not Assigned(FPattern) then
1577 begin
1578 Result := nil;
1579 end
1580 else if FPattern.DrawMode = dmOpaque then
1581 Result := FillLineOpaque
1582 else if FPattern.DrawMode = dmBlend then
1583 begin
1584 if FPattern.MasterAlpha = 255 then
1585 Result := FillLineBlend
1586 else
1587 Result := FillLineBlendMasterAlpha;
1588 end
1589 else if (FPattern.DrawMode = dmCustom) and Assigned(FPattern.OnPixelCombine) then
1590 begin
1591 Result := FillLineCustomCombine;
1592 end
1593 else
1594 Result := nil;
1595end;
1596
1597{ TSamplerFiller }
1598
1599constructor TSamplerFiller.Create(Sampler: TCustomSampler = nil);
1600begin
1601 inherited Create;
1602 FSampler := Sampler;
1603 SamplerChanged;
1604end;
1605
1606procedure TSamplerFiller.EndRendering;
1607begin
1608 if Assigned(FSampler) then
1609 FSampler.FinalizeSampling
1610 else
1611 raise Exception.Create(RCStrNoSamplerSpecified);
1612end;
1613
1614procedure TSamplerFiller.SampleLineOpaque(Dst: PColor32; DstX, DstY,
1615 Length: Integer; AlphaValues: PColor32; CombineMode: TCombineMode);
1616var
1617 X: Integer;
1618 BlendMemEx: TBlendMemEx;
1619begin
1620 BlendMemEx := BLEND_MEM_EX[CombineMode]^;
1621 for X := DstX to DstX + Length - 1 do
1622 begin
1623 BlendMemEx(FGetSample(X, DstY) and $00FFFFFF or $FF000000, Dst^, AlphaValues^);
1624 EMMS;
1625 Inc(Dst);
1626 Inc(AlphaValues);
1627 end;
1628end;
1629
1630procedure TSamplerFiller.SamplerChanged;
1631begin
1632 if Assigned(FSampler) then
1633 FGetSample := FSampler.GetSampleInt;
1634end;
1635
1636procedure TSamplerFiller.BeginRendering;
1637begin
1638 if Assigned(FSampler) then
1639 FSampler.PrepareSampling
1640 else
1641 raise Exception.Create(RCStrNoSamplerSpecified);
1642end;
1643
1644function TSamplerFiller.GetFillLine: TFillLineEvent;
1645begin
1646 Result := SampleLineOpaque;
1647end;
1648
1649procedure TSamplerFiller.SetSampler(const Value: TCustomSampler);
1650begin
1651 if FSampler <> Value then
1652 begin
1653 FSampler := Value;
1654 SamplerChanged;
1655 end;
1656end;
1657
1658
1659{ TCustomPolygonRenderer }
1660
1661procedure TCustomPolygonRenderer.PolygonFS(
1662 const Points: TArrayOfFloatPoint; const ClipRect: TFloatRect;
1663 Transformation: TTransformation);
1664begin
1665 PolyPolygonFS(PolyPolygon(Points), ClipRect, Transformation);
1666end;
1667
1668procedure TCustomPolygonRenderer.PolygonFS(
1669 const Points: TArrayOfFloatPoint; const ClipRect: TFloatRect);
1670begin
1671 PolyPolygonFS(PolyPolygon(Points), ClipRect);
1672end;
1673
1674procedure TCustomPolygonRenderer.PolyPolygonFS(
1675 const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect);
1676begin
1677 // implemented by descendants
1678end;
1679
1680procedure TCustomPolygonRenderer.PolyPolygonFS(
1681 const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect;
1682 Transformation: TTransformation);
1683var
1684 APoints: TArrayOfArrayOfFloatPoint;
1685begin
1686 if Assigned(Transformation) then
1687 APoints := TransformPolyPolygon(Points, Transformation)
1688 else
1689 APoints := Points;
1690 PolyPolygonFS(APoints, ClipRect);
1691end;
1692
1693{ TPolygonRenderer32 }
1694
1695constructor TPolygonRenderer32.Create(Bitmap: TBitmap32;
1696 Fillmode: TPolyFillMode);
1697begin
1698 inherited Create;
1699 FBitmap := Bitmap;
1700 FFillMode := Fillmode;
1701end;
1702
1703procedure TPolygonRenderer32.PolygonFS(const Points: TArrayOfFloatPoint);
1704begin
1705 PolyPolygonFS(PolyPolygon(Points), FloatRect(FBitmap.ClipRect));
1706end;
1707
1708procedure TPolygonRenderer32.PolyPolygonFS(const Points: TArrayOfArrayOfFloatPoint);
1709begin
1710 PolyPolygonFS(Points, FloatRect(FBitmap.ClipRect));
1711end;
1712
1713procedure TPolygonRenderer32.SetBitmap(const Value: TBitmap32);
1714begin
1715 if FBitmap <> Value then
1716 begin
1717 FBitmap := Value;
1718 Changed;
1719 end;
1720end;
1721
1722procedure TPolygonRenderer32.SetColor(const Value: TColor32);
1723begin
1724 if FColor <> Value then
1725 begin
1726 FColor := Value;
1727 Changed;
1728 end;
1729end;
1730
1731procedure TPolygonRenderer32.SetFiller(const Value: TCustomPolygonFiller);
1732begin
1733 if FFiller <> Value then
1734 begin
1735 FFiller := Value;
1736 Changed;
1737 end;
1738end;
1739
1740procedure TPolygonRenderer32.SetFillMode(const Value: TPolyFillMode);
1741begin
1742 if FFillMode <> Value then
1743 begin
1744 FFillMode := Value;
1745 Changed;
1746 end;
1747end;
1748
1749{ TPolygonRenderer32VPR }
1750
1751{$IFDEF USESTACKALLOC}
1752{$W+}
1753{$ENDIF}
1754procedure TPolygonRenderer32VPR.FillSpan(const Span: TValueSpan; DstY: Integer);
1755var
1756 AlphaValues: PColor32Array;
1757 Count: Integer;
1758begin
1759 Count := Span.X2 - Span.X1 + 1;
1760 {$IFDEF USESTACKALLOC}
1761 AlphaValues := StackAlloc(Count * SizeOf(TColor32));
1762 {$ELSE}
1763 GetMem(AlphaValues, Count * SizeOf(TColor32));
1764 {$ENDIF}
1765 FFillProc(Span.Values, AlphaValues, Count, FColor);
1766 FFiller.FillLine(@Bitmap.ScanLine[DstY][Span.X1], Span.X1, DstY, Count,
1767 PColor32(AlphaValues), Bitmap.CombineMode);
1768 EMMS;
1769 {$IFDEF USESTACKALLOC}
1770 StackFree(AlphaValues);
1771 {$ELSE}
1772 FreeMem(AlphaValues);
1773 {$ENDIF}
1774end;
1775{$IFDEF USESTACKALLOC}
1776{$W-}
1777{$ENDIF}
1778
1779function TPolygonRenderer32VPR.GetRenderSpan: TRenderSpanEvent;
1780begin
1781 if Assigned(FFiller) then
1782 Result := FillSpan
1783 else
1784 Result := RenderSpan;
1785end;
1786
1787procedure TPolygonRenderer32VPR.PolyPolygonFS(
1788 const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect);
1789{$IFDEF CHANGENOTIFICATIONS}
1790var
1791 I: Integer;
1792{$ENDIF}
1793begin
1794 UpdateFillProcs;
1795 if Assigned(FFiller) then
1796 begin
1797 FFiller.BeginRendering;
1798 RenderPolyPolygon(Points, ClipRect, GetRenderSpan());
1799 FFiller.EndRendering;
1800 end
1801 else
1802 RenderPolyPolygon(Points, ClipRect, GetRenderSpan());
1803
1804{$IFDEF CHANGENOTIFICATIONS}
1805 if TBitmap32Access(Bitmap).UpdateCount = 0 then
1806 for I := 0 to High(Points) do
1807 if Length(Points[I]) > 0 then
1808 Bitmap.Changed(MakeRect(PolygonBounds(Points[I])));
1809{$ENDIF}
1810end;
1811
1812{$W+}
1813procedure TPolygonRenderer32VPR.RenderSpan(const Span: TValueSpan;
1814 DstY: Integer);
1815var
1816 AlphaValues: PColor32Array;
1817 Count: Integer;
1818begin
1819 Count := Span.X2 - Span.X1 + 1;
1820 {$IFDEF USESTACKALLOC}
1821 AlphaValues := StackAlloc(Count * SizeOf(TColor32));
1822 {$ELSE}
1823 GetMem(AlphaValues, Count * SizeOf(TColor32));
1824 {$ENDIF}
1825 FFillProc(Span.Values, AlphaValues, Count, FColor);
1826 if Bitmap.CombineMode = cmMerge then
1827 MergeLine(@AlphaValues[0], @Bitmap.ScanLine[DstY][Span.X1], Count)
1828 else
1829 BlendLine(@AlphaValues[0], @Bitmap.ScanLine[DstY][Span.X1], Count);
1830 EMMS;
1831 {$IFDEF USESTACKALLOC}
1832 StackFree(AlphaValues);
1833 {$ELSE}
1834 FreeMem(AlphaValues);
1835 {$ENDIF}
1836end;
1837{$W-}
1838
1839procedure TPolygonRenderer32VPR.UpdateFillProcs;
1840const
1841 FillProcs: array [Boolean, TPolyFillMode] of TFillProc = (
1842 (MakeAlphaEvenOddUP, MakeAlphaNonZeroUP),
1843 (MakeAlphaEvenOddUPF, MakeAlphaNonZeroUPF)
1844 );
1845begin
1846 FFillProc := FillProcs[Assigned(FFiller), FillMode];
1847end;
1848
1849{ TPolygonRenderer32LCD }
1850
1851procedure TPolygonRenderer32LCD.PolyPolygonFS(
1852 const Points: TArrayOfArrayOfFloatPoint; const ClipRect: TFloatRect);
1853var
1854 R: TFloatRect;
1855 APoints: TArrayOfArrayOfFloatPoint;
1856{$IFDEF CHANGENOTIFICATIONS}
1857 I: Integer;
1858{$ENDIF}
1859begin
1860 APoints := ScalePolyPolygon(Points, 3, 1);
1861 R.Top := ClipRect.Top;
1862 R.Bottom := ClipRect.Bottom;
1863 R.Left := ClipRect.Left * 3;
1864 R.Right := ClipRect.Right * 3;
1865 RenderPolyPolygon(APoints, R, RenderSpan);
1866{$IFDEF CHANGENOTIFICATIONS}
1867 if TBitmap32Access(Bitmap).UpdateCount = 0 then
1868 for I := 0 to High(Points) do
1869 if length(Points[I]) > 0 then
1870 Bitmap.Changed(MakeRect(PolygonBounds(Points[I])));
1871{$ENDIF}
1872end;
1873
1874{$W+}
1875procedure TPolygonRenderer32LCD.RenderSpan(const Span: TValueSpan;
1876 DstY: Integer);
1877const
1878 PADDING = 5;
1879var
1880 AlphaValues: SysUtils.PByteArray;
1881 Count: Integer;
1882 X1, Offset: Integer;
1883const
1884 MakeAlpha: array [TPolyFillMode] of TMakeAlphaProcLCD = (MakeAlphaEvenOddLCD, MakeAlphaNonZeroLCD);
1885begin
1886 Count := Span.X2 - Span.X1 + 1;
1887 X1 := DivMod(Span.X1, 3, Offset);
1888
1889 // Left Padding + Right Padding + Filter Width = 2 + 2 + 2 = 6
1890 {$IFDEF USESTACKALLOC}
1891 AlphaValues := StackAlloc((Count + 6 + PADDING) * SizeOf(Byte));
1892 {$ELSE}
1893 GetMem(AlphaValues, (Count + 6 + PADDING) * SizeOf(Byte));
1894 {$ENDIF}
1895 AlphaValues[0] := 0;
1896 AlphaValues[1] := 0;
1897 if (X1 > 0) then
1898 begin
1899 Dec(X1);
1900 Inc(Offset, 3);
1901 AlphaValues[2] := 0;
1902 AlphaValues[3] := 0;
1903 AlphaValues[4] := 0;
1904 end;
1905
1906 MakeAlpha[FFillMode](Span.Values, PByteArray(@AlphaValues[PADDING]), Count, FColor);
1907 CombineLineLCD(@AlphaValues[PADDING - Offset], PColor32Array(@Bitmap.ScanLine[DstY][X1]), FColor, (Count + Offset + 2) div 3);
1908
1909 {$IFDEF USESTACKALLOC}
1910 StackFree(AlphaValues);
1911 {$ELSE}
1912 FreeMem(AlphaValues);
1913 {$ENDIF}
1914end;
1915{$W-}
1916
1917
1918{ TPolygonRenderer32LCD2 }
1919
1920{$W+}
1921procedure TPolygonRenderer32LCD2.RenderSpan(const Span: TValueSpan;
1922 DstY: Integer);
1923const
1924 PADDING = 5;
1925var
1926 AlphaValues: SysUtils.PByteArray;
1927 Count: Integer;
1928 X1, Offset: Integer;
1929const
1930 MakeAlpha: array [TPolyFillMode] of TMakeAlphaProcLCD = (MakeAlphaEvenOddLCD2, MakeAlphaNonZeroLCD2);
1931begin
1932 Count := Span.X2 - Span.X1 + 1;
1933 X1 := DivMod(Span.X1, 3, Offset);
1934
1935 // Left Padding + Right Padding + Filter Width = 2 + 2 + 2 = 6
1936 {$IFDEF USESTACKALLOC}
1937 AlphaValues := StackAlloc((Count + 6 + PADDING) * SizeOf(Byte));
1938 {$ELSE}
1939 GetMem(AlphaValues, (Count + 6 + PADDING) * SizeOf(Byte));
1940 {$ENDIF}
1941 AlphaValues[0] := 0;
1942 AlphaValues[1] := 0;
1943 if (X1 > 0) then
1944 begin
1945 Dec(X1);
1946 Inc(Offset, 3);
1947 AlphaValues[2] := 0;
1948 AlphaValues[3] := 0;
1949 AlphaValues[4] := 0;
1950 end;
1951
1952 Dec(Offset, 1);
1953 MakeAlpha[FFillMode](Span.Values, PByteArray(@AlphaValues[PADDING]), Count, FColor);
1954 Inc(Count);
1955 CombineLineLCD(@AlphaValues[PADDING - Offset], PColor32Array(@Bitmap.ScanLine[DstY][X1]), FColor, (Count + Offset + 2) div 3);
1956
1957 {$IFDEF USESTACKALLOC}
1958 StackFree(AlphaValues);
1959 {$ELSE}
1960 FreeMem(AlphaValues);
1961 {$ENDIF}
1962end;
1963{$W-}
1964
1965initialization
1966 RegisterPolygonRenderer(TPolygonRenderer32VPR);
1967 RegisterPolygonRenderer(TPolygonRenderer32LCD);
1968 RegisterPolygonRenderer(TPolygonRenderer32LCD2);
1969
1970finalization
1971 PolygonRendererList.Free;
1972
1973end.
Note: See TracBrowser for help on using the repository browser.