Page 1 of 1

[c++]How do you draw a line on a canvas in Noesis that is 1 pixel thick

Posted: 15 Mar 2019, 07:56
by tkawa
I'm using the Path class to draw on a canvas in Noesis and even though I set StrokeThickness = 1, the line shows up 2 pixels wide - it's almost as if the minimum thickness is two. How do I draw a line that is truly 1 pixel thick?

https://stackoverflow.com/questions/287 ... ixel-thick
<Border BorderThickness="1" BorderBrush="Red" Height="20">
    <Canvas>
        <Path SnapsToDevicePixels="True" Stroke="Red" StrokeThickness="1" Data="M 5,5 L 100,5"/>
        <Path SnapsToDevicePixels="True" Stroke="Red" StrokeThickness="1" Data="M 5,10 L 100,10"/>
        <Path SnapsToDevicePixels="True" Stroke="Red" StrokeThickness="1" Data="M 5,15 L 100,15"/>

        <Path Stroke="Red" StrokeThickness="1" Data="M 5,25 L 100,25"/>
        <Path Stroke="Red" StrokeThickness="1" Data="M 5,30 L 100,30"/>
        <Path Stroke="Red" StrokeThickness="1" Data="M 5,35 L 100,35"/>
    </Canvas>
</Border>

Re: [c++]How do you draw a line on a canvas in Noesis that is 1 pixel thick

Posted: 15 Mar 2019, 12:22
by stonstad
I am very new to Noesis. But I just wanted to throw out a suggestion for something to try. What happens if you turn off PPAA (pixel perfect anti-aliasing) on the view?

Re: [c++]How do you draw a line on a canvas in Noesis that is 1 pixel thick

Posted: 16 Mar 2019, 08:28
by jsantos
This is almost for sure related to PPAA (our cheap antialiasing emulation). If this is the reason, there are two solutions:

You can disable PPAA in the NoesisView component and use GPU MSAA. This will probably give you overall better quality but probably less performance.

Disable, selectively PPAA on those elements you know they don't need it using the noesis:Element.PPAAMode property. For example:
<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:noesis="clr-namespace:NoesisGUIExtensions"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
    Background="White">

  <Grid x:Name="_LayoutRoot">
    <Grid.RowDefinitions>
      <RowDefinition Height="1*" />
      <RowDefinition Height="8*" />
      <RowDefinition Height="1*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="1*" />
      <ColumnDefinition Width="8*" />
      <ColumnDefinition Width="1*" />
    </Grid.ColumnDefinitions>

      <Grid Width="600" Height="480" Grid.Row="1" Grid.Column="1" UseLayoutRounding="True" noesis:Element.PPAAMode="Disabled">

Re: [c++]How do you draw a line on a canvas in Noesis that is 1 pixel thick

Posted: 18 Mar 2019, 07:19
by tkawa
Thanks for the reply.

I've tried setting
UseLayoutRounding="True" noesis:Element.PPAAMode="Disabled"
on the Window, the Grid, the Canvas, and the Path.
But, UseLayoutRounding and PPAAMode doesn't seem to have same effect with SnapsToDevicePixels.
This behavior is same in WPF.
<Grid Background="White">
    <StackPanel Orientation="Horizontal">
        <Border BorderThickness="1" BorderBrush="Red" Width="100" >
            <Canvas SnapsToDevicePixels="True" >
                <Path Stroke="Red" StrokeThickness="1" Data="M 0,0 L 100,100"       />
                <Path Stroke="Red" StrokeThickness="1" Data="M 0,50 L 100,50"    />
                <Path Stroke="Red" StrokeThickness="1" Data="M 0,100 L 100,0" />
            </Canvas>
        </Border>
        <Border BorderThickness="1" BorderBrush="Blue" Width="100" >
            <Canvas UseLayoutRounding="True" >
                <Path Stroke="Red" StrokeThickness="1" Data="M 0,0 L 100,100"       />
                <Path Stroke="Red" StrokeThickness="1" Data="M 0,50 L 100,50"    />
                <Path Stroke="Red" StrokeThickness="1" Data="M 0,100 L 100,0" />
            </Canvas>
        </Border>
    </StackPanel>
</Grid>
It may not be easy to see, but width of path is not changed from 2px when set UseLayoutRounding=True.
WPF image ↓

Re: [c++]How do you draw a line on a canvas in Noesis that is 1 pixel thick

Posted: 18 Mar 2019, 08:45
by nikobarli
Hi, I think the problem is with the anti-aliasing. Our integration layer (which is also used by tkawa) is using MSAA (PPAA is disabled) for anti-aliasing and it caused the problem that thin lines appear to be blurred. Disabling MSAA fixed the problem, but at the cost of anti-aliasing in other parts.

Using PPAA and disabling it in parts that we need crisp rendering may solve the problem, but overall PPAA seems slower and not as pretty as MSAA.

Do you have a better recommendation ?

Re: [c++]How do you draw a line on a canvas in Noesis that is 1 pixel thick

Posted: 18 Mar 2019, 20:44
by jsantos
What is happening is that the stroked line needs to be displaced by half-width to properly align with the pixels. Something like this is working fine in both Noesis and Blend:
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  UseLayoutRounding="True" Background="White">
    <Border BorderThickness="1" BorderBrush="Black" Height="20">
        <Canvas>
            <Path Stroke="Red" StrokeThickness="1" Data="M 5,5.5 L 100,5.5"/>
            <Path Stroke="Red" StrokeThickness="1" Data="M 5,10.5 L 100,10.5"/>
            <Path Stroke="Red" StrokeThickness="1" Data="M 5,15.5 L 100,15.5"/>
        </Canvas>
    </Border>
</Grid>
Note that in Noesis, SnapsToDevicePixels is not implemented.

Re: [c++]How do you draw a line on a canvas in Noesis that is 1 pixel thick

Posted: 25 Mar 2019, 06:59
by tkawa
I could draw 1 pixel line by displacing it by half.
Thank you for your helpful response!

Re: [c++]How do you draw a line on a canvas in Noesis that is 1 pixel thick

Posted: 27 Mar 2019, 00:31
by jsantos
Thanks! Closing this!