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

More drawing primitives #260

Closed
ollelogdahl opened this issue Mar 24, 2023 · 11 comments
Closed

More drawing primitives #260

ollelogdahl opened this issue Mar 24, 2023 · 11 comments
Labels
feature request New feature or request visualize Related to drawing and visualizations.

Comments

@ollelogdahl
Copy link
Contributor

ollelogdahl commented Mar 24, 2023

I think we need a place to discuss drawing primitives. For example:

@SekoiaTree
Copy link
Contributor

I'll try and do Bezier curves!

@ollelogdahl
Copy link
Contributor Author

I also think a cool feature would be patterns in the Paint object. Kind of like pattern in LaTeX. This would inpact all painting objects, for example: rect(fill: solid blue, ...), rect(fill: lines blue, ...), rect(fill: hatch blue, ...).

@SekoiaTree
Copy link
Contributor

Added in #333!

@birktj
Copy link
Contributor

birktj commented Apr 1, 2023

Ok, so I know that this is sort of under way/discussion in #333 , but I am considering taking my own stab at a general path primitive. I believe such a primitive should support the standard moveto, lineto, arcto and curveto operations. It should have stroke, fill and closed parameters. And also preferably it should support being used as a clipping mask for content.

For the operations API I imagine a couple of possible solutions:

  • Take a string in the same format as svg paths. This is a well known format, but would probably not be so ergonomical to use so I am not really a fan.
  • Extend the type system with a path type and add the operations above as constructors of this type. I think that adding an explicit type would introduce unnecessary complexity, but I think maybe as a dynamic type that implements join this could be a nice solution.
  • Same as above but instead of adding a type as above we could simply introduce functions that return single element arrays with dicts on the form of (op: "moveto", x: 5.0, y: 4.0) . The arrays would be joined together in a code block so that one could easily write complex paths.

For both of the two last solutions above I imagine it would look something like this:

path(stroke: 1pt + red, {
  moveto(x: 2.0pt, y: 2.0pt)
  lineto(dx: 10.0pt)
  let i = 0
  while i < 5 {
    lineto(dx: 5.0pt)
    lineto(y: 7.0pt)
    lineto(dx: 5.0pt)
    lineto(y: 2.0pt)
    i += 1
  }

  moveto(x: 10.0, y: 10.0)
  arcto(r: 4.0, ang: 90deg)
})

@laurmaedje laurmaedje added feature request New feature or request visualize Related to drawing and visualizations. labels Apr 1, 2023
@ollelogdahl
Copy link
Contributor Author

ollelogdahl commented Apr 1, 2023

Ok, so I know that this is sort of under way/discussion in #333 , but I am considering taking my own stab at a general path primitive. I believe such a primitive should support the standard moveto, lineto, arcto and curveto operations. It should have stroke, fill and closed parameters. And also preferably it should support being used as a clipping mask for content.

For the operations API I imagine a couple of possible solutions:

  • Take a string in the same format as svg paths. This is a well known format, but would probably not be so ergonomical to use so I am not really a fan.

  • Extend the type system with a path type and add the operations above as constructors of this type. I think that adding an explicit type would introduce unnecessary complexity, but I think maybe as a dynamic type that implements join this could be a nice solution.

  • Same as above but instead of adding a type as above we could simply introduce functions that return single element arrays with dicts on the form of (op: "moveto", x: 5.0, y: 4.0) . The arrays would be joined together in a code block so that one could easily write complex paths.
    ...

    moveto(x: 10.0, y: 10.0)
    arcto(r: 4.0, ang: 9

So you want to add the internal API to the language itself? I think this sounds intresting, although i believe the syntax is a bit weird. You're suddenly in another syntax-context. What about somethink like lineto(path_obj, dx: 5pt)? I think this would make more sense.

@birktj
Copy link
Contributor

birktj commented Apr 1, 2023

Not really (if I understand you correctly), the language already works this way. Consider the following code which works today:

#let moveto(x, y) = ((op: "moveto", x: x, y: y),)
#let ops = {
  moveto(1pt, 2pt)
  moveto(5pt, 5pt)
};
#assert(ops == ((op: "moveto", x: 1pt, y: 2pt), (op: "moveto", x: 5pt, y: 5pt)))

I find it works well thinking of the typst language as a pure immutable functional language that masquerades as a procedural language with some syntactic sugar.

@laurmaedje
Copy link
Member

I agree that your proposal fits quite well with Typst's design. The only thing I don't like too much is adding all these path ops to the global scope. And people will just try to insert them into their document probably and will see a dictionary instead of a path segment. But I don't really have a better idea.

@birktj
Copy link
Contributor

birktj commented Apr 2, 2023

I have the same concern and can think of two potential solutions:

  • Make path take a function with an ctx argument that is a module with all of these functions. I don't really know if this is possible today, but to me it seems that it should be.
  • Put all of these ops into a draw module at the global scope

@laurmaedje
Copy link
Member

Yes, both should be possible, although the first one makes it a bit difficult to integrate with the automatically generated documentation. And you can't have mutation across the creation of multiple paths by forcing use of a closure.

@SekoiaTree SekoiaTree mentioned this issue Apr 2, 2023
@Enivex Enivex mentioned this issue Apr 4, 2023
@birktj
Copy link
Contributor

birktj commented Apr 7, 2023

I see that path support was merged in #536 now, is there still interest for a slightly more ergonomic canvas-like api? I started working on an implementation last week that I am wondering if I should finish.

@laurmaedje
Copy link
Member

All primitives requested in the original issue are now implemented. There isn't a more ergonomic canvas-like API at the moment, but that's separate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request visualize Related to drawing and visualizations.
Projects
None yet
Development

No branches or pull requests

4 participants