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 layer colour and pen width customisation API #205

Open
abey79 opened this issue Jan 16, 2022 · 5 comments
Open

Add layer colour and pen width customisation API #205

abey79 opened this issue Jan 16, 2022 · 5 comments

Comments

@abey79
Copy link
Owner

abey79 commented Jan 16, 2022

Metadata, and in particular layer color & pen width customisation, was added in vpype in abey79/vpype#359. Although It can be immediately used in vsketch via vsk.vpype(), a proper API must be added.

Layer color

In Processing, the color is set with stroke(). In (plotter-centric) vsketch, one must choose a specific pen rather than a colour and thus vsk.stroke() takes a layer ID.

I initially see two possible ways to add colour API:

  1. Stick close to Processing and extend vsk.stroke():

    vsk.stroke(2, color="red")  # any valid SVG color accepted
    vsk.stroke(2, "#f00")  # keyword argument optional
  2. Add a dedicated function, similar to vsk.penWidth():

    vsk.stroke(2)
    vsk.penColor("red", 2)

I'm currently leaning towards (2) because of the consistency with vsk.penWidth() and because of the separation of the plotter configuration logic from drawing logic. In particular, it is rather typical to call vsk.stroke() on a given layer multiple time. In this case, only the last value of color would be considered, which may result in potentially unexpected result. For example, the following would be all green (not half-red, half-green):

vsk.stroke(1, "red")
# draw stuff

vsk.stroke(2)
# do stuff with other layer IDS

vsk.stroke(1, "green")
# draw more stuff

This looks probably better:

vsk.penColor("green", 1)

vsk.stroke(1)
# draw stuff

vsk.stroke(2)
# do stuff with other layer IDS

vsk.stroke(1)
# draw more stuff

Pen width

The best course of action is probably to stick with the existing vsk.penWidth().

One small issue is the default pen width variant (vsk.penWidth("0.1mm")), which applies to all existing and future layers for which a pen width hasn't been specifically provided. This could be mistaken with setting the color of the "current" layer. Since there is no such a thing as one current layer (a current stroke layer and/or a current fill layer may or may not be defined), this latter behaviour would be difficult to actually implement.

@abey79
Copy link
Owner Author

abey79 commented Jan 16, 2022

Another avenue would be a new, combined API.

Pen configuration

Both color and pen width, and other properties (such as name or custom properties) could be set with a single API call:

vsk.penConfig(1, "red", "0.1mm")  # set color and pen width on layer 1 (positional args)
vsk.penConfig(2, width="3px")   # set pen width on layer 2
vsk.penConfig(1, color="#ff0", name="My first pen")  # set color and vp:name on layer 1
vsk.penConfig([1, 2, 3], my_prop="my_value")   # set arbitrary property on multiple layers

Pro:

  • less code for pen/layer configuration
  • layer name support
  • generic property support
  • emphasis on plotter configuration logic being separated from drawing logic

Cons:

  • redundant with existing vsk.penWidth()
  • further and further from the original Processing spirit

@hapiel
Copy link

hapiel commented Jan 16, 2022

I vote for penConfig.
penColor is nice too, but I have an issue with penWidth:

I set penWidth to be the distance between lines in double strokes or fills. And I've used that for stylish purposes, not necessarily the true width of the pen, for example if I just want 2 lines drawn next to each other.

For that I'd suggest changing penWidth to something like penSpacing, but that's a whole issue altogether. Should this route be taken then penWidth and penColor could be used. But since that's likely to lead to confusion and compatibility issues, penConfig is the best alternative, as I see it.

@abey79
Copy link
Owner Author

abey79 commented Jan 16, 2022

@hapiel If I understand correctly, you address two orthogonal points.

The "liberal" use of the pen width for stylistic purposes.

Although there is nothing inherently wrong about it, this is not the intention behind the pen width parameter. The actual intention is to accurately emulate thick lines and 100% fills with a plotter. For example, there is no guarantee that the current hatching pattern won't be changed to something entirely different if it works better. This would potentially break stylistic endeavours relying on this mechanism. Likewise, I hope to add strokeCap() at some point. This may affect how thick lines are drawn.

In general, I would advise the client code to properly implement such stylistic feature for better controllability and future proofing (e.g. using shapely's buffer(), etc.

For records, I'm not excluding adding explicit support for stylistic features in the future -- much to the contrary. I'd love to have the capability to emulate gritty-looking lines (I've had a proto of this for ages actually), brush-like strokes, etc. If this ever happens, the proper API for this should refer to "stroke" (e.g. vsk.strokeStyle("gritty")) as opposed to "pen", the idea being that "stroke" refers to the mark to be applied on paper (in all its potential complexity) and "pen" refers to the physical tool used to that end.

The actual API for setting the pen width parameter.

With the above out of the way, I note a weak vote in favour of penConfig() vs. multiple calls such as penColor(), layerName(), etc.

Did I miss something?

@hapiel
Copy link

hapiel commented Jan 16, 2022

Correct.

Yes, I understand my 'liberal' usage is not as intended, but it's a neat bonus feature that becomes more difficult to use if penWidth() also controls the pen style in the viewer. I'd be surprised if I was the first to use penWidth() in that way ;).

And of course, if you end up changing that feature that is fine as there will be plenty of other ways to achieve the same effects!

Oh and I definitely vote against the option of vsk.stroke(2, color="red")

@abey79
Copy link
Owner Author

abey79 commented Jan 16, 2022

Yes, it should be expected that the viewer will now follow the pen width defined by the sketch. If this is a big issue, this might be a way to work around it: abey79/vpype#377.

Again, the proper way to deal with this is, IMO, a proper stroke styling mechanism. Thinking of it, a first iteration of this could be based strictly on client code. What do you think about #206?

Your vote is duly noted. I'm myself leaning toward vsk.penConfig(). We're pre-1.0, I can break stuff however I want :)

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

No branches or pull requests

2 participants