processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.61k stars 3.31k forks source link

Issues with stroke join for text #5408

Open dhowe opened 3 years ago

dhowe commented 3 years ago

Note that this only occurs when strokeWeight is large in relation to textSize Setting strokeJoin(ROUND) or strokeJoin(BEVEL) eliminates the problem

Screenshot 2021-09-13 at 1 17 31 PM

Related to #3035 -- steps to reproduce: show font with stroke and large relative strokeWeight:

function setup() {
  createCanvas(750, 500);
  background(150);

  textFont(kingthings);
  textSize(42);

  strokeWeight(4);
  //strokeJoin(ROUND);//BEVEL
  stroke(0);

  fill(255);
  text("if I found a fun igloo", 100, 200);
}

Most appropriate sub-area of p5.js?

Details about the bug:

limzykenneth commented 3 years ago

Is it the same problem as #3035?

dhowe commented 3 years ago

Definitely related, as noted above...

limzykenneth commented 3 years ago

Does it also happens if this font is rendered in something like Illustrator? Shall we reconsider adding a new miter limit function as proposed before?

golanlevin commented 3 years ago

So, this visual glitch is 'expected behavior', as others have pointed out. If a font (or other shape) has a zig-zag with sufficiently pointy angles, then this is what will happen, period. It is a fundamental geometric property of 2D graphics.

Just my two cents, but:

Possible solutions to the issue, from most to least preferable in my opinion, are:

limzykenneth commented 3 years ago

I tend to lean towards adding a new function to control this as well. I found before that setting a lower default may cause other drawing issues such as not being able to draw star shape with strokes so I wouldn't recommend it.

However also to add that with the native canvas API, the miter limit can be set with something like below:

canvas = createCanvas(200, 200);
let context = canvas.elt.getContext("2d");
context.miterLimit = 2;
dhowe commented 3 years ago

Easy enough to add a strokeMiterLimit() or similar function... though, as there are existing options, setting strokeJoin() or canvas miter limit (also canvas lineJoin property), perhaps documentation somewhere would suffice (maybe an example on the strokeJoin page)?

outofambit commented 3 years ago

I'm on board with adding a new function for setting a stroke miter limit and adding documentation in strokeJoin, but I'm also really curious about:

Make the problem disappear by changing the default strokeJoin for fonts to be ROUND (as PhotoShop does)

Are there any significant downsides to doing this? It seems like barely perceptible difference for the (probably) vast majority of cases and makes this not an issue folks would hit when playing with large stroke widths.

I think configurability for this is good, but good defaults are good too!

limzykenneth commented 3 years ago

Make the problem disappear by changing the default strokeJoin for fonts to be ROUND (as PhotoShop does)

For a star shape it would mean the points are not "pointy" as they will be rounded, not inherently a problem but also not an uncommon thing that is expected by the user. It can work as a default but we may also need configurability for it.

munusshih commented 1 year ago

Hi! I'm working on this issue as part of my GSoC project. I think adding a textMiterLimit() function makes sense. I'm wondering more about if there's any push back against changing the default context.miterLimit = 1?

limzykenneth commented 1 year ago

@munusshih Instead of textMiterLimit(), the proposed strokeMiterLimit() will probably be more intuitive since this affects all shapes drawn with strokes too.

I would prefer leaving the HTML canvas default (10.0) instead of changing it to 1 as the default here or it could break the behaviour of existing sketch. We can add a short note in the relevant documentation pages hinting that strokeMiterLimit() can be used to change the behaviour.

davepagurek commented 1 year ago

Although WebGL text doesn't support strokes, WebGL strokes for other shapes also have a bit of a miter limit going on in here:

https://github.com/processing/p5.js/blob/679218522c0daeb61c50da7adae42e31bdc01920/src/webgl/shaders/line.vert#L178-L186

It's probably fine to not implement this for WebGL too at the same time, but if we don't, we can maybe make an issue for it so that we remember to implement it there too eventually!

munusshih commented 1 year ago

This is in the making here #6331