cparnot / ASCIImage

Create UIImage / NSImage instances with NSString and ASCII art
MIT License
1.52k stars 76 forks source link

Have way to specifying subpaths #7

Open MrNoodle opened 9 years ago

MrNoodle commented 9 years ago

Paths need not be contiguous and having composite paths are necessary to have shapes with holes in them. Personally, I think all paths in one ASCII representation should be part of one path and you would use multiple paths/representations for separate shapes. But if you want to work it all into a single rep then that's your choice.

cparnot commented 9 years ago

My main concern in forcing to split everything in multiple paths is that something like this becomes suddenly more tedious:

  @"· · · · 1 1 1 · · · ·",
  @"· · 1 · · · · · 1 · ·",
  @"· 1 · · · · · · · 1 ·",
  @"1 · · 2 · · · 3 · · 1",
  @"1 · · · # · # · · · 1",
  @"1 · · · · # · · · · 1",
  @"1 · · · # · # · · · 1",
  @"1 · · 3 · · · 2 · · 1",
  @"· 1 · · · · · · · 1 ·",
  @"· · 1 · · · · · 1 · ·",
  @"· · · 1 1 1 1 1 · · ·",

Now, you have to split it in 2 separate layers:

  @"· · · · 1 1 1 · · · ·",
  @"· · 1 · · · · · 1 · ·",
  @"· 1 · · · · · · · 1 ·",
  @"1 · · · · · · · · · 1",
  @"1 · · · · · · · · · 1",
  @"1 · · · · · · · · · 1",
  @"1 · · · · · · · · · 1",
  @"1 · · · · · · · · · 1",
  @"· 1 · · · · · · · 1 ·",
  @"· · 1 · · · · · 1 · ·",
  @"· · · 1 1 1 1 1 · · ·",

  @"· · · · · · · · · · ·",
  @"· · · · · · · · · · ·",
  @"· · · · · · · · · · ·",
  @"· · · 2 · · · 3 · · ·",
  @"· · · · # · # · · · ·",
  @"· · · · · # · · · · ·",
  @"· · · · # · # · · · ·",
  @"· · · 3 · · · 2 · · ·",
  @"· · · · · · · · · · ·",
  @"· · · · · · · · · · ·",
  @"· · · · · · · · · · ·",

Separating into multiple layers should only be done if it helps 'seeing' the final image IMO.

I propose that separate paths be defined by skipping 2 characters, while skipping 1 character only create subpaths. It would break existing ASCII art, but that's fine, there is only one app shipping some.

MrNoodle commented 9 years ago

Fair enough though I would argue in for that particular icon, you want a composite path as the X should be clear and not painted white.

cparnot commented 9 years ago

Fair enough though I would argue in for that particular icon, you want a composite path as the X should be clear and not painted white.

Yes, and that's another issue I have faced: using [NSColor clearColor] indeed does not work when drawing all the shape in the same context (same for the lock example). It's another thing that would be nice: allow compositing of the bezier paths instead of just layering.

Your approach would allow to do it in code, but wouldn't it be nice to have some kind of composite property so ASCIImage can do it for you? :-)

MrNoodle commented 9 years ago

Well, again, I think a compound path is the solution here. In your example, you draw the circle, then you draw the outline of the X. Depending on winding rule, you may have to make sure to draw the X in the opposite direction of the circle. That allows you to draw shapes with holes instead of having to draw shapes on top of eachother to simulate holes.

I know I seem to be pimping my blog but relevant article: http://www.noodlesoft.com/blog/2006/11/30/mmmdonuts/

The lock example is a bit trickier since you'd need a way to draw a semicircle. I thought about adding support for drawing arcs though the syntax for it can get messy since there's a bit more data you have to specify.

cparnot commented 9 years ago

Ah, very nice, thanks for pointing that out! That's indeed one more strong argument for coumpound paths. In this particular case,the X is not a closed path, though: just 2 lines. Not sure it could be done quite the same way. I also could not find a method to convert a stroke into a closed path (stroke outline).

I had considered arcs as well, but indeed not sure how to do it right. One way for indivual arcs would be to pass that as a parameter in the context, but that does not help in connecting an arc to another path (well, I suppose the order of the character sequence could be taken into account in that case...).

cparnot commented 9 years ago

Ah, got it: CGContextReplacePathWithStrokedPath() http://stackoverflow.com/questions/2737973/on-osx-how-do-i-gradient-fill-a-path-stroke/2770034#2770034