Forum > LCL

Drawing a rectangle

(1/2) > >>

Zaxxon:
Why the difference in drawing?
Using Canvas.Rectangle vs Canvas.MoveTo / Canvas.LineTo.
Same coordinates are used.

Handoko:
Not only slow but TCanvas drawing often gives you weird result. Is it a bug? I don't know but I already knew this weird issue long ago, no one care to fix it. Maybe it is done by design.

For example below is the code for drawing rectangles, both give different results and both are wrong:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.Button1Click(Sender: TObject);begin  // Draw first rectangle  Canvas.Rectangle(10,10,12,12);  // delta X = 2, delta Y = 2   //Draw second rectangle  Canvas.MoveTo(10,15);  Canvas.LineTo(12,15);  // delta X = 2  Canvas.LineTo(12,17);  // delta Y = 2  Canvas.LineTo(10,17);  Canvas.LineTo(10,15);end;
If I remember correctly, some call it last pixel missing issue.

howardpc:
It is not a bug.
The LCL graphics routines are nearly all based on rectangular frames. In 2-D, how do you count and identify pixels? In a line of pixels numbered 0, 1, 2 etc. from left to right the LineTo/MoveTo routines use the numbered pixels as expected.
However, the rectangle-based routines (Rectangle, FrameRect, FillRect, Frame, Ellipse, etc.) regard the coordinate given as the rightmost pixel to be the "edge" of the graphic, and the graphic is drawn up to that edge.
If you add an OnPaint handler to your example, and fill out the skeleton code Lazarus provides as follows you will perhaps get a feel for the routines. Uncomment the commented lines one at a time to see the effect.

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.FormPaint(Sender: TObject);begin  Canvas.Pen.Color := clBlack;  Canvas.Brush.Color := clWhite;   //Canvas.Rectangle(56,321,56,321);   // this obviously does nothing  Canvas.Rectangle(56,321,57,322);   // this also does nothing  //Canvas.Rectangle(56,321,58,323); // this paints a single pixel  //Canvas.Rectangle(56,321,59,324); // this paints the smallest framed square possible  //Canvas.Rectangle(56,321,60,325); // this paints a slightly larger square  //Canvas.Rectangle(56,321,61,326); // etc.end;

winni:
Hi !

To make it clear:

This draws a line of 101 Pixels:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- Canvas.MoveTo(100,y); Canvas.LineTo(200,y);
But this draws a rectangle with a horizontal  width of 100:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---canvas.rectangle (100,y1,200,y2);

Winni

Handoko:
Thanks howardpc for the explanation.

But that does not explain why we can't get a good rectangle even if the delta x > 2 and delta y > 2. You always get a missing pixel. Also how will you explain the missing pixel of:

Canvas.MoveTo(12,15);
Canvas.LineTo(12,17);
Canvas.LineTo(10,17);

Even if one can explain it, that still against the rule of POLA:
https://en.wikipedia.org/wiki/Principle_of_least_astonishment

The best thing to do is avoid using TCanvas drawing feature, use OpenGL or other graphics engine. At least BASIC, which I learned when I was a kid, does not have this problem.