View Issue Details

IDProjectCategoryView StatusLast Update
0034744LazarusWidgetsetpublic2019-06-18 19:50
Reporternigel lightfootAssigned ToDmitry Boyarintsev 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionreopened 
PlatformMacbookOSmacOSOS Version10.13.6
Product Version2.0RC2Product Build 
Target VersionFixed in Version 
Summary0034744: Canvas Line styles not visible in Cocoa
DescriptionLines draw on a canvas with varying line styles such as dashed or dotted show as a solid line. The same behaviour with Carbon or Cocoa widget sets
Steps To ReproduceLoad the Canvas_Test project from the standard examples
Run and choose the 'Show Pens Dialog' button
The Pens dialog draws rectangles with each of the standard styles. Apart from some fine structure in the lines they look the same.
The same thing happens if pen line styles are used in TAChart
TagsNo tags attached.
Fixed in Revision61115, 61411
LazTarget-
WidgetsetCocoa
Attached Files
  • patch1.txt (5,967 bytes)
    Index: lcl/interfaces/carbon/carbongdiobjects.pp
    ===================================================================
    --- lcl/interfaces/carbon/carbongdiobjects.pp	(revision 60594)
    +++ lcl/interfaces/carbon/carbongdiobjects.pp	(working copy)
    @@ -197,11 +197,18 @@
     const
       // Paul Ishenin:
       // pen shapes are compared with windows shapes and now a bit to bit equal
    -  CarbonDashStyle: Array [0..1] of Single = (3, 1);
    -  CarbonDotStyle: Array [0..1] of Single = (1, 1);
    -  CarbonDashDotStyle: Array [0..3] of Single = (3, 1, 1, 1);
    -  CarbonDashDotDotStyle: Array [0..5] of Single = (3, 1, 1, 1, 1, 1);
    +  // 2-2019: small adjustment to be more like Windows for any line-cap style
    +  CarbonDashStyle: Array [0..1] of Single = (2, 2);
    +  CarbonDotStyle: Array [0..1] of Single = (1, 2);
    +  CarbonDashDotStyle: Array [0..3] of Single = (3, 2, 1, 2);
    +  CarbonDashDotDotStyle: Array [0..5] of Single = (3, 2, 1, 2, 1, 2);
     
    +  // 2-2019: styles for cosmetic pen with width = 1. Same as in Windows
    +  CarbonDashStyleCosmetic: Array [0..1] of Single = (16, 8);
    +  CarbonDotStyleCosmetic: Array [0..1] of Single = (3, 3);
    +  CarbonDashDotStyleCosmetic: Array [0..3] of Single = (8, 7, 2, 7);
    +  CarbonDashDotDotStyleCosmetic: Array [0..5] of Single = (8, 4, 2, 4, 2, 4);
    +
     type
       TCarbonDashes = array of Float32;
     
    @@ -2022,13 +2029,19 @@
      ------------------------------------------------------------------------------}
     procedure TCarbonPen.Apply(ADC: TCarbonContext; UseROP2: Boolean);
     
    -  function GetDashes(Source: TCarbonDashes): TCarbonDashes;
    +  function GetDashes(Source, CosmeticSource: TCarbonDashes): TCarbonDashes;
       var
         i: Integer;
       begin
    -    Result := Source;
    -    for i := Low(Result) to High(Result) do
    -      Result[i] := Result[i] * FWidth;
    +    if FIsGeometric then
    +    begin
    +      Result := Source;
    +      for i := Low(Result) to High(Result) do
    +        Result[i] := Result[i] * FWidth;
    +    end else
    +    begin
    +      Result:= CosmeticSource;
    +    end;
       end;
     
     var
    @@ -2069,22 +2082,22 @@
       case FStyle of
         PS_DASH:
           begin
    -        ADashes := GetDashes(CarbonDashStyle);
    +        ADashes := GetDashes(CarbonDashStyle, CarbonDashStyleCosmetic);
             CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
           end;
         PS_DOT:
           begin
    -        ADashes := GetDashes(CarbonDotStyle);
    +        ADashes := GetDashes(CarbonDotStyle, CarbonDotStyleCosmetic);
             CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
           end;
         PS_DASHDOT:
           begin
    -        ADashes := GetDashes(CarbonDashDotStyle);
    +        ADashes := GetDashes(CarbonDashDotStyle, CarbonDashDotStyleCosmetic);
             CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
           end;
         PS_DASHDOTDOT:
           begin
    -        ADashes := GetDashes(CarbonDashDotDotStyle);
    +        ADashes := GetDashes(CarbonDashDotDotStyle, CarbonDashDotDotStyleCosmetic);
             CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
           end;
         PS_USERSTYLE:
    Index: lcl/interfaces/cocoa/cocoagdiobjects.pas
    ===================================================================
    --- lcl/interfaces/cocoa/cocoagdiobjects.pas	(revision 60594)
    +++ lcl/interfaces/cocoa/cocoagdiobjects.pas	(working copy)
    @@ -149,11 +149,18 @@
     
     const
       // use the same pen shapes that are used for carbon
    -  CocoaDashStyle: Array [0..1] of CGFloat = (3, 1);
    -  CocoaDotStyle: Array [0..1] of CGFloat = (1, 1);
    -  CocoaDashDotStyle: Array [0..3] of CGFloat = (3, 1, 1, 1);
    -  CocoaDashDotDotStyle: Array [0..5] of CGFloat = (3, 1, 1, 1, 1, 1);
    +  // 2-2019: small adjustment to be more like Windows for any line-cap style
    +  CocoaDashStyle: Array [0..1] of CGFloat = (2, 2);
    +  CocoaDotStyle: Array [0..1] of CGFloat = (1, 2);
    +  CocoaDashDotStyle: Array [0..3] of CGFloat = (3, 2, 1, 2);
    +  CocoaDashDotDotStyle: Array [0..5] of CGFloat = (3, 2, 1, 2, 1, 2);
     
    +  // 2-2019: styles for cosmetic pen with width = 1. Same as in Windows
    +  CocoaDashStyleCosmetic: Array [0..1] of CGFloat = (16, 8);
    +  CocoaDotStyleCosmetic: Array [0..1] of CGFloat = (3, 3);
    +  CocoaDashDotStyleCosmetic: Array [0..3] of CGFloat = (8, 7, 2, 7);
    +  CocoaDashDotDotStyleCosmetic: Array [0..5] of CGFloat = (8, 4, 2, 4, 2, 4);
    +
     type
       TCocoaDashes = array of CGFloat;
     
    @@ -2692,13 +2699,19 @@
     
     procedure TCocoaPen.Apply(ADC: TCocoaContext; UseROP2: Boolean = True);
     
    -  function GetDashes(Source: TCocoaDashes): TCocoaDashes;
    +  function GetDashes(Source, CosmeticSource: TCocoaDashes): TCocoaDashes;
       var
         i: Integer;
       begin
    -    Result := Source;
    -    for i := Low(Result) to High(Result) do
    -      Result[i] := Result[i] * FWidth;
    +    if FIsGeometric then
    +    begin
    +      Result := Source;
    +      for i := Low(Result) to High(Result) do
    +        Result[i] := Result[i] * FWidth;
    +    end else
    +    begin
    +      Result:= CosmeticSource;
    +    end;
       end;
     
     var
    @@ -2738,22 +2751,22 @@
       case FStyle of
         PS_DASH:
           begin
    -        ADashes := GetDashes(CocoaDashStyle);
    +        ADashes := GetDashes(CocoaDashStyle, CocoaDashStyleCosmetic);
             CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
           end;
         PS_DOT:
           begin
    -        ADashes := GetDashes(CocoaDotStyle);
    +        ADashes := GetDashes(CocoaDotStyle, CocoaDotStyleCosmetic);
             CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
           end;
         PS_DASHDOT:
           begin
    -        ADashes := GetDashes(CocoaDashDotStyle);
    +        ADashes := GetDashes(CocoaDashDotStyle, CocoaDashDotStyleCosmetic);
             CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
           end;
         PS_DASHDOTDOT:
           begin
    -        ADashes := GetDashes(CocoaDashDotDotStyle);
    +        ADashes := GetDashes(CocoaDashDotDotStyle, CocoaDashDotDotStyleCosmetic);
             CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
           end;
         PS_USERSTYLE:
    
    patch1.txt (5,967 bytes)
  • line styles 11-5-19 (minimized).pptx (407,131 bytes)
  • line_style_test.zip (129,952 bytes)
  • line styles 11-5-19.pptx (573,076 bytes)

