Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option for clear type text #3846

Closed
wants to merge 1 commit into from
Closed

Conversation

bforlgreen
Copy link
Contributor

@bforlgreen bforlgreen commented May 18, 2024

Clear type text is a process to make text appear crisper at the same resolution. Whilst basic antialiasing makes text look less pixelated, it can also then make text look more blurry. Clear type is an extension to antialiasing that uses colours to "trick" us into perceiving the text is crisper.

On the left, no AA, so looks pixelated.
In the middle, AA has been applied (but in certain situations, like with a grey colour, it can look blurry)
On the right, AA with clear type

image

To enable ClearType in Skia, you have to set LcdRenderText on the Paint class to true, which will then enables "SubpixelAntialias". I am not sure why they use the name "LcdRenderText" instead of 'SubpixelAntialias'.

Unfortunately, this is not the only change you have to make to enable ClearType. You also have to set the SkSurfacesProperties within the SKElement class. To achieve this, you kind of have to copy the the SKElement class from the SkiaSharp code base.

Results ( you will need to zoom in)
image

/// To make use of ClearType text, you must also set the SKSurfaceProperties
/// of your SKSurface to be something other than SKPixelGeometry.Unknown
/// </summary>
public bool SubPixelAntiAliasText { get; set; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wonder if we should make this an enum, since setting LcdRenderText to true has no effect unless paint.IsAntialias is also true.

I'm thinking something along the lines of

enum TextAntialiasType {
  None,
  Antialias,
  SubpixelAntialias,
}

Then we can set the booleans but allow a simpler API. But we'll need to keep AntiAliasText to keep backwards compatibility. I think we should use getters and setters to enforce the current behaviour (if AntiAliasText is set to true we get the current AA behaviour, if it's false we get no AA). Not sure if setting it to true while subpixel AA is on should have no effect or if it should be set to non-subpixel AA.

@@ -32,6 +32,12 @@ public class Label
public bool AntiAliasBackground { get; set; } = true;
public bool AntiAliasText { get; set; } = true;

/// <summary>
/// To make use of ClearType text, you must also set the SKSurfaceProperties
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is something that has to be enabled on the control, and I don't like the idea of having AA flags being placed in two very different places. I think the solution is probably making some TextAntialiasType a global field which is read in both places (maybe on the Plot class?). And if necessary we can preserve some way for the user to mix unantialiased text with AA text. But I'm not convinced that the user would want something like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the problem is that you have to be able to set SKSurfaceProperties when creating the SKSurface, which you can only do by implementing your own SKElement class (SKElement is implemented in SkiaSharp)

The only clean way I can see to do it would be to have a copy of the SkiaSharp SKElement class inside of the ScottPlot library itself. But appreciate you won't want to do that just for this use case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already use SKElement on (most of) the controls. For example, see https://github.com/ScottPlot/ScottPlot/blob/main/src/ScottPlot5/ScottPlot5%20Controls/ScottPlot.WPF/Themes/Generic.xaml

Worst case scenario, we can subclass SKElement to provide our own OnRender function (relevant code for WPF is here: https://github.com/mono/SkiaSharp/blob/main/source/SkiaSharp.Views/SkiaSharp.Views.WPF/SKElement.cs). But I'm admittedly not that pleased at the idea of duplicating most of the function just to allow a slightly different SKSurface.Create call. Granted it doesn't look like these views are changed much, but it doesn't fill me with joy. I do also see some private methods and fields which we'd need to copy-paste for this to work.

This could also be achieved by copying , but that's not ideal, one of the big benefits of ScottPlot 5 is we don't normally need to copy bitmaps between the plot and the controls.

@bforlgreen bforlgreen closed this Jun 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants