ForNeVeR / xaml-math

A collection of .NET libraries for rendering mathematical formulae using the LaTeX typesetting style, for the WPF and Avalonia XAML-based frameworks
MIT License
643 stars 103 forks source link

Support for Windows Forms apps #281

Open pavledev opened 4 years ago

pavledev commented 4 years ago

Can you please add support for Windows Forms Apps?

Happypig375 commented 4 years ago

https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.integration.elementhost

pavledev commented 4 years ago

ElementHost host = new ElementHost(); host.Dock = DockStyle.Fill;

WpfMath.Controls.FormulaControl formulaControl = new WpfMath.Controls.FormulaControl(); host.Child = formulaControl;

this.Controls.Add(host);

@Happypig375 I get error: the type 'UIElement' is defined in an assembly that is not referenced. You must add a reference to assembly 'PresentationCore'

FoggyFinder commented 4 years ago

I get error: the type 'UIElement' is defined in an assembly that is not referenced. You must add a reference to assembly 'PresentationCore'

Well, cause you have to add that reference.

pavledev commented 4 years ago

I added references to PresentationCore, PresentationFramework and WindowsBase and now it works. @FoggyFinder Thank you.

pavledev commented 4 years ago

How I can do this from WinForm https://github.com/ForNeVeR/wpf-math/blob/master/docs/blurred-text-issue.md

FoggyFinder commented 4 years ago

you could try something like this:

var style = new Style
{
    TargetType = typeof(FormulaControl)
};
style.Setters.Add(new Setter(TextOptions.TextRenderingModeProperty,
                             TextRenderingMode.ClearType));
style.Setters.Add(new Setter(TextOptions.TextHintingModeProperty, 
                             TextHintingMode.Fixed));
style.Setters.Add(new Setter(TextOptions.TextFormattingModeProperty, 
                             TextFormattingMode.Display));

var formulaControl = new FormulaControl()
{
    Style = style
};
pavledev commented 4 years ago

@FoggyFinder I tried that code but it still looks same.

FoggyFinder commented 4 years ago

I don't know then

ForNeVeR commented 4 years ago

Hello. I doubt proper support for Windows Forms is possible for WPF-Math in the nearest future.

For now, we heavily rely on WPF geometry and font rendering support.

  1. As a general (right) solution, we'd better get a Windows Forms-specific renderer (in the same way we're getting Avalonia one), but that's a lot of work.
  2. As a light workaround, you, for sure, should be able to embed WPF elements into your Windows Forms apps, as explained above.

    About the blurry fonts inside of ElementHost in a Windows Forms apps, I've no idea. I guess, we'll need someone with heavy experience in both WPF and Windows Forms to dedug the accompanying issues.

  3. There's another workaround possible: check the code sample to generate a PNG image. You may use it in runtime, and then embed the resulting PNG into a Windows Forms application. I guess it would be less problematic than messing with the ElementHost.

I am leaving the issue open in favor of (eventually, some time) doing it in the "right" way, approach # 1 described above.

pavledev commented 4 years ago

@ForNeVeR Ok. Thank you. Can you please add /angle symbol to wpf-math?

ForNeVeR commented 1 year ago

Okay, I've taken a look at it, it wasn't too hard (since we now have pretty much platform-neutral rendering pipeline), and got some results. Here's the result of rendering \sqrt 2 on Windows Forms:

image

The general rendering quality is awful, but I think there are some ways to improve it (like setting some flag on Graphics or something), but there's also a font metric issue: see how the bar is misaligned over the X axis. The bar is drawn using the graphics API (FillRectangle in this case), while the radical sign and the 2 are drawn using the font API. It looks like the bar is drawn correctly, but the font characters are a bit misaligned.

I wasn't still able to figure out what exactly is happening there. If you want to experiment, see the code in the branch experiment/281.winforms: https://github.com/ForNeVeR/xaml-math/blob/51d02e2b5e5c6fa8c9262aec169dc2bfc4353640/src/WinFormsMath/Rendering/WinFormsRenderer.cs#L32-L66

In WPF and Avalonia, we use x and y to determine the text baseline origin. On what the baseline origin is, see this helpful image from Microsoft documentation: Explanation of font metrics

WinForms API, on the contrary, expects us to pass the top left corner of the glyph drawing area.

I've used some tricks to shift the Y axis of the WinForms renderer to correctly apply the baseline (and it, indeed, looks correct), but I haven't found any tricks to do the same for the X axis: it looks like normally the baseline origin should be zero. But, as you see, the zero origin doesn't correspond to our WPF/Avalonia rendering results, and doesn't correspond to what should really happen.

I'm not sure how to proceed. Maybe just ditch the idea of using WinForms Font/DrawString directly, and go with DirectX renderer (#96) instead?

ForNeVeR commented 1 year ago

Applying StringFormat.Typographic (whatever that means) to DrawString fixed the problem.

ygra commented 1 year ago

GDI+ normally fits the characters to the pixel grid, which results in more legible characters on low-DPI screens and small font sizes. But it throws the exact font metrics off. So in this case I don't think there's even another option than to go with Typographic.