Activities

Nigel Lightfoot

2019-03-05 14:29

reporter   ~0114662

Attached patch file which modifies lcl/interfaces/cocoa/cocoagdiobjects.pas and lcl/interfaces/carbon/carbongdiobjects.pas, dash and dot lengths modified so that even with a round end-cap style is used there is gap between dash/dot. Also included alternate styles with geometric pen to mimic how MS Windows works.

Nigel Lightfoot

2019-03-05 14:30

reporter  

patch1.txt (5,967 bytes)
Index: lcl/interfaces/carbon/carbongdiobjects.pp
===================================================================
--- lcl/interfaces/carbon/carbongdiobjects.pp	(revision 60594)
+++ lcl/interfaces/carbon/carbongdiobjects.pp	(working copy)
@@ -197,11 +197,18 @@
 const
   // Paul Ishenin:
   // pen shapes are compared with windows shapes and now a bit to bit equal
-  CarbonDashStyle: Array [0..1] of Single = (3, 1);
-  CarbonDotStyle: Array [0..1] of Single = (1, 1);
-  CarbonDashDotStyle: Array [0..3] of Single = (3, 1, 1, 1);
-  CarbonDashDotDotStyle: Array [0..5] of Single = (3, 1, 1, 1, 1, 1);
+  // 2-2019: small adjustment to be more like Windows for any line-cap style
+  CarbonDashStyle: Array [0..1] of Single = (2, 2);
+  CarbonDotStyle: Array [0..1] of Single = (1, 2);
+  CarbonDashDotStyle: Array [0..3] of Single = (3, 2, 1, 2);
+  CarbonDashDotDotStyle: Array [0..5] of Single = (3, 2, 1, 2, 1, 2);
 
