Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/FireMonkey/Runtime    [ Add a report in this area ]  
Report #:  119515   Status: Closed
[Android] [ldpi] TCanvas.DrawLine issues with ldpi device when Canvas.Stroke.Thickness is 1.0
Project:  Delphi Build #:  19.0.13476.4176
Version:    19.0 Submitted By:   Roman Yankovsky
Report Type:  Basic functionality failure Date Reported:  10/4/2013 9:22:21 AM
Severity:    Infrequently encountered problem Last Updated: 1/29/2014 6:16:41 AM
Platform:    Google mobile OS Internal Tracking #:   44100
Resolution: As Designed (Resolution Comments) Resolved in Build: : None
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: None
Description
[Android] [ldpi] TCanvas.DrawLine issues with ldpi device when Canvas.Stroke.Thickness is 1.0

TCanvas.DrawLine works fine when compiling to Windows platform and doesn't work occasionally on Android.

See attached screenshots.
Steps to Reproduce:
Create new project and put the following code into form's OnPaint event handler:
-----------
procedure TForm1.FormPaint(Sender: TObject; Canvas: TCanvas;
  const ARect: TRectF);
var
  I: Integer;
  CellSize: Single;
begin
  CellSize := ClientHeight / 8;
  if Canvas.BeginScene then
    try
      Canvas.Stroke.Thickness := 1;
      Canvas.Stroke.Kind := TBrushKind.bkSolid;
      Canvas.Fill.Color := TAlphaColorRec.Black;
      Canvas.Fill.Kind := TBrushKind.bkSolid;

      Canvas.DrawRectSides(RectF(ClientWidth-CellSize*10, 0, ClientWidth, ClientHeight), 0, 0, AllCorners, 1, AllSides);

      for I := 1 to 9 do
        Canvas.DrawLine(PointF(ClientWidth-I*CellSize, 0), PointF(ClientWidth-I*CellSize, ClientHeight), 1);

      for I := 1 to 7 do
        Canvas.DrawLine(PointF(ClientWidth-CellSize*10, ClientHeight-I*CellSize), PointF(ClientWidth, ClientHeight-I*CellSize), 1);
    finally
      Canvas.EndScene;
    end;
end;
-----------
Workarounds
None
Attachment
119515.zip
Comments

Tomohiro Takahashi at 10/4/2013 7:11:53 PM -
>       Canvas.Stroke.Thickness := 1;
I can not reproduce your issue, but I can see that thickness of some lines are different from other lines on screen.
I think this issue is related to Density of Pixel(ppi) in a device/screen. So, what Android device(model name, OS version) do you use?

and, what about using 1.5 as below?
>       Canvas.Stroke.Thickness := 1.5;

Roman Yankovsky at 10/5/2013 1:29:36 AM -
Maybe it worth creating other report about thickness of lines on Android.

Tomohiro Takahashi at 10/6/2013 6:02:58 PM -
no need to put new QC report.
I opened this report, editing the [Ttitle].

Roman Yankovsky at 10/5/2013 12:57:17 AM -
> what about using 1.5 as below?

When I change Thickness to 1.5, it looks much better. But some lines seem to be different.

Screenshot: http://s6.hostingkartinok.com/uploads/images/2013/10/bd2a977da7f0b9f4285244a450fed4b1.png

> So, what Android device(model name, OS version) do you use?

Texet TM-7025
Android 4.0

Alysson Cunha at 10/7/2013 4:45:54 AM -
1.5 is not a good value, because when the logic-to-pixel process occur, it will "multiply" 1.5 by the screen scale... 1.5 * 0.75 = 1,125 ... That is not a rounded pixel.

Tomohiro Takahashi at 10/5/2013 4:52:02 AM -
Roman-san

> Texet TM-7025
On your device, what Scale does this code show, for example 0.75 etc...?

--------
uses FMX.Platform;

procedure TForm1.Button1Click(Sender: TObject);
var
  ws: IFMXWindowService;
begin
  ws := TPlatformServices.Current.GetPlatformService(IFMXWindowService) as IFMXWindowService;
  ShowMessage(FloatToStr(ws.GetWindowScale(Self)));
end;
--------

Roman Yankovsky at 10/5/2013 5:09:00 AM -
This code shows 0.75

Roman Yankovsky at 10/6/2013 11:48:22 PM -
Just want to add a few words.
As a result, some standard FM components don't work well (e.g. TRectangle), when they use Stroke.Thickness=1.0

Tomohiro Takahashi at 10/6/2013 11:56:46 PM -
Does your issue occur only with the ldpi device?
What about other devices, for example Nexus 7(2013) etc...?

Roman Yankovsky at 10/7/2013 11:02:46 PM -
Yes, it seems to be an "ldpi only" issue

Alysson Cunha at 10/7/2013 4:47:48 AM -
Try this, and tell us if it works:

-------------

function TForm1.RoundLogicPointsToMatchPixel(const LogicPoints: Single; const AtLeastOnePixel: Boolean = False): Single;
var
  ws: IFMXWindowService;
  ScreenScale, Pixels: Single;
begin
  ws := TPlatformServices.Current.GetPlatformService(IFMXWindowService) as IFMXWindowService;
  ScreenScale := ws.GetWindowScale(Self);

  Pixels := Round(LogicPoints * ScreenScale);  //  Maybe you will want to use Ceil or Trunc instead of Round

  if (Pixels < 1) and (AtLeastOnePixel) then
    Pixels := 1.0;

  Result := Pixels / ScreenScale;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
TheThicknessToUse: Single;
begin
  TheThicknessToUse := RoundLogicPointsToMatchPixel(1.0, True);

// Use "TheThicknessToUse" on the Stroke
end;


--------

This will transform the logic dp unit to match a rounded pixel size.
Maybe you will need also to round the Y value before calling DrawLine

Roman Yankovsky at 10/7/2013 11:01:47 PM -
It works fine for me.
Actually my solution was shifting Y value by the half of line's thickness (http://roman.yankovsky.me/?p=1018). But your approach looks better. Thank you.

Sfirschi Mihaela at 1/29/2014 6:07:10 AM -
This is a specific scaling behavior on ldpi devices, which requires user to write scale-aware code. Canvas cannot automatically figure out what behavior is expected and readjust widths or positions, so solutions already discussed in QC should be used. From canvas perspective, it is working as expected considering device scale in question.

Server Response from: ETNACODE01