Search code examples
firemonkeyc++builder

Why is FMX's DrawLine() function not working properly?


I'm using C++Builder 11 Community Edition on a Windows 10 PC.

I'm trying to draw lines. When I make a VCL app, it all works fine, but I want to use FMX to take advantage of the GPU.

The FMX code is giving me blurred lines with Stroke->Thickness set to 1.0. I need the line thickness to be 1 pixel wide. This will eventually be a program that draws a bar graph.

This is the VCL code:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Canvas->Pen->Width = 1;
    Canvas->Pen->Color = (Graphics::TColor) clBlack;

    Canvas->MoveTo(100,100);
    Canvas->LineTo(500,100);
    Canvas->MoveTo(100,101);
    Canvas->LineTo(300,101);
    Canvas->MoveTo(100,102);
    Canvas->LineTo(500,102);
}

VCL lines with windows magnifier

This is the FMX code:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
    Canvas->BeginScene();
//  Canvas->Clear(TAlphaColorRec::Blue);

    Canvas->Stroke->Color = TAlphaColorRec::Black;
    Canvas->Stroke->Thickness = 1.0;
    Canvas->DrawLine(TPointF(100,100), TPointF(500,100), 1.0);
    Canvas->DrawLine(TPointF(100,101), TPointF(300,101), 1.0);
    Canvas->DrawLine(TPointF(100,102), TPointF(500,102), 1.0);

    Canvas->EndScene();
}

FMX lines with windows magnifier

I've tried different opacities and line thicknesses. If I repeat the line draw function 10 times, it looks better, but this is obviously not the way to go!

Can anybody help with this?


Solution

  • The solution is to offset all coordinates by half a pixel so that it's drawing from the center of the pixel rather than at a pixel boundary. This ensures that the anti-aliased graphics doesn't blend the pixels over a boundary. You could also set the Form's Quality property to HighPerformance to disable anti-aliasing, but that may negatively affect graphics quality on other parts of the form where you may want to keep anti-aliasing.

    The following works with Quality set to HighQuality

    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
        Canvas->BeginScene();
    //  Canvas->Clear(TAlphaColorRec::Blue);
    
        Canvas->Stroke->Color = TAlphaColorRec::Black;
        Canvas->Stroke->Thickness = 1.0;
        Canvas->DrawLine(TPointF(100.5,100.5), TPointF(500.5,100.5), 1.0);
        Canvas->DrawLine(TPointF(100.5,101.5), TPointF(300.5,101.5), 1.0);
        Canvas->DrawLine(TPointF(100.5,102.5), TPointF(500.5,102.5), 1.0);
    
        Canvas->EndScene();
    }