source: branches/gbitmap/Packages/FastGraphics/UGGraphics.pas

Last change on this file was 25, checked in by chronos, 8 years ago
  • Fixed: Memory leaks introduced by TFColor. TFColor now use reference counting as descendant of IFColor.
  • Added: Line drawing for TFPixmap class.
File size: 6.7 KB
Line 
1unit UGGraphics;
2
3{$mode delphi}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, Graphics;
9
10type
11 // Possible fixed color types:
12 // 0..1, 0..3, 0..15, Byte, Word, Cardinal, Int64, record RGB, record RGBA, class
13 // Bit level addressing -> bit addressable memory -> slowdown
14 // Color with dynamic size
15 // Color with dynamic number of channels
16 // Representing pallete
17
18 { TGBrush }
19
20 TGBrush<TGColor> = class
21 Color: TGColor;
22 Canvas: TObject; // TGCanvas<TGColor>;
23 end;
24
25 { TGPen }
26
27 TGPen<TGColor> = class
28 Position: TPoint;
29 Color: TGColor;
30 Canvas: TObject; // TGCanvas<TGColor>;
31 procedure MoveTo(Pos: TPoint);
32 procedure LineTo(Pos: TPoint);
33 end;
34
35 { TGCanvas }
36
37 TGCanvas<TGColor> = class
38 Bitmap: TObject; // TGPixmap<TGColor>;
39 Pen: TGPen<TGColor>;
40 Brush: TGBrush<TGColor>;
41 constructor Create;
42 destructor Destroy; override;
43 end;
44
45 { TGPixmap }
46
47 TGPixmap<TGColor> = class
48 public
49 type
50 TGConvertColor = function (Color: TGColor): TColor of object;
51 TGGetColor = function (Position: TPoint): TGColor of object;
52 protected
53 FData: PByte;
54 FSize: TPoint;
55 FCanvas: TGCanvas<TGColor>;
56 function GetPixel(X, Y: Integer): TGColor; virtual;
57 function GetSize: TPoint; virtual;
58 procedure SetPixel(X, Y: Integer; AValue: TGColor); virtual;
59 procedure SetSize(AValue: TPoint); virtual;
60 private
61 procedure CheckLimits(X, Y: Integer);
62 public
63 constructor Create;
64 destructor Destroy; override;
65 procedure PaintToCanvas(Canvas: TCanvas; ColorConvertFunc: TGConvertColor);
66 procedure Fill(Color: TGColor); overload;
67 procedure Fill(Func: TGGetColor); overload;
68 function GetDataSize: Int64; virtual;
69 property Canvas: TGCanvas<TGColor> read FCanvas;
70 property Pixels[X, Y: Integer]: TGColor read GetPixel write SetPixel;
71 property Size: TPoint read GetSize write SetSize;
72 end;
73
74{ TGPixmapBit }
75
76 TGPixmapBit<TGColor> = class(TGPixmap<TGColor>)
77 protected
78 function GetPixel(X, Y: Integer): TGColor; override;
79 procedure SetPixel(X, Y: Integer; AValue: TGColor); override;
80 private
81 FBitsPerPixel: Integer;
82 procedure BitMove(SourceBase: PByte; SourceOffset: Integer;
83 DestBase: PByte; DestOffset: Integer; Size: Integer);
84 function GetByteSize(BitSize: Integer): Integer;
85 procedure SetBitsPerPixel(AValue: Integer);
86 public
87 property BitsPerPixel: Integer read FBitsPerPixel write SetBitsPerPixel;
88 function GetDataSize: Int64; override;
89 end;
90
91
92implementation
93
94{ TGPixmap }
95
96function TGPixmap<TGColor>.GetPixel(X, Y: Integer): TGColor;
97begin
98 CheckLimits(X, Y);
99 Move(PByte(FData + (X + Y * FSize.X) * SizeOf(TGColor))^, Result, SizeOf(TGColor));
100end;
101
102procedure TGPixmap<TGColor>.SetPixel(X, Y: Integer; AValue: TGColor);
103begin
104 CheckLimits(X, Y);
105 Move(AValue, PByte(FData + (X + Y * FSize.X) * SizeOf(TGColor))^, SizeOf(TGColor));
106end;
107
108function TGPixmap<TGColor>.GetSize: TPoint;
109begin
110 Result := FSize;
111end;
112
113procedure TGPixmap<TGColor>.SetSize(AValue: TPoint);
114begin
115 if (FSize.X <> AValue.X) and (FSize.Y <> AValue.Y) then begin
116 FSize := AValue;
117 ReAllocMem(FData, FSize.X * FSize.Y * SizeOf(TGColor));
118 end;
119end;
120
121constructor TGPixmap<TGColor>.Create;
122begin
123 FCanvas := TGCanvas<TGColor>.Create;
124 FCanvas.Bitmap := Self;
125end;
126
127destructor TGPixmap<TGColor>.Destroy;
128begin
129 Size := Point(0, 0);
130 FreeAndNil(FCanvas);
131end;
132
133procedure TGPixmap<TGColor>.CheckLimits(X, Y: Integer);
134begin
135 if (X < 0) or (X >= FSize.X) or (Y < 0) or (Y >= FSize.Y) then
136 raise Exception.Create('Position out of range');
137end;
138
139procedure TGPixmap<TGColor>.Fill(Color: TGColor);
140var
141 X, Y: Integer;
142begin
143 for Y := 0 to FSize.Y - 1 do
144 for X := 0 to FSize.X - 1 do
145 Pixels[X, Y] := Color;
146end;
147
148procedure TGPixmap<TGColor>.Fill(Func: TGGetColor);
149var
150 X, Y: Integer;
151begin
152 for Y := 0 to FSize.Y - 1 do
153 for X := 0 to FSize.X - 1 do
154 Pixels[X, Y] := Func(Point(X, Y));
155end;
156
157procedure TGPixmap<TGColor>.PaintToCanvas(Canvas: TCanvas;
158 ColorConvertFunc: TGConvertColor);
159var
160 X, Y: Integer;
161begin
162 try
163 Canvas.Lock;
164 for Y := 0 to FSize.Y - 1 do
165 for X := 0 to FSize.X - 1 do begin
166 Canvas.Pixels[X, Y] := ColorConvertFunc(Pixels[X, Y]);
167 end;
168 finally
169 Canvas.Unlock;
170 end;
171end;
172
173function TGPixmap<TGColor>.GetDataSize: Int64;
174begin
175 Result := FSize.X * FSize.Y * SizeOf(TGColor);
176end;
177
178{ TGPen }
179
180procedure TGPen<TGColor>.MoveTo(Pos: TPoint);
181begin
182 Position := Pos;
183end;
184
185procedure TGPen<TGColor>.LineTo(Pos: TPoint);
186var
187 I: Integer;
188 Len: Integer;
189begin
190 Len := Trunc(Sqrt(Sqr(Position.X - Pos.X) + Sqr(Position.Y - Pos.Y)));
191 for I := 0 to Len - 1 do
192 ((Canvas as TGCanvas<TGColor>).Bitmap as TGPixmap<TGColor>).Pixels[Trunc(Position.X + I * (Pos.X - Position.X) / Len),
193 Trunc(Position.Y + I * (Pos.Y - Position.Y) / Len)] := Color;
194 Position := Pos;
195end;
196
197{ TGCanvas }
198
199constructor TGCanvas<TGCanvas>.Create;
200begin
201 Pen := TGPen<TGColor>.Create;
202 Pen.Canvas := Self;
203 Brush := TGBrush<TGColor>.Create;
204 Brush.Canvas := Self;
205end;
206
207destructor TGCanvas<TGCanvas>.Destroy;
208begin
209 FreeAndNil(Pen);
210 FreeAndNil(Brush);
211 inherited Destroy;
212end;
213
214{ TGPixmapBit }
215
216procedure TGPixmapBit<TGColor>.BitMove(SourceBase: PByte; SourceOffset: Integer;
217 DestBase: PByte; DestOffset: Integer; Size: Integer);
218var
219 Value: Byte;
220 Mask: Word;
221begin
222 if ((SourceOffset + Size) > 8) or ((DestOffset + Size) > 8) then
223 raise Exception.Create('Max. supported size for bit move is 8 bits.');
224 Mask := ((1 shl Size) - 1);
225 Value := (PByte(SourceBase)^ shr SourceOffset) and Mask;
226 DestBase^ := (DestBase^ and ($ff xor (Mask shl DestOffset))) or (Value shl DestOffset);
227end;
228
229function TGPixmapBit<TGColor>.GetPixel(X, Y: Integer): TGColor;
230var
231 Offset: Integer;
232begin
233 CheckLimits(X, Y);
234 Offset := (X + Y * FSize.X) * BitsPerPixel;
235 BitMove(FData + (Offset shr 3), Offset and 7, @Result, 0, BitsPerPixel);
236end;
237
238procedure TGPixmapBit<TGColor>.SetPixel(X, Y: Integer; AValue: TGColor);
239var
240 Offset: Integer;
241begin
242 CheckLimits(X, Y);
243 Offset := (X + Y * FSize.X) * BitsPerPixel;
244 BitMove(@AValue, 0, FData + (Offset shr 3), Offset and 7, BitsPerPixel);
245end;
246
247function TGPixmapBit<TGColor>.GetDataSize: Int64;
248begin
249 Result := GetByteSize(FSize.X * FSize.Y * BitsPerPixel);
250end;
251
252function TGPixmapBit<TGColor>.GetByteSize(BitSize: Integer): Integer;
253begin
254 Result := (((BitSize - 1) or 7) + 1) shr 3;
255end;
256
257procedure TGPixmapBit<TGColor>.SetBitsPerPixel(AValue: Integer);
258begin
259 if FBitsPerPixel <> AValue then begin
260 FBitsPerPixel := AValue;
261 end;
262end;
263
264end.
265
Note: See TracBrowser for help on using the repository browser.