charlesroddie / MathAtom

Structural representations of visual mathematics expressions for use in .Net rendering libraries
MIT License
7 stars 0 forks source link

API shape + Type naming #6

Open Happypig375 opened 5 years ago

Happypig375 commented 5 years ago

I propose the following general API shape:

namespace To_Be_Determined_Library_Name.VisualAtom
    type VisualAtom = ...
namespace To_Be_Determined_Library_Name.MathAtom
   type MathAtom =
      | ...
   [<RequireQualifiedAccess>]
   module LaTeX =
      let ToAtom (s: string) : MathAtom =
         ...
      let FromAtom (a: MathAtom) : string =
         ...
   [<RequireQualifiedAccess>]
   module MathML =
      let ToAtom (s: string) : MathAtom =
         ...
      let FromAtom (a: MathAtom) : string =
         ...
   [<RequireQualifiedAccess>]
   module Visual =
      let FromAtom (a: MathAtom) : VisualAtom =
         ...
namespace To_Be_Determined_Library_Name.TextAtom
   type TextAtom =
      | ...
   [<RequireQualifiedAccess>]
   module LaTeX =
      let ToAtom (s: string) : TextAtom =
         ...
      let FromAtom (a: TextAtom) : string =
         ...
   [<RequireQualifiedAccess>]
   module Visual =
      let FromAtom (a: TextAtom) : VisualAtom =
         ...
namespace To_Be_Determined_Library_Name.VisualAtom
   type ICanvas =
      abstract member DrawLine(...) =
         ...
      ...
   [<RequireQualifiedAccess>]
   module ICanvas =
      let DrawOn (c: ICanvas) (v: VisualAtom) : unit =
         ...

image

Happypig375 commented 5 years ago

Visual is identical to Box in wpf-math and Display in CSharpMath. I named it Visual because 1. it sounds more appropriate than Box or Display, and 2. it shows up after MathAtom and TextAtom in Intellisense, which provides visual ordering of operations.

Example usage:

open MathAtom
open VisualAtom

@"\frac{1}{2}"
|> LaTeX.ToAtom //LaTeX to MathAtom
|> Visual.FromAtom //Visual from MathAtom
|> SKCanvas.DrawOn canvas //Visual on SKCanvas
charlesroddie commented 5 years ago

Sorry that I've been too overloaded to check in a consolidated Atom type.

It's OK to use capital letters to avoid the annotations and I would use ToAtom and FromAtom. More standard. Namespaces are often opened and then To and From by themselves are in conflict.

TextAtom.Atom would need renaming. Again namespaces are often opened so having two Atom types should be avoided. Probably it shouldn't have Atom in the name at all. We can worry about that later.

type Visual should go after the MathAtom/MathText types (with separate types for Math and MathText).

namespace Visual would cause confusion with type Visual.

For the math layers there is Atom (the visual structure), Box/Visual (full description of layout) and Rendering (with or without a SkiaSharp dependency).

Happypig375 commented 5 years ago

I updated the code.

I don't expect people to open both MathAtom and TextAtom namespaces at the same time.

type Visual should go after the MathAtom/MathText types (with separate types for Math and MathText).

MathAtom.Visual.FromAtom and TextAtom.Visual.FromAtom depends on VisualAtom so it is defined earlier than them.

namespace Visual would cause confusion with type Visual.

I don't see the namespace conflicting with the type but the module with the type. Renamed Visual to VisualAtom.

ForNeVeR commented 5 years ago
  1. I would recommend against namespace Visual, because there's already class Visual in WPF (and we definitely will want to mix this library with WPF). Namespace and type name conflicts are usually confusing (probably due to poor C# error reporting) and basically would create a constant pain-point for the library users.
  2. What exactly are MathAtom and TextAtom?
  3. Let's look from a contributor perspective. Where will I (a hypothetical contributor) need to place my code if I want to implement a parser for LaTeX?
Happypig375 commented 5 years ago
  1. Renamed namespace Visual to namespace VisualAtom. (All the namespaces here would obviously be surrounded with a master namespace with the to-be-determined library name though.)
  2. MathAtoms are the Atoms in wpf-math, TextAtom includes a case for MathAtom but supports features of non-math (text) mode LaTeX.
  3. If it is LaTeX -> MathAtom, then To_Be_Determined_Library_Name.MathAtom.LaTeX.ToAtom.
charlesroddie commented 5 years ago

My suggestion for structure (dependencies and file order). It doesn't include namespaces but that should be compatible with file/project order. Namespaces can be altered later very easily.

image

I would not recommend distinguishing VisualAtom/Box and an ICanvas. A VisualAtom/Box is a model of the view, and drawing it is just a matter of hooking up the particular drawing engine. We should make it obvious in the VisualAtom/Box structure how it should be rendered. ICanvas then serves no function and is not needed as an abstraction layer.

Happypig375 commented 5 years ago

Just to be clear about ICanvas, it does not represent the atom but the canvas. Something like:

type ICanvas =
   abstract member DrawLine: x1:float -> y1:float -> x2:float -> y2:float -> thickness:float -> unit
   abstract member DrawQuadratc: x1: float -> y1: float -> x2:float -> y2: float -> x3:float -> y3:float -> unit
   abstract member DrawCubic: x1: float -> y1: float -> x2:float -> y2: float -> x3:float -> y3:float -> x4: float -> y4: float -> unit
  ...

VisualAtom.SKCanvas.DrawOn would call VisualAtom.ICanvas.DrawOn as its underlying implementation. Updated the image again. As now I'm on a Mac, sorry for the blurry text from the Preview app.

charlesroddie commented 5 years ago

Yes I understand that. To oversimplify things, imagine we have

type Element =
    | Glyph of char * Point * size:float
    | Line of Point * Point * thickness:float
    ...
type Box = Element list

Then the SkiaSharp project can draw a Box on an SKCanvas, and similarly for any other renderer, and we don't need an intermediate interface layer.

Happypig375 commented 5 years ago

The current Box/Display/VisualAtom abstracts a "box"/"display"/"visual" that draws an atom. For example in CSharpMath: AccentDisplay, FractionDisplay, RadicalDisplay... This abstraction layer provides valuable information for e.g. the TextLayoutter which is responsible for separating these displays into lines for TextPainter to draw.