2
\$\begingroup\$

Challenge

Premise

It's 2006, and Alice is trying to send Bob their her completed notes on their newly ended expeditions into the labyrinthine school library, which the two of them found suffers from a bad case of non-Euclidean geometry.1

For some reason, Alice originally created her notes, which consist of black text on a white background, using SVG. What a genius. It hits her now that Bob doesn't have a single device that will display SVG! I mean, she accidentally fried it the last time she paid him a visit at his place.

She decides to send him a black-on-white raster rendering without anti-aliasing of any sort. Of course, she's going to do it with code. Her, since it figures that Bob would be the sort to take to hardware rather than software.2 Regardless, Alice can't go back on her word, so she supposes she's got to see it through. She thinks Bob should consider himself lucky that she has so much time to spend on their her notes…

1. Don't get the wrong idea! She's only sending them because he asked nicely, not because she's got any sympathy for boys who play Quake III Arena for eight hours at night (or whatever it is they do) and create only the barest skeleton of notes on their own.

2. She also, mysteriously, hasn't got a capable OS, but that's another story.

Task

Help Alice draw rasterised glyphs. She'll re-use and position them by herself, tasks that are trivial in comparison.

Input:

  • First take a string whose contents are an SVG path definition (d attribute) defining a single glyph. Only lines and cubic Béziers will be used. You only need to consider upper-case commands. Each pair of coordinates will be comma-separated. All coordinates will be given to one decimal place. Please refer to the examples.
    • There may or may not be whitespace at the top and/or left of the glyph.
  • Next, take an integer \$10\leq n\leq72\$ representing the height of the output described below.

Output: A matrix (actual type: 2D array or equivalent) of 1s and 0s where a 1 represents a pixel to be coloured black and a 0, white. The matrix is to be scaled to a height of \$n\$, maintaining the glyph's aspect ratio as far as possible. A 1 must appear where and only where, ideally, using vector graphics, more than or exactly 50% of the corresponding space would be black.

  • For standardisation purposes, compute the output as though there were no whitespace borders in the input.

In every example below, for reasons of clarity only, the output substitutes X for 1 and [space] for 0.

Examples

Run the following snippet to view them.