+  // 2-2019: styles for cosmetic pen with width = 1. Same as in Windows
+  CarbonDashStyleCosmetic: Array [0..1] of Single = (16, 8);
+  CarbonDotStyleCosmetic: Array [0..1] of Single = (3, 3);
+  CarbonDashDotStyleCosmetic: Array [0..3] of Single = (8, 7, 2, 7);
+  CarbonDashDotDotStyleCosmetic: Array [0..5] of Single = (8, 4, 2, 4, 2, 4);
+
 type
   TCarbonDashes = array of Float32;
 
@@ -2022,13 +2029,19 @@
  ------------------------------------------------------------------------------}
 procedure TCarbonPen.Apply(ADC: TCarbonContext; UseROP2: Boolean);
 
-  function GetDashes(Source: TCarbonDashes): TCarbonDashes;
+  function GetDashes(Source, CosmeticSource: TCarbonDashes): TCarbonDashes;
   var
     i: Integer;
   begin
-    Result := Source;
-    for i := Low(Result) to High(Result) do
-      Result[i] := Result[i] * FWidth;
+    if FIsGeometric then
+    begin
+      Result := Source;
+      for i := Low(Result) to High(Result) do
+        Result[i] := Result[i] * FWidth;
+    end else
+    begin
+      Result:= CosmeticSource;
+    end;
   end;
 
 var
@@ -2069,22 +2082,22 @@
   case FStyle of
     PS_DASH:
       begin
-        ADashes := GetDashes(CarbonDashStyle);
+        ADashes := GetDashes(CarbonDashStyle, CarbonDashStyleCosmetic);
         CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
       end;
     PS_DOT:
       begin
