diff options
author | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2007-12-02 18:12:30 +0000 |
---|---|---|
committer | graemeg <graemeg@ae50a9b5-8222-0410-bf8d-8a13f76226bf> | 2007-12-02 18:12:30 +0000 |
commit | b98125eb588b85ce05fafd07f6e48413187bdba1 (patch) | |
tree | 5fbf4d8df610dc03fe6f88dfd3bd401f0d35c604 /src/corelib | |
parent | 51b57f100e50eb56b87641efb7b0cb29f8340407 (diff) | |
download | fpGUI-b98125eb588b85ce05fafd07f6e48413187bdba1.tar.xz |
* Implemented the Wu Anti-Aliased line drawing algorithm. Soon the canvas DrawLine will start using it.
* Created a very quick and simple Wu Line example.
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/gfx_wuline.pas | 167 | ||||
-rw-r--r-- | src/corelib/x11/fpgfx_package.lpk | 6 | ||||
-rw-r--r-- | src/corelib/x11/fpgfx_package.pas | 2 |
3 files changed, 173 insertions, 2 deletions
diff --git a/src/corelib/gfx_wuline.pas b/src/corelib/gfx_wuline.pas new file mode 100644 index 00000000..ce5c403b --- /dev/null +++ b/src/corelib/gfx_wuline.pas @@ -0,0 +1,167 @@ +{ + fpGUI - Free Pascal GUI Library + + Copyright (C) 2006 - 2007 See the file AUTHORS.txt, included in this + distribution, for details of the copyright. + + See the file COPYING.modifiedLGPL, included in this distribution, + for details about redistributing fpGUI. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + Description: + + A Object Pascal implemenation of Wu Anti-Aliased Lines. + For details about the algorithm have a look at: + http://freespace.virgin.net/hugo.elias/graphics/x_wuline.htm + Here is an implementation in C++ + http://www.codeproject.com/gdi/antialias.asp +} +unit gfx_wuline; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, gfxbase, fpgfx; + + +procedure WuLine(ACanvas: TfpgCanvas; Point1, Point2: TPoint; AColor: TfpgColor); +procedure DrawWuCircle(Canvas: TfpgCanvas; x, y, r: integer; AColor: TfpgColor); + + +implementation + + +type + // to get access to Protected fields + TCanvasHack = class(TfpgCanvas); + + +// Blend a pixel with the current colour +procedure AlphaBlendPixel(ACanvas: TfpgCanvas; X, Y: integer; R, G, B: word; ARatio: Double); +var + LBack, LNew: TRGBTriple; + LMinusRatio: Double; +begin + if (X < 0) or (X > TCanvasHack(ACanvas).FWindow.Width - 1) or (Y < 0) or + (Y > TCanvasHack(ACanvas).FWindow.Height - 1) then + Exit; // clipping + + LMinusRatio := 1 - ARatio; + LBack := fpgColorToRGBTriple(ACanvas.Pixels[X, Y]); + LNew.Blue := round(B*ARatio + LBack.Blue*LMinusRatio); + LNew.Green := round(G*ARatio + LBack.Green*LMinusRatio); + LNew.Red := round(R*ARatio + LBack.Red*LMinusRatio); + ACanvas.Pixels[X, Y] := RGBTripleTofpgColor(LNew); +end; + +// Draw a anti-aliased line +procedure WuLine(ACanvas: TfpgCanvas; Point1, Point2: TPoint; AColor: TfpgColor); +var + deltax, deltay, loop, start, finish: integer; + dx, dy, dydx: single; // fractional parts + LR, LG, LB: word; + x1, x2, y1, y2: integer; +begin + x1 := Point1.X; + y1 := Point1.Y; + x2 := Point2.X; + y2 := Point2.Y; + deltax := abs(x2 - x1); // Calculate deltax and deltay for initialisation + deltay := abs(y2 - y1); + + if (deltax = 0) or (deltay = 0) then // straight lines + begin + ACanvas.SetColor(AColor); + ACanvas.DrawLine(x1, y1, x2, y2); + Exit; //==> + end; + LR := fpgGetRed(AColor); + LG := fpgGetGreen(AColor); + LB := fpgGetBlue(AColor); + if deltax > deltay then + begin // horizontal or vertical + if y2 > y1 then // determine rise and run + dydx := -(deltay / deltax) + else + dydx := deltay / deltax; + + if x2 < x1 then + begin + start := x2; // right to left + finish := x1; + dy := y2; + end + else + begin + start := x1; // left to right + finish := x2; + dy := y1; + dydx := -dydx; // inverse slope + end; + + for loop := start to finish do + begin + AlphaBlendPixel(ACanvas, loop, trunc(dy), LR, LG, LB, 1 - frac(dy)); + AlphaBlendPixel(ACanvas, loop, trunc(dy) + 1, LR, LG, LB, frac(dy)); + dy := dy + dydx; // next point + end; + end + else + begin + if x2 > x1 then // determine rise and run + dydx := -(deltax / deltay) + else + dydx := deltax / deltay; + + if y2 < y1 then + begin + start := y2; // right to left + finish := y1; + dx := x2; + end + else + begin + start := y1; // left to right + finish := y2; + dx := x1; + dydx := -dydx; // inverse slope + end; + + for loop := start to finish do + begin + AlphaBlendPixel(ACanvas, trunc(dx), loop, LR, LG, LB, 1 - frac(dx)); + AlphaBlendPixel(ACanvas, trunc(dx) + 1, loop, LR, LG, LB, frac(dx)); + dx := dx + dydx; // next point + end; + end; +end; + +// A very basic circle implementation. Not to pretty, but it works. +procedure DrawWuCircle(Canvas: TfpgCanvas; x, y, r: integer; AColor: TfpgColor); +var + x1, y1, x2, y2: integer; + dt: integer; + theta: integer; +begin + theta := 0; + dt := 4; + while theta < 360 do + begin + x1 := round( r*cos(theta*pi/180.0)+x); + y1 := round(-r*sin(theta*pi/180.0)+y); + + x2 := round( r*cos((theta+dt)*pi/180.0)+x); + y2 := round(-r*sin((theta+dt)*pi/180.0)+y); + + WuLine(Canvas, Point(x1, y1), Point(x2, y2), AColor); + theta := theta + dt; + end; +end; + +end. + diff --git a/src/corelib/x11/fpgfx_package.lpk b/src/corelib/x11/fpgfx_package.lpk index 49ac5b3a..6536d8e5 100644 --- a/src/corelib/x11/fpgfx_package.lpk +++ b/src/corelib/x11/fpgfx_package.lpk @@ -24,7 +24,7 @@ <License Value="Modified LGPL "/> <Version Minor="5" Release="1"/> - <Files Count="17"> + <Files Count="18"> <Item1> <Filename Value="x11_xft.pas"/> <UnitName Value="x11_xft"/> @@ -93,6 +93,10 @@ <Filename Value="../gfx_command_intf.pas"/> <UnitName Value="gfx_command_intf"/> </Item17> + <Item18> + <Filename Value="../gfx_wuline.pas"/> + <UnitName Value="gfx_wuline"/> + </Item18> </Files> <LazDoc Paths="../../../docs/xml/corelib/;../../../docs/xml/corelib/x11/;../../../docs/xml/corelib/gdi/"/> <RequiredPkgs Count="1"> diff --git a/src/corelib/x11/fpgfx_package.pas b/src/corelib/x11/fpgfx_package.pas index d3ec9058..34e24d16 100644 --- a/src/corelib/x11/fpgfx_package.pas +++ b/src/corelib/x11/fpgfx_package.pas @@ -10,7 +10,7 @@ uses x11_xft, x11_keyconv, gfxbase, gfx_x11, fpgfx, gfx_stdimages, gfx_imgfmt_bmp, gfx_widget, gfx_UTF8utils, gfx_extinterpolation, gfx_cmdlineparams, gfx_clipboard, gfx_utils, gfx_popupwindow, gfx_impl, gfx_strings, - gfx_command_intf; + gfx_command_intf, gfx_wuline; implementation |