# 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.

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;
}
.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

• 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. Jun 27, 2020 at 10:56

# 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.createElementcanvas.getContext2d).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.getContext2d    //
).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()


## HTML5 + ES6, 320 bytes

with(c.getContext2d)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.getContext2d)  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.