-        ADashes := GetDashes(CarbonDotStyle);
+        ADashes := GetDashes(CarbonDotStyle, CarbonDotStyleCosmetic);
         CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
       end;
     PS_DASHDOT:
       begin
-        ADashes := GetDashes(CarbonDashDotStyle);
+        ADashes := GetDashes(CarbonDashDotStyle, CarbonDashDotStyleCosmetic);
         CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
       end;
     PS_DASHDOTDOT:
       begin
-        ADashes := GetDashes(CarbonDashDotDotStyle);
+        ADashes := GetDashes(CarbonDashDotDotStyle, CarbonDashDotDotStyleCosmetic);
         CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
       end;
     PS_USERSTYLE:
Index: lcl/interfaces/cocoa/cocoagdiobjects.pas
===================================================================
--- lcl/interfaces/cocoa/cocoagdiobjects.pas	(revision 60594)
+++ lcl/interfaces/cocoa/cocoagdiobjects.pas	(working copy)
@@ -149,11 +149,18 @@
 
 const
   // use the same pen shapes that are used for carbon
-  CocoaDashStyle: Array [0..1] of CGFloat = (3, 1);
-  CocoaDotStyle: Array [0..1] of CGFloat = (1, 1);
-  CocoaDashDotStyle: Array [0..3] of CGFloat = (3, 1, 1, 1);
-  CocoaDashDotDotStyle: Array [0..5] of CGFloat = (3, 1, 1, 1, 1, 1);
+  // 2-2019: small adjustment to be more like Windows for any line-cap style
+  CocoaDashStyle: Array [0..1] of CGFloat = (2, 2);
+  CocoaDotStyle: Array [0..1] of CGFloat = (1, 2);
+  CocoaDashDotStyle: Array [0..3] of CGFloat = (3, 2, 1, 2);
+  CocoaDashDotDotStyle: Array [0..5] of CGFloat = (3, 2, 1, 2, 1, 2);
 
+  // 2-2019: styles for cosmetic pen with width = 1. Same as in Windows
+  CocoaDashStyleCosmetic: Array [0..1] of CGFloat = (16, 8);
+  CocoaDotStyleCosmetic: Array [0..1] of CGFloat = (3, 3);
+  CocoaDashDotStyleCosmetic: Array [0..3] of CGFloat = (8, 7, 2, 7);
+  CocoaDashDotDotStyleCosmetic: Array [0..5] of CGFloat = (8, 4, 2, 4, 2, 4);
+
 type
   TCocoaDashes = array of CGFloat;
 
@@ -2692,13 +2699,19 @@
 
 procedure TCocoaPen.Apply(ADC: TCocoaContext; UseROP2: Boolean = True);
 
-  function GetDashes(Source: TCocoaDashes): TCocoaDashes;
+  function GetDashes(Source, CosmeticSource: TCocoaDashes): TCocoaDashes;
   var
     i: Integer;
   begin
-    Result := Source;
-    for i := Low(Result) to High(Result) do
-      Result[i] := Result[i] * FWidth;
+    if FIsGeometric then
+    begin
+      Result := Source;
+      for i := Low(Result) to High(Result) do
+        Result[i] := Result[i] * FWidth;
+    end else
+    begin
+      Result:= CosmeticSource;
+    end;
   end;
 
 var
@@ -2738,22 +2751,22 @@
   case FStyle of
     PS_DASH:
       begin
-        ADashes := GetDashes(CocoaDashStyle);
+        ADashes := GetDashes(CocoaDashStyle, CocoaDashStyleCosmetic);
         CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
       end;
     PS_DOT:
       begin
-        ADashes := GetDashes(CocoaDotStyle);
+        ADashes := GetDashes(CocoaDotStyle, CocoaDotStyleCosmetic);
         CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
       end;
     PS_DASHDOT:
       begin
