TAntiAliasCanvas.LineTo with IPenWidth=2 doesn't draw a line

TeeChart VCL for Borland/CodeGear/Embarcadero RAD Studio, Delphi and C++ Builder.
Post Reply
Rob62
Newbie
Newbie
Posts: 4
Joined: Mon Feb 20, 2012 12:00 am

TAntiAliasCanvas.LineTo with IPenWidth=2 doesn't draw a line

Post by Rob62 » Thu Feb 23, 2012 10:21 pm

I'm using Delphi5 Pro with TeeChart Pro 2011 Full Source Code.

Here are the relevant settings when calling TAntiAliasCanvas.LineTo function:

IAlias:=True;
Current.x:=830;
Current.y:=255;
x:=831;
y:=256;
Pen.Style:=psSolid;
LinePen.Width:=2;
Pen.Width:=2;
IPenWidth:=2;
IPenSmallDot:= False;

When drawing an angled line then TAntiAliasCanvas.LineTo does not appear to be drawing any line at all.
I find that the recursive calls to "LineTo" in the "DoLineTo" sub-procedure just complete a few "MoveTo" procedures then exit.

The code appears to be incomplete:

I can see that "IPenWidth" current value is saved to "Old" ("Old:=IPenWidth" on line 984) and then later reset ("IPenWidth:=Old"),
however ""IPenWidth" itself is never set to any other value in the block of code between.

Were "IPenWidth" to be set to "1" in this block of code then the recursive calls to this "LineTo" function would actually perform antialiasing as all antialiasing code in this LineTo function is restricted to being used when "IPenWidth=1" (See "if IPenWidth>1 then" on line 981).

Otherwise all that occurs are "MoveTo" procedures until the recursion completes and the LineTo procedure exits on supposed completion of the line ...

Rob62
Newbie
Newbie
Posts: 4
Joined: Mon Feb 20, 2012 12:00 am

Re: TAntiAliasCanvas.LineTo with IPenWidth=2 doesn't draw a line

Post by Rob62 » Fri Feb 24, 2012 12:32 am

I've got it working. Here are proposed changes to the DoLineTo sub-procedure of the TAntiAliasCanvas.SetAntiAlias procedure:

Code: Select all

    if IPenWidth>1 then
    begin

      Old:=IPenWidth;
      Pen.Width:=IPenWidth;
      IPenColor:=ColorToRGB(Pen.Color);

      OldP:=Current;

      for t:=0 to Old-1 do
      begin
        IAlias:=(t=0) or (t=Old-1);

        tmp:=(Old div 2)-t;

        if Abs(dy)>Abs(dx) then
        begin
          MoveTo(OldP.X-tmp,OldP.Y);
          if (IPenWidth>1) then
          begin
            if IEnter<>1 then  // TV52015427
            begin
              IEnter:=1;

              //20120224
              //Rob's alteration
              IPenWidth := 1;
              Pen.Width := IPenWidth;

              LineTo(X-tmp+1,Y);
            end;
          end;
          MoveTo(X-tmp,Y);
        end
        else
        begin
          MoveTo(OldP.X,OldP.Y-tmp);
          if (IPenWidth>1) then
          begin
            if Ienter<>1 then
            begin
              IEnter:=1;

              //////////////////////////
              //20120224
              //Rob's alteration
              IPenWidth := 1;
              Pen.Width := IPenWidth;
              //////////////////////////

              LineTo(X,Y);
            end;
          end;
          MoveTo(X-tmp-1,Y);
        end;

        //////////////////////////
        //Rob's alteration
        IEnter:=0;
        IPenWidth:=Old;
        Pen.Width:=IPenWidth;
        //////////////////////////
      end;

      //////////////////////////
      //20120224
      //Rob's alteration
      {IEnter:=0;
      IPenWidth:=Old;
      Pen.Width:=IPenWidth;}
      //////////////////////////
      
      IAlias:=True;
    end

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: TAntiAliasCanvas.LineTo with IPenWidth=2 doesn't draw a line

Post by Yeray » Tue Feb 28, 2012 11:19 am

Hi Rob,

This is a known bug already present in the defect list to be fixed asap (TV52015964).
Note it is related to TV52015427, and actually your proposal breaks it again. But thanks anyway!
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Rob62
Newbie
Newbie
Posts: 4
Joined: Mon Feb 20, 2012 12:00 am

Re: TAntiAliasCanvas.LineTo with IPenWidth=2 doesn't draw a line

Post by Rob62 » Tue Feb 28, 2012 11:44 am

No worries,

Since you are going to have a look at this procedure at some point,
here are some more fixes in same procedure (to prevent a "ghosting effect" being drawn at chart.height-2 or chart.width-2 when line is attempted to be drawn beyond chart height or width and then antialiased):

...
///////////////////////////////////////////////////////////////////////////////
//20120226
//Rob's alteration
//we otherwise create an antialiased "ghost" line at the bottom of the chart
if (tmpYt >= 0)and(tmpYt <= IHeight) then
begin
{if tmpYt < 0 then tmpYt:=0;
if tmpYt > IHeight then tmpYt:=IHeight-2;}
///////////////////////////////////////////////////////////////////////////////

dist:=yt-tmpYt;
oneDist:=1-dist;

BlendColor1(xs, tmpYt);
BlendColor2(xs, tmpYt+1);

///////////////////////////////////////////////////////////////////////////////
//20120226
//Rob's alteration
end;
///////////////////////////////////////////////////////////////////////////////
Inc(xs);
...

and then further down:

...
///////////////////////////////////////////////////////////////////////////////
//20120226
//Rob's alteration
//we otherwise create an antialiased "ghost" line at the bottom of the chart
if (tmpXt >= 0)and(tmpXt <= IWidth) then
begin
{if tmpXt < 0 then tmpXt:=0;
if tmpXt > IWidth then tmpXt:=IWidth-1;}
///////////////////////////////////////////////////////////////////////////////

dist:=xt-tmpXt;
oneDist:=1-dist;

//if (PointInPolygon(TeePoint(tmpXt,ys),ICurrentClipPolygon)) then
begin // TV52015427
BlendColor1(tmpXt,ys);
BlendColor2(tmpXt+1, ys);
end;

///////////////////////////////////////////////////////////////////////////////
//20120226
//Rob's alteration
end;
///////////////////////////////////////////////////////////////////////////////
Inc(ys);
...

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: TAntiAliasCanvas.LineTo with IPenWidth=2 doesn't draw a line

Post by Yeray » Tue Feb 28, 2012 12:14 pm

Thank you, Rob.
I've added these proposals to the TV52015964 description to be revised with it.
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Rob62
Newbie
Newbie
Posts: 4
Joined: Mon Feb 20, 2012 12:00 am

Re: TAntiAliasCanvas.LineTo with IPenWidth=2 doesn't draw a line

Post by Rob62 » Thu Mar 01, 2012 10:40 pm

I've discovered the issues related to Canvas.ClipRectangle in TeeAntiAlias:

I found that "TeeAntiAlias.LineTo" was drawing lines beyond the bounds of "Rect" in ClipRectangle.

I'm sure there is going to be a better way of doing this, but the best I could do to overcome this issue was to place "IClipRect : TRect" in TAntiAliasCanvas as a private variable,
override "Create","ClipRectangle" and "UnclipRectangle", then apply IClipRect.Left,IClipRect.Top,IClipRect.Right and IClipRect.Bottom to all conditions where extreme bounds were evaluated as needed.

Here are the constructor and procedures overridden:

////////////////////////////////////////////
//20120302
//Rob's Alteration
Constructor TAntiAliasCanvas.Create;
begin
inherited Create;

//Initialize rect to extreme bounds so that "greater than" and "less than" are always accurate, even when IClipRect not "set"
IClipRect := Rect( low(integer),low(integer),high(integer),high(integer) );
end;

procedure TAntiAliasCanvas.ClipRectangle(const Rect:TRect);
begin
inherited ClipRectangle(Rect);

IClipRect := Rect;

//Not implemented yet in RoundRect procedure
{IRoundX := low(integer);
IRoundY := low(integer);}
end;

procedure TAntiAliasCanvas.ClipRectangle(const Rect:TRect; RoundX,RoundY:Integer);
begin
inherited ClipRectangle(Rect,RoundX,RoundY);

IClipRect := Rect;

//Not implemented yet in RoundRect procedure
{IRoundX := RoundX;
IRoundY := RoundY;}
end;

procedure TAntiAliasCanvas.UnclipRectangle;
begin
//Initialize rect to extreme bounds so that "greater than" and "less than" are always accurate, even when IClipRect not "set"
IClipRect := Rect( low(integer),low(integer),high(integer),high(integer) );

//Not implemented yet in RoundRect procedure
{IRoundX := low(integer);
IRoundY := low(integer);}

inherited UnclipRectangle;
end;
////////////////////////////////////////////

Yeray
Site Admin
Site Admin
Posts: 9612
Joined: Tue Dec 05, 2006 12:00 am
Location: Girona, Catalonia
Contact:

Re: TAntiAliasCanvas.LineTo with IPenWidth=2 doesn't draw a line

Post by Yeray » Tue Mar 06, 2012 12:26 pm

Thanks again for the feedback, Rob.
Best Regards,
ImageYeray Alonso
Development & Support
Steema Software
Av. Montilivi 33, 17003 Girona, Catalonia (SP)
Image Image Image Image Image Image Please read our Bug Fixing Policy

Post Reply