View Issue Details

IDProjectCategoryView StatusLast Update
0035279PackagesPackagespublic2020-11-23 12:17
ReporterAndrea Mauri Assigned ToDmitry Boyarintsev  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionreopened 
PlatformMacOSmacOS 
Product Version2.1 (SVN) 
Summary0035279: VirtualTreeView rendering on Cocoa
DescriptionVirtualTreeView is not rendering well on MacOS (Cocoa). Even changing DoubleBuffered property. Both fonts, images and directly drawing on canvas.
Steps To ReproduceYou can check Online Package Manager that uses VirtualTreeView.
Additional InformationMaybe related to HiDPI. Seems to work on Linux and Windows, I have not tested on HiDPI monitor on Linux and Windows.
TagsNo tags attached.
Fixed in Revisionr61618 63695
LazTarget-
WidgetsetCocoa
Attached Files

Activities

Andrea Mauri

2019-03-26 08:37

reporter  

Trevor Roydhouse

2019-12-07 05:41

reporter   ~0119672

Seems to be OK in Lazarus trunk r61775M - see attached image

Juha Manninen

2019-12-12 13:23

developer   ~0119792

Most likely fixed with r61618. Resolving.

Andrea Mauri

2019-12-13 11:19

reporter   ~0119813

On my mac it is better but not well defined as the lazarus editor fonts.
Rev 62382. See attached image. Am I doing something wrong?

Wallaby

2020-08-05 04:56

reporter   ~0124573

Not sure if this is the same or different issue, but VirtualTreeView draws itself with blurry fonts on macOS Retina screens.

Everything is OK with Windows even on high DPI, but on MacOS the fonts are blurry on Retina. Non-Retina screens are OK.

I have attached a screen shot.
Ifjvulm.png (214,616 bytes)   
Ifjvulm.png (214,616 bytes)   

Trevor Roydhouse

2020-08-05 10:12

reporter   ~0124575