-        ADashes := GetDashes(CocoaDashDotStyle);
+        ADashes := GetDashes(CocoaDashDotStyle, CocoaDashDotStyleCosmetic);
         CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
       end;
     PS_DASHDOTDOT:
       begin
-        ADashes := GetDashes(CocoaDashDotDotStyle);
+        ADashes := GetDashes(CocoaDashDotDotStyle, CocoaDashDotDotStyleCosmetic);
         CGContextSetLineDash(ADC.CGContext, 0, @ADashes[0], Length(ADashes));
       end;
     PS_USERSTYLE:
patch1.txt (5,967 bytes)

Dmitry Boyarintsev

2019-05-03 17:16

developer   ~0115977

fixed using a different approach. please test and close if ok

Nigel Lightfoot

2019-05-12 23:51

reporter   ~0116153

1) Thank you for implementing the added cosmetic pen styles.
2) The modification to the patterns for geometric pens is not implemented. I have attached powerpoint slides as evidence that better comparison is possible. These show even better agreement with Windows than my earlier patch.
3) I have attached a zipped project of the test harness I used to comparing line styles.
4) There is no change to the Carbon implementation. Is this to remain legacy?

line styles 11-5-19 (minimized).pptx (407,131 bytes)
line_style_test.zip (129,952 bytes)

Nigel Lightfoot

2019-05-13 09:36

reporter  

line styles 11-5-19.pptx (573,076 bytes)

Nigel Lightfoot

2019-05-13 09:36

reporter   ~0116154

Un-minimised PPTX file attached as 'minimised' version does not open in 'Keynote'. (originally from LibreOffice)

Dmitry Boyarintsev

2019-06-18 15:12

developer   ~0116770

slide "10" shows a problem with geometric pen

Dmitry Boyarintsev

2019-06-18 15:48

developer   ~0116771

please test and close if ok

nigel lightfoot

2019-06-18 19:50

reporter   ~0116772

Tested OK

Issue History

Date Modified Username Field Change
2018-12-21 15:38 nigel lightfoot New Issue
2019-03-05 14:29 Nigel Lightfoot Note Added: 0114662
2019-03-05 14:30 Nigel Lightfoot File Added: patch1.txt
2019-05-03 17:16 Dmitry Boyarintsev Assigned To => Dmitry Boyarintsev
2019-05-03 17:16 Dmitry Boyarintsev Status new => resolved
2019-05-03 17:16 Dmitry Boyarintsev Resolution open => fixed
2019-05-03 17:16 Dmitry Boyarintsev Fixed in Revision => 61115
2019-05-03 17:16 Dmitry Boyarintsev LazTarget => -
2019-05-03 17:16 Dmitry Boyarintsev Widgetset Cocoa => Cocoa
2019-05-03 17:16 Dmitry Boyarintsev Note Added: 0115977
2019-05-12 23:51 Nigel Lightfoot File Added: line styles 11-5-19 (minimized).pptx
2019-05-12 23:51 Nigel Lightfoot File Added: line_style_test.zip
2019-05-12 23:51 Nigel Lightfoot Note Added: 0116153
2019-05-13 09:36 Nigel Lightfoot File Added: line styles 11-5-19.pptx
2019-05-13 09:36 Nigel Lightfoot Note Added: 0116154
2019-06-18 15:12 Dmitry Boyarintsev Status resolved => assigned
2019-06-18 15:12 Dmitry Boyarintsev Resolution fixed => reopened
2019-06-18 15:12 Dmitry Boyarintsev Note Added: 0116770
2019-06-18 15:48 Dmitry Boyarintsev Status assigned => resolved
2019-06-18 15:48 Dmitry Boyarintsev Fixed in Revision 61115 => 61115, 61411
2019-06-18 15:48 Dmitry Boyarintsev Widgetset Cocoa => Cocoa
2019-06-18 15:48 Dmitry Boyarintsev Note Added: 0116771
2019-06-18 19:50 nigel lightfoot Status resolved => closed
2019-06-18 19:50 nigel lightfoot Note Added: 0116772