body { font-family: verdana; }
table, th, td {
  border: 1px solid black;
  border-collapse: collapse;
}
th, td { padding: 5px; }
td { vertical-align: top; }
.w { width: 60%; }
.g { background-color: #eee; }
.m {
  font-family: monospace;
  padding: .2em;
}
.a { line-height: .7em !important; }
.s { font-size: 85%; }
<h2>Example 1</h2>
<table>
<tr><th>Input</th><th>Image from path definition</th></tr>
<tr><td class="w" rowspan="3"><span class="g m">
M 60.0,10.0 L 85.3,79.7 C 86.3,82.3 87.1,84.1 87.9,85.0 C 88.7,85.9 89.8,86.6 91.2,87.1 L 96.6,88.7 L 96.7,91.1 C 91.7,91.0 87.1,90.9 82.9,90.9 C 78.5,90.9 73.4,91.0 67.5,91.1 L 67.3,88.7 L 72.7,87.1 C 73.5,86.8 74.0,86.6 74.3,86.2 C 74.7,85.9 74.8,85.4 74.8,84.7 C 74.8,83.9 74.6,82.9 74.2,81.7 C 73.8,80.4 73.3,78.8 72.5,76.8 L 67.2,61.5 L 39.7,61.5 L 33.7,76.7 C 32.9,78.8 32.3,80.5 31.9,81.8 C 31.4,83.0 31.2,84.0 31.2,84.7 C 31.2,85.4 31.4,85.9 31.7,86.2 C 32.1,86.6 32.6,86.8 33.3,87.0 L 38.6,88.5 L 38.7,91.1 C 33.4,91.0 28.9,90.9 25.5,90.9 C 22.1,90.9 18.3,91.0 14.1,91.1 L 13.8,88.7 L 19.5,86.9 C 21.0,86.4 22.1,85.7 22.7,84.8 C 23.4,83.8 24.2,82.4 25.0,80.3 L 54.1,10.8 L 60.0,10.0 z M 41.8,56.3 L 65.3,56.3 L 54.2,24.9 L 41.8,56.3 z
<br><br>
11
</span><td>
<svg width="125" height="110" xmlns="http://www.w3.org/2000/svg">
<path style="fill:#000;" d="M 60.0,10.0 L 85.3,79.7 C 86.3,82.3 87.1,84.1 87.9,85.0 C 88.7,85.9 89.8,86.6 91.2,87.1 L 96.6,88.7 L 96.7,91.1 C 91.7,91.0 87.1,90.9 82.9,90.9 C 78.5,90.9 73.4,91.0 67.5,91.1 L 67.3,88.7 L 72.7,87.1 C 73.5,86.8 74.0,86.6 74.3,86.2 C 74.7,85.9 74.8,85.4 74.8,84.7 C 74.8,83.9 74.6,82.9 74.2,81.7 C 73.8,80.4 73.3,78.8 72.5,76.8 L 67.2,61.5 L 39.7,61.5 L 33.7,76.7 C 32.9,78.8 32.3,80.5 31.9,81.8 C 31.4,83.0 31.2,84.0 31.2,84.7 C 31.2,85.4 31.4,85.9 31.7,86.2 C 32.1,86.6 32.6,86.8 33.3,87.0 L 38.6,88.5 L 38.7,91.1 C 33.4,91.0 28.9,90.9 25.5,90.9 C 22.1,90.9 18.3,91.0 14.1,91.1 L 13.8,88.7 L 19.5,86.9 C 21.0,86.4 22.1,85.7 22.7,84.8 C 23.4,83.8 24.2,82.4 25.0,80.3 L 54.1,10.8 L 60.0,10.0 z M 41.8,56.3 L 65.3,56.3 L 54.2,24.9 L 41.8,56.3 z"/>
</svg>
</td></tr>
<tr><th>Output</th></tr>
<tr><td><pre class="a g">
      X     
     XX     
     XXX    
    X XX    
    X  X    
   X   XX   
   XXXXXX   
   X    XX  
  X     XX  
  X      X  
XXX     XXXX
</pre></td></tr></table>

<h2>Example 2</h2>
<table>
<tr><th>Input</th><th>Image from path definition</th><th>Output</th></tr>
<tr><td><span class="g m">
M 40.0,10.0 C 44.3,10.2 48.5,10.2 52.4,10.2 C 56.4,10.2 60.5,10.2 64.8,10.0 L 65.0,12.2 L 58.8,14.0 C 58.0,14.2 57.6,14.7 57.5,15.6 C 57.5,16.7 57.4,18.0 57.4,19.4 C 57.4,20.8 57.4,22.3 57.4,23.9 L 57.4,69.3 C 57.4,72.5 57.3,75.5 57.0,78.2 C 56.8,80.9 56.3,83.3 55.7,85.4 C 55.0,87.5 54.2,89.4 53.0,91.0 C 51.9,92.7 50.4,94.1 48.6,95.4 C 46.9,96.7 44.7,97.8 42.2,98.8 C 39.7,99.8 36.7,100.7 33.3,101.5 L 32.6,99.0 C 36.0,97.5 38.8,95.9 40.7,94.1 C 42.7,92.3 44.2,90.3 45.2,88.0 C 46.3,85.8 46.9,83.2 47.2,80.4 C 47.5,77.6 47.6,74.4 47.6,70.8 L 47.6,24.1 C 47.6,22.4 47.6,20.9 47.6,19.5 C 47.6,18.2 47.6,16.9 47.5,15.8 C 47.5,15.0 47.1,14.4 46.3,14.1 L 40.1,12.2 L 40.0,10.0 Z
<br><br>
20
</span></td><td>
<svg width="125" height="110" xmlns="http://www.w3.org/2000/svg">
<path style="fill:#000;" d="M 40.0,10.0 C 44.3,10.2 48.5,10.2 52.4,10.2 C 56.4,10.2 60.5,10.2 64.8,10.0 L 65.0,12.2 L 58.8,14.0 C 58.0,14.2 57.6,14.7 57.5,15.6 C 57.5,16.7 57.4,18.0 57.4,19.4 C 57.4,20.8 57.4,22.3 57.4,23.9 L 57.4,69.3 C 57.4,72.5 57.3,75.5 57.0,78.2 C 56.8,80.9 56.3,83.3 55.7,85.4 C 55.0,87.5 54.2,89.4 53.0,91.0 C 51.9,92.7 50.4,94.1 48.6,95.4 C 46.9,96.7 44.7,97.8 42.2,98.8 C 39.7,99.8 36.7,100.7 33.3,101.5 L 32.6,99.0 C 36.0,97.5 38.8,95.9 40.7,94.1 C 42.7,92.3 44.2,90.3 45.2,88.0 C 46.3,85.8 46.9,83.2 47.2,80.4 C 47.5,77.6 47.6,74.4 47.6,70.8 L 47.6,24.1 C 47.6,22.4 47.6,20.9 47.6,19.5 C 47.6,18.2 47.6,16.9 47.5,15.8 C 47.5,15.0 47.1,14.4 46.3,14.1 L 40.1,12.2 L 40.0,10.0 Z"/>
</svg>
</td><td><pre class="a g">
 XXXXX
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
  XX  
 XX   
XX    
</pre></td></tr></table>

<h2>Example 3</h2>
<table>
<tr><th>Input</th><th>Image from path definition</th></tr>
<tr><td class="w" rowspan="3"><span class="g m">
M 80.0,40.0 C 80.0,50.8 77.1,59.6 71.5,66.3 C 65.8,73.0 58.4,76.9 49.2,77.9 C 51.9,85.6 58.9,89.5 70.1,89.5 C 74.6,89.5 78.7,88.8 82.3,87.4 L 82.8,89.7 C 75.9,95.2 70.5,97.9 66.5,97.9 C 53.9,97.9 45.8,91.4 42.3,78.3 C 31.3,78.3 22.8,75.1 16.7,68.6 C 10.6,62.2 7.5,53.4 7.5,42.3 C 7.5,30.7 10.8,21.6 17.4,14.9 C 24.0,8.1 33.1,4.8 44.8,4.8 C 56.0,4.8 64.7,7.9 70.8,14.2 C 76.9,20.5 80.0,29.0 80.0,40.0 L 80.0,40.0 z M 18.5,40.6 C 18.5,51.5 20.7,59.8 25.1,65.6 C 29.5,71.4 35.9,74.3 44.4,74.3 C 52.8,74.3 59.0,71.7 63.0,66.4 C 67.0,61.2 69.0,52.9 69.0,41.7 C 69.0,31.1 66.9,23.0 62.6,17.3 C 58.4,11.7 51.8,8.8 43.0,8.8 C 34.4,8.8 28.2,11.5 24.3,16.7 C 20.4,22.0 18.5,29.9 18.5,40.6 L 18.5,40.6 Z
<br><br>
10
</span><td>
<svg width="125" height="110" xmlns="http://www.w3.org/2000/svg">
<path style="fill:#000;" d="M 80.0,40.0 C 80.0,50.8 77.1,59.6 71.5,66.3 C 65.8,73.0 58.4,76.9 49.2,77.9 C 51.9,85.6 58.9,89.5 70.1,89.5 C 74.6,89.5 78.7,88.8 82.3,87.4 L 82.8,89.7 C 75.9,95.2 70.5,97.9 66.5,97.9 C 53.9,97.9 45.8,91.4 42.3,78.3 C 31.3,78.3 22.8,75.1 16.7,68.6 C 10.6,62.2 7.5,53.4 7.5,42.3 C 7.5,30.7 10.8,21.6 17.4,14.9 C 24.0,8.1 33.1,4.8 44.8,4.8 C 56.0,4.8 64.7,7.9 70.8,14.2 C 76.9,20.5 80.0,29.0 80.0,40.0 L 80.0,40.0 z M 18.5,40.6 C 18.5,51.5 20.7,59.8 25.1,65.6 C 29.5,71.4 35.9,74.3 44.4,74.3 C 52.8,74.3 59.0,71.7 63.0,66.4 C 67.0,61.2 69.0,52.9 69.0,41.7 C 69.0,31.1 66.9,23.0 62.6,17.3 C 58.4,11.7 51.8,8.8 43.0,8.8 C 34.4,8.8 28.2,11.5 24.3,16.7 C 20.4,22.0 18.5,29.9 18.5,40.6 L 18.5,40.6 Z"/>
</svg>
</td></tr>
<tr><th>Output</th></tr>
<tr><td><pre class="a g">
  XXXX  
 X    X 
X     XX
X      X
X      X
X     X 
 X    X 
  XXXX  
    X   
     XXX
</pre></td></tr></table>

<h2>Example 4</h2>
<table>
<tr><th>Input</th><th>Image from path definition</th><th>Output</th></tr>
<tr><td><span class="g m">
M 80.0,40.0 C 80.0,50.8 77.1,59.6 71.5,66.3 C 65.8,73.0 58.4,76.9 49.2,77.9 C 51.9,85.6 58.9,89.5 70.1,89.5 C 74.6,89.5 78.7,88.8 82.3,87.4 L 82.8,89.7 C 75.9,95.2 70.5,97.9 66.5,97.9 C 53.9,97.9 45.8,91.4 42.3,78.3 C 31.3,78.3 22.8,75.1 16.7,68.6 C 10.6,62.2 7.5,53.4 7.5,42.3 C 7.5,30.7 10.8,21.6 17.4,14.9 C 24.0,8.1 33.1,4.8 44.8,4.8 C 56.0,4.8 64.7,7.9 70.8,14.2 C 76.9,20.5 80.0,29.0 80.0,40.0 L 80.0,40.0 z M 18.5,40.6 C 18.5,51.5 20.7,59.8 25.1,65.6 C 29.5,71.4 35.9,74.3 44.4,74.3 C 52.8,74.3 59.0,71.7 63.0,66.4 C 67.0,61.2 69.0,52.9 69.0,41.7 C 69.0,31.1 66.9,23.0 62.6,17.3 C 58.4,11.7 51.8,8.8 43.0,8.8 C 34.4,8.8 28.2,11.5 24.3,16.7 C 20.4,22.0 18.5,29.9 18.5,40.6 L 18.5,40.6 Z
<br><br>
50
</span></td><td>
<svg width="125" height="110" xmlns="http://www.w3.org/2000/svg">
<path style="fill:#000;" d="M 80.0,40.0 C 80.0,50.8 77.1,59.6 71.5,66.3 C 65.8,73.0 58.4,76.9 49.2,77.9 C 51.9,85.6 58.9,89.5 70.1,89.5 C 74.6,89.5 78.7,88.8 82.3,87.4 L 82.8,89.7 C 75.9,95.2 70.5,97.9 66.5,97.9 C 53.9,97.9 45.8,91.4 42.3,78.3 C 31.3,78.3 22.8,75.1 16.7,68.6 C 10.6,62.2 7.5,53.4 7.5,42.3 C 7.5,30.7 10.8,21.6 17.4,14.9 C 24.0,8.1 33.1,4.8 44.8,4.8 C 56.0,4.8 64.7,7.9 70.8,14.2 C 76.9,20.5 80.0,29.0 80.0,40.0 L 80.0,40.0 z M 18.5,40.6 C 18.5,51.5 20.7,59.8 25.1,65.6 C 29.5,71.4 35.9,74.3 44.4,74.3 C 52.8,74.3 59.0,71.7 63.0,66.4 C 67.0,61.2 69.0,52.9 69.0,41.7 C 69.0,31.1 66.9,23.0 62.6,17.3 C 58.4,11.7 51.8,8.8 43.0,8.8 C 34.4,8.8 28.2,11.5 24.3,16.7 C 20.4,22.0 18.5,29.9 18.5,40.6 L 18.5,40.6 Z"/>
</svg>
</td><td><pre class="a g s">
               XXXXXXXX                
           XXXXXXXXXXXXXXXX            
        XXXXXXX     XXXXXXXXX          
       XXXXX           XXXXXXX         
      XXXX                XXXXXX       
     XXXX                  XXXXXX      
    XXXX                    XXXXXX     
   XXXXX                     XXXXX     
   XXXXX                     XXXXXX    
  XXXXX                       XXXXX    
 XXXXXX                       XXXXXX   
 XXXXXX                         XXXX   
XXXXXXX                         XXXXX  
XXXXXX                          XXXXX  
XXXXXX                          XXXXX  
XXXXXX                          XXXXX  
XXXXXX                          XXXXX  
XXXXXX                          XXXXX  
XXXXXX                          XXXXX  
XXXXXX                          XXXXX  
XXXXXX                          XXXXX  
XXXXXX                          XXXXX  
XXXXXX                          XXXXX  
XXXXXX                         XXXXXX  
 XXXXX                         XXXXXX  
 XXXXXX                        XXXXXX  
 XXXXXX                        XXXXXX  
 XXXXXX                        XXXXX   
  XXXXX                        XXXX    
  XXXXXX                      XXXXX    
  XXXXXX                      XXXXX    
   XXXXXX                     XXXX     
    XXXXX                    XXX       
     XXXXX                  XXX        
     XXXXXX                XXX         
       XXXXXX             XXX          
       XXXXXXX           XXX           
         XXXXXXXXXXXXXXXXXX            
            XXXXXXXXXXXXX              
                  XXX                  
                  XXXX                 
                  XXXXX                
                   XXXX                
                   XXXXX               
                    XXXXXX            X
                    XXXXXXXXXXXXXXXXXXX
                     XXXXXXXXXXXXXXXX  
                      XXXXXXXXXXXXXXX  
                        XXXXXXXXXXX    
                           XXXXX       
</pre></td></tr></table>

<h2>Credit</h2>
<a href="https://upload.wikimedia.org/wikipedia/commons/4/4c/Latin_Alphabet.svg">Wikimedia Commons</a>

Remarks

\$\endgroup\$
1
  • \$\begingroup\$ For standardisation purposes, compute the output as though there were no whitespace borders in the input. ~> I'm not sure to understand this rule. It seems like we need to compute the bounding box of the path if we want to get your example outputs -- which is equivalent to removing the top, right, bottom and left borders. \$\endgroup\$
    – Arnauld
    Jun 27 '20 at 10:56
4
\$\begingroup\$

JavaScript (ES7),  364  352 bytes

Expects (path)(height).

f=
p=>h=>([x,y,X,Y]=[0,1,2,3].map(i=>Math[i&2?'max':'min'](...p.match(/\d+\S+/g).map(s=>+s.split`,`[i&1]))+.5|0),C=document.createElement`canvas`.getContext`2d`).fill(new Path2D(p))&C.getImageData(x,y,X-=x,Y-=y).data.map((v,i)=>!v|i%4-3?0:m[(i>>=2)/X*h/Y|0][i%X*h/Y|0]++,m=[...Array(h)].map(_=>Array(X*h/Y|0).fill(0)))||m.map(r=>r.map(v=>+(v>(Y/h)**2/2)))

o.innerHTML = f("M 80.0,40.0 C 80.0,50.8 77.1,59.6 71.5,66.3 C 65.8,73.0 58.4,76.9 49.2,77.9 C 51.9,85.6 58.9,89.5 70.1,89.5 C 74.6,89.5 78.7,88.8 82.3,87.4 L 82.8,89.7 C 75.9,95.2 70.5,97.9 66.5,97.9 C 53.9,97.9 45.8,91.4 42.3,78.3 C 31.3,78.3 22.8,75.1 16.7,68.6 C 10.6,62.2 7.5,53.4 7.5,42.3 C 7.5,30.7 10.8,21.6 17.4,14.9 C 24.0,8.1 33.1,4.8 44.8,4.8 C 56.0,4.8 64.7,7.9 70.8,14.2 C 76.9,20.5 80.0,29.0 80.0,40.0 L 80.0,40.0 z M 18.5,40.6 C 18.5,51.5 20.7,59.8 25.1,65.6 C 29.5,71.4 35.9,74.3 44.4,74.3 C 52.8,74.3 59.0,71.7 63.0,66.4 C 67.0,61.2 69.0,52.9 69.0,41.7 C 69.0,31.1 66.9,23.0 62.6,17.3 C 58.4,11.7 51.8,8.8 43.0,8.8 C 34.4,8.8 28.2,11.5 24.3,16.7 C 20.4,22.0 18.5,29.9 18.5,40.6 L 18.5,40.6 Z")(20).map(r => r.map(v => ' X'[v]).join('')).join('\n')
<pre id=o></pre>

Commented

p => h =>                        // p = path, h = height
( [x, y, X, Y] =                 // find the bounding box (x, y) - (X, Y)
  [0, 1, 2, 3].map(i =>          // for i = 0 to 3:
    Math[i & 2 ? 'max' : 'min']( //   get the max if i > 1, or the min otherwise:
      ...p.match(/\d+\S+/g)      //     match all coordinates
      .map(s =>                  //     for each of them:
        +s.split`,`[i & 1]       //       keep x if i is even, or y if i is odd
      )                          //     end of inner map()
    ) + .5 | 0                   //   end of Math.min or Math.max; round the result
  ),                             // end of outer map()
  C = document.createElement     // create a canvas and get its 2D context C
      `canvas`.getContext`2d`    //
).fill(new Path2D(p)) &          // draw the path in the canvas
C.getImageData(                  // turn X into the width and Y into the height
  x, y, X -= x, Y -= y           //
).data.map((v, i) =>             // for each value at position i in the context data:
  !v |                           //   if v is not set
  i % 4 - 3 ?                    //   or this is not a transparency field:
    0                            //     do nothing
  :                              //   else:
    m[(i >>= 2) / X * h / Y | 0] //     increment m[] at the position obtained by
    [i % X * h  / Y | 0]++,      //     rescaling ((i >> 2) / X, (i >> 2) % X)
                                 //     according to the ratio h / Y
  m =                            //   initialize m[] to a matrix of size
    [...Array(h)].map(_ =>       //   floor(X * h / Y) x h,
      Array(X * h / Y | 0)       //
      .fill(0)                   //   filled with 0's
    )                            //
) ||                             // end of map()
m.map(r =>                       // for each row r[] in m[]:
  r.map(v =>                     //   for each value v in m[]:
    +(v > (Y / h) ** 2 / 2)      //     set v to 1 if it's greater than the threshold
  )                              //   end of inner map()
)                                // end of outer map()
\$\endgroup\$
0
\$\begingroup\$

HTML5 + ES6, 320 bytes

with(c.getContext`2d`)f=(d,h)=>(p.setAttribute("d",d),b=p.getBBox(),c.height=h,c.width=w=h*b.width/b.height,scale(s=h/b.height,s),translate(-b.x,-b.y),fill(new Path2D(d)),[...getImageData(0,0,w,h).data.filter((_,i)=>!(3&~i))].map(i=>` X`[i>>7]).join``.match(RegExp(`.{${c.width}}`,`g`)).join`
`)
console.log(f("M 80.0,40.0 C 80.0,50.8 77.1,59.6 71.5,66.3 C 65.8,73.0 58.4,76.9 49.2,77.9 C 51.9,85.6 58.9,89.5 70.1,89.5 C 74.6,89.5 78.7,88.8 82.3,87.4 L 82.8,89.7 C 75.9,95.2 70.5,97.9 66.5,97.9 C 53.9,97.9 45.8,91.4 42.3,78.3 C 31.3,78.3 22.8,75.1 16.7,68.6 C 10.6,62.2 7.5,53.4 7.5,42.3 C 7.5,30.7 10.8,21.6 17.4,14.9 C 24.0,8.1 33.1,4.8 44.8,4.8 C 56.0,4.8 64.7,7.9 70.8,14.2 C 76.9,20.5 80.0,29.0 80.0,40.0 L 80.0,40.0 z M 18.5,40.6 C 18.5,51.5 20.7,59.8 25.1,65.6 C 29.5,71.4 35.9,74.3 44.4,74.3 C 52.8,74.3 59.0,71.7 63.0,66.4 C 67.0,61.2 69.0,52.9 69.0,41.7 C 69.0,31.1 66.9,23.0 62.6,17.3 C 58.4,11.7 51.8,8.8 43.0,8.8 C 34.4,8.8 28.2,11.5 24.3,16.7 C 20.4,22.0 18.5,29.9 18.5,40.6 L 18.5,40.6 Z",50))
<canvas id=c><svg><path id=p />

Explanation: The HTML creates two global variables, c being the canvas element and p being the SVG path element.

with(c.getContext`2d`)

Put all of the canvas's 2d drawing functions into the current scope.

f=(d,h)=>(

Create a function of two parameters.

p.setAttribute("d",d),b=p.getBBox(),

Set the d attribute of the path and then get its bounding box.

c.height=h,c.width=w=h*b.width/b.height,

Set the size of the canvas to the desired height and scale the width.

scale(s=h/b.height,s),translate(-b.x,-b.y),

Scale and translate the drawing to fit the desired height.

fill(new Path2D(d)),

Draw the path on the canvas.

[...getImageData(0,0,w,h).data.filter((_,i)=>!(3&~i))].

Get the alpha channel of the canvas.

map(i=>` X`[i>>7]).

Map the dark pixels to X and the light pixels to space.

join``.match(RegExp(`.{${w}}`,`g`)).join`
`)

Rewrap the pixels to the width of the canvas.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.