OK, my screen is non-retina (Mac mini + Benq 24" LCD).

Dmitry Boyarintsev

2020-08-07 06:55

developer   ~0124639

proposed patch. (it's hacky but works)
vtvretina.diff (6,044 bytes)   
Index: laz.virtualtrees.pas
===================================================================
--- laz.virtualtrees.pas	(revision 63684)
+++ laz.virtualtrees.pas	(working copy)
@@ -60,6 +60,10 @@
 {$I laz.vtconfig.inc}
 
 uses
+  {$ifdef LCLCocoa}
+  MacOSAll, // hack: low-level access to Cocoa drawins is going to be used
+            //       in order to support Cocoa HighDPI implementation
+  {$endif}
   {$ifdef Windows}
   Windows,
   ActiveX,
@@ -83,6 +87,12 @@
   SysUtils, Classes, Graphics, Controls, Forms, ImgList, StdCtrls, Menus, Printers,
   SyncObjs,  // Thread support
   Clipbrd // Clipboard support
+  {$ifdef LCLCocoa}
+  ,CocoaGDIObjects // hack: while using buffered drawing, multiply the context
+                   //       by the retina scale to achieve the needed scale for Retina
+                   //       Ideally - not to use Buffered. but Unbuffered drawing
+                   //       seems to need a fix
+  {$endif}
   {$ifdef ThemeSupport}
   , Themes , TmSchema
   {$endif ThemeSupport}
@@ -90,6 +100,14 @@
   , oleacc // for MSAA IAccessible support
   {$endif};
 
+{$ifdef LCLCocoa}
+// WideChar is defined in MacOSAll. This is causing collission
+// with System.WideChar, which is used by the unit below.
+// Redeclearing the type.
+type
+  WideChar = System.WideChar;
+{$endif}
+
 const
   {$I laz.lclconstants.inc}
 
@@ -9210,6 +9228,9 @@
 var
   VisibleFixedWidth: Integer;
   RTLOffset: Integer;
+  {$ifdef LCLCocoa}
+  sc : Double;
+  {$endif}
 
   procedure PaintFixedArea;
   
@@ -9226,6 +9247,15 @@
   begin
     FHeaderBitmap.Width := Max(Right, R.Right - R.Left);
     FHeaderBitmap.Height := Bottom;
+    {$ifdef LCLCocoa}
+    if Assigned(Header) and Assigned(Header.TreeView) then
+      sc := Header.Treeview.GetCanvasScaleFactor
+    else
+      sc := 1.0;
+    FHeaderBitmap.Width := Round(FHeaderBitmap.Width * sc);
+    FHeaderBitmap.Height := Round(FHeaderBitmap.Height * sc);
+    CGContextScaleCTM(TCocoaBitmapContext(FHeaderBitmap.Canvas.Handle).CGContext, sc, sc);
+    {$endif}
   end;
 
   VisibleFixedWidth := GetVisibleFixedWidth;
@@ -9247,10 +9277,18 @@
   // In case of right-to-left directionality we paint the fixed part last.
   if RTLOffset <> 0 then
     PaintFixedArea;
-  
+
   // Blit the result to target.
   with TWithSafeRect(R) do
+    {$ifdef LCLCocoa}
+    StretchBlt(DC, Left, Top, Right - Left, Bottom - Top,
+      FHeaderBitmap.Canvas.Handle,
+      Left, Top,
+      FHeaderBitmap.Width, FHeaderBitmap.Height,
+      SRCCOPY);
+    {$else}
     BitBlt(DC, Left, Top, Right - Left, Bottom - Top, FHeaderBitmap.Canvas.Handle, Left, Top, SRCCOPY);
+    {$endif}
 end;
 
 //----------------------------------------------------------------------------------------------------------------------
@@ -30600,7 +30638,17 @@
   CellIsInLastColumn: Boolean;
   ColumnIsFixed: Boolean;
 
+  {$ifdef LCLCocoa}
+  sc: Double; // the retina scale. 1.0 for no-retina
+  cg: CGContextRef; // tracking the Context of Bitmap
+  cglast: CGContextRef; // the last Context of Bitmap.
+                        // The scale is applied only when the context changes
+  {$endif}
 begin
+  {$ifdef LCLCocoa}
+  cglast := nil;
+  sc := GetCanvasScaleFactor;
+  {$endif}
   {$ifdef DEBUG_VTV}Logger.EnterMethod([lcPaint],'PaintTree');{$endif}
   {$ifdef DEBUG_VTV}Logger.Send([lcPaint, lcHeaderOffset],'Window',Window);{$endif}
   {$ifdef DEBUG_VTV}Logger.Send([lcPaint, lcHeaderOffset],'Target',Target);{$endif}
@@ -30643,7 +30691,12 @@
         else
           NodeBitmap.PixelFormat := PixelFormat;
 
+        {$ifdef LCLCocoa}
+        NodeBitmap.Width := Round(PaintWidth*sc);
+        cg := TCocoaBitmapContext(NodeBitmap.Canvas.Handle).CGContext;
+        {$else}
         NodeBitmap.Width := PaintWidth;
+        {$endif}
 
         // Make sure the buffer bitmap and target bitmap use the same transformation mode.
         {$ifndef Gtk}
@@ -30761,8 +30814,18 @@
                 begin
                   if Height <> PaintInfo.Node.NodeHeight then
                   begin
-                    // Avoid that the VCL copies the bitmap while changing its height.                    
+                    // Avoid that the VCL copies the bitmap while changing its height.
+                    {$ifdef LCLCocoa}
+                    Height := Round(PaintInfo.Node.NodeHeight * sc);
+                    cg := TCocoaBitmapContext(NodeBitmap.Canvas.Handle).CGContext;
+                    if cglast <> cg then
+                    begin
+                      CGContextScaleCTM(cg, sc, sc);
+                      cglast := cg;
+                    end;
+                    {$else}
                     Height := PaintInfo.Node.NodeHeight;
+                    {$endif}
                     {$ifdef UseSetCanvasOrigin}
                     SetCanvasOrigin(Canvas, Window.Left, 0);
                     {$else}
@@ -31082,9 +31145,25 @@
                 // Put the constructed node image onto the target canvas.
                 if not (poUnbuffered in PaintOptions) then
                   with TWithSafeRect(TargetRect), NodeBitmap do
+                  begin
+                    {$ifdef LCLCocoa}
+                    StretchBlt(
+                      TargetCanvas.Handle,
+                      Left,
+                      Top {$ifdef ManualClipNeeded} + YCorrect{$endif},
+                      PaintWidth, PaintInfo.Node.NodeHeight,
+                      Canvas.Handle,
+                      Window.Left,
+                      {$ifdef ManualClipNeeded}YCorrect{$else}0{$endif},
+                      NodeBitmap.Width, NodeBitmap.Height,
+                      SRCCOPY
+                    );
+                    {$else}
                     BitBlt(TargetCanvas.Handle, Left,
                      Top {$ifdef ManualClipNeeded} + YCorrect{$endif}, Width, Height, Canvas.Handle, Window.Left,
                      {$ifdef ManualClipNeeded}YCorrect{$else}0{$endif}, SRCCOPY);
+                    {$endif}
+                  end;
               end;
             end;
 
vtvretina.diff (6,044 bytes)   

Wallaby

2020-08-07 07:30

reporter   ~0124640

I confirm that the patch resolves the blur on Retina. Here is a screen shot of VTV and regular ListView on Retina side by side.

As far as I can tell the font rendering is identical and looks great without the blur.
fixed.png (301,768 bytes)

Andrea Mauri

2020-11-23 12:17

reporter   ~0127138

Tested with Lazarus 2.1.0 r64156 FPC 3.2.0 x86_64-darwin-cocoa
Works as expected

Issue History

Date Modified Username Field Change
2019-03-26 08:37 Andrea Mauri New Issue
2019-03-26 08:37 Andrea Mauri File Added: Screen Shot 2019-03-08 at 16.51.16.png
2019-12-07 05:41 Trevor Roydhouse File Added: Screen Shot 2019-12-07 at 15.35.29.png
2019-12-07 05:41 Trevor Roydhouse Note Added: 0119672
2019-12-12 13:22 Juha Manninen Assigned To => Dmitry Boyarintsev
2019-12-12 13:22 Juha Manninen Status new => assigned
2019-12-12 13:23 Juha Manninen Status assigned => resolved
2019-12-12 13:23 Juha Manninen Resolution open => fixed
2019-12-12 13:23 Juha Manninen Fixed in Revision => r61618
2019-12-12 13:23 Juha Manninen LazTarget => -
2019-12-12 13:23 Juha Manninen Widgetset Cocoa => Cocoa
2019-12-12 13:23 Juha Manninen Note Added: 0119792
2019-12-13 11:19 Andrea Mauri File Added: Screen Shot 2019-12-13 at 11.16.48.png
2019-12-13 11:19 Andrea Mauri Note Added: 0119813
2019-12-13 14:05 Andrea Mauri Status resolved => assigned
2019-12-13 14:05 Andrea Mauri Resolution fixed => reopened
2020-08-05 04:56 Wallaby Note Added: 0124573
2020-08-05 04:56 Wallaby File Added: Ifjvulm.png
2020-08-05 10:12 Trevor Roydhouse Note Added: 0124575
2020-08-07 06:55 Dmitry Boyarintsev Note Added: 0124639
2020-08-07 06:55 Dmitry Boyarintsev File Added: vtvretina.diff
2020-08-07 07:30 Wallaby Note Added: 0124640
2020-08-07 07:30 Wallaby File Added: fixed.png
2020-08-07 16:28 Dmitry Boyarintsev Status assigned => resolved
2020-08-07 16:28 Dmitry Boyarintsev Fixed in Revision r61618 => r61618 63695
2020-08-07 16:28 Dmitry Boyarintsev Widgetset Cocoa => Cocoa
2020-11-23 12:17 Andrea Mauri Status resolved => closed
2020-11-23 12:17 Andrea Mauri Note Added: 0127138