Page 1 of 1

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

Posted: Thu Feb 23, 2012 10:21 pm
by 16561618
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 ...

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

Posted: Fri Feb 24, 2012 12:32 am
by 16561618
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

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

Posted: Tue Feb 28, 2012 11:19 am
by yeray
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!

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

Posted: Tue Feb 28, 2012 11:44 am
by 16561618
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);
...

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

Posted: Tue Feb 28, 2012 12:14 pm
by yeray
Thank you, Rob.
I've added these proposals to the TV52015964 description to be revised with it.

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

Posted: Thu Mar 01, 2012 10:40 pm
by 16561618
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;
////////////////////////////////////////////

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

Posted: Tue Mar 06, 2012 12:26 pm
by yeray
Thanks again for the feedback, Rob.