File: doc.go

package info (click to toggle)
golang-golang-x-exp 0.0~git20181112.a3060d4-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 3,968 kB
  • sloc: ansic: 1,884; sh: 342; objc: 273; asm: 48; makefile: 10
file content (667 lines) | stat: -rw-r--r-- 27,007 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package iconvg implements a compact, binary format for simple vector graphics:
icons, logos, glyphs and emoji.

WARNING: THIS FORMAT IS EXPERIMENTAL AND SUBJECT TO INCOMPATIBLE CHANGES.

It is similar in concept to SVG (Scalable Vector Graphics) but much simpler.
Compared to "SVG Tiny", it does not have features for text, multimedia,
interactivity, linking, scripting, animation, XSLT, DOM, combination with
raster graphics such as JPEG formatted textures, etc.

It is a format for efficient presentation, not an authoring format. For
example, it does not provide grouping individual paths into higher level
objects. Instead, the anticipated workflow is that artists use other tools and
authoring formats like Inkscape and SVG, or commercial equivalents, and export
IconVG versions of their assets, the same way that they would produce PNG
versions of their vector art. It is not a goal to be able to recover the
original SVG from a derived IconVG.

It is not a pixel-exact format. Different implementations may produce slightly
different renderings, due to implementation-specific rounding errors in the
mathematical computations when rasterizing vector paths to pixels. Artifacts
may appear when scaling up to extreme sizes, say 1 million by 1 million pixels.
Nonetheless, at typical scales, e.g. up to 4096 × 4096, such differences are
not expected to be perceptible to the naked eye.


Structure

An IconVG graphic consists of a magic identifier, one or more metadata bytes
then a sequence of variable length instructions for a virtual machine.

Those instructions encode a sequence of filled paths, similar to SVG path data
(https://www.w3.org/TR/SVG/paths.html#PathData). Rendering involves switching
between two modes: a styling mode where color registers are set, and a drawing
mode where a path's geometry is defined. The virtual machine starts in the
styling mode.

In both modes, rendering proceeds by reading a one byte opcode followed by a
variable number of data bytes for that opcode. The mapping from byte values to
opcodes depends on whether the renderer is in the styling or drawing mode. A
0x07 byte value means setting the color selector register in the styling mode,
and means adding multiple lineto segments in the drawing mode.


Level of Detail

The machine state includes 2 level of detail registers, denoted LOD0 and LOD1,
both float32 values, initialized to +0 and +infinity. Drawing mode opcodes have
no effect (other than leaving drawing mode) unless the height H in pixels of
the rasterization satisfies LOD0 <= H and H < LOD1.

This allows the format to provide a simpler version for small rasterizations
(e.g. below 32 pixels) and a more complex version for large rasterizations
(e.g. 32 and above pixels).


Registers

The machine state includes 64 color registers (denoted CREG[0], CREG[1], ...,
CREG[63]) and 64 number registers (denoted NREG[0], NREG[1], ..., NREG[63]).
Register indexing is done modulo 64, so CREG[70] is the same as CREG[6], and
CREG[-1] is the same as CREG[63].

Each CREG and NREG register is 32 bits wide. The CREG registers are initialized
to the custom palette (see below); the NREG registers are initialized to 0. The
machine state also includes two selector registers, denoted CSEL and NSEL. They
are effectively 6 bit integers, as they index CREG and NREG, and are also
initialized to 0.

Color registers are four uint8 values: red, green, blue and alpha.

Number registers are float32 values.


Colors and Gradients

IconVG graphics work in 32 bit alpha-premultiplied color, with 8 bits for red,
green, blue and alpha. Alpha-premultiplication means that c00000c0 represents a
75%-opaque, fully saturated red.

It also means that some RGBA combinations (where e.g. the red value is greater
than the alpha value) are nonsensical. The virtual machine re-purposes some of
those values to represent gradients instead of flat colors. Any color register
whose alpha value is zero but whose blue value is at least 128 is a gradient.
Its remaining bits are reinterpreted such that:

The low 6 bits of the red value is the number of color/offset stops, NSTOPS.

The high 2 bits of the red value are reserved.

The low 6 bits of the green value is the color register base, CBASE.

The high 2 bits of the green value is how to spread the gradient past its
nominal bounds (from offset being 0.0 to offset being 1.0). The high two bits
being 0, 1, 2 or 3 mean none, pad, reflect and repeat respectively. None means
that offsets outside of the [0.0, 1.0] range map to transparent black. Pad
means that offsets below 0.0 and above 1.0 map to the colors that 0.0 and 1.0
would map to. Reflect means that the offset mapping is reflected start-to-end,
end-to-start, start-to-end, etc. Repeat means that the offset mapping is
repeated start-to-end, start-to-end, start-to-end, etc.

The low 6 bits of the blue value is the number register base, NBASE.

The remaining bit (the 0x40 bit) of the blue value denotes the gradient shape:
0 means a linear gradient and 1 means a radial gradient.

The gradient has NSTOPS color/offset stops. The first stop has color
CREG[CBASE+0] and offset NREG[NBASE+0], the second stop has color CREG[CBASE+1]
and offset NREG[NBASE+1], and so on.

The gradient also uses the six numbers from NREG[NBASE-6] to NREG[NBASE-1],
which form an affine transformation matrix [a, b, c; d, e, f] such that
a=NREG[NBASE-6], b=NREG[NBASE-5], c=NREG[NBASE-4], etc. This matrix maps from
graphic coordinate space (defined by the metadata's viewBox) to gradient
coordinate space. Gradient coordinate space is where a linear gradient ranges
from x=0 to x=1, and a radial gradient has center (0, 0) and radius 1.

The graphic coordinate (px, py) maps to the gradient coordinate (dx, dy) by:

	dx = a*px + b*py + c
	dy = d*px + e*py + f

The appendix below gives explicit formulae for the [a, b, c; d, e, f] affine
transformation matrix for common gradient geometry, such as a linear gradient
defined by two points.

At the time a gradient is used to fill a path, it is invalid for any of the
stop colors to itself be a gradient, or for any stop offset to be less than or
equal to a previous offset, or outside the range [0, 1].


Colors

Color register values are always 32 bits, or 4 bytes. Colors in the instruction
byte stream can be encoded more compactly, and are encoded in either 1, 2, 3 or
4 bytes, depending on context. For example, some opcodes are followed by a 1
byte color, others by a 2 byte color. There are two forms of 3 byte colors:
direct and indirect.

For a 1 byte encoding, byte values in the range [0, 125) encode the RGBA color
where the red, green and blue values come from the base-5 encoding of that byte
value such that 0, 1, 2, 3 and 4 map to 0x00, 0x40, 0x80, 0xc0, 0xff. The alpha
value is 0xff. For example, the color 40ffc0ff can be encoded as 0x30, as
decimal 48 equals 1*25 + 4*5 + 3. A byte value of 125, 126 or 127 mean the
colors c0c0c0c0, 80808080 and 00000000 respectively. Byte values in the range
[128, 192) mean a color from the custom palette (indexed by that byte value
minus 128). Byte values in the range [192, 256) mean the value of a CREG color
register (with CREG indexed by that byte value minus 192).

For a 2 byte encoding, the red, green, blue and alpha values are all 4 bit
values. For example, the color 338800ff can be encoded as 0x38 0x0f.

For a 3 byte direct encoding, the red, green and blue values are all 8 bit
values. The alpha value is implicitly 255. For example, the color 306607ff can
be encoded as 0x30 0x66 0x07.

For a 4 byte encoding, the red, green, blue and alpha values are all 8 bit
values. For example, the color 30660780 is simply 0x30 0x66 0x07 0x80.

For a 3 byte indirect encoding, the first byte is an integer value in the range
[0, 255] (denoted T) and the second and third bytes are each a 1 byte encoded
color (denoted C0 and C1). The resultant color's red channel value is given by:
	RESULTANT.RED = (((255-T) * C0.RED) + (T * C1.RED) + 128) / 255
rounded down to an integer value (the mathematical floor function), and
likewise for the green, blue and alpha channels. For example, if the custom
palette's third entry is a fully opaque orange, then 0x40 0x7f 0x82 encodes a
25% percent opaque orange: a blend of 75% times fully transparent (1 byte color
0x7f) and 25% times a fully opaque orange (1 byte color 0x82).

It is valid for some encodings to yield a color value where the red, green or
blue value is greater than the alpha value, as this may be a gradient. If it
isn't a gradient, the subsequent rendering is undefined.


Palettes

Rendering an IconVG graphic can be varied by a 64 color palette. For example,
an emoji graphic may be rendered with palette color 0 for skin and palette
color 1 for hair. Decorative variations, such as different clothing, can be
implemented by palette colors possibly set to completely transparent to switch
paths off.

Rendering software should allow users to pass an optional 64 color palette. If
one isn't provided, the suggested palette (either given in the metadata or the
default consisting entirely of opaque black) should be used. Whichever palette
ends up being used is designated the custom palette.

Some user-given colors may be nonsensical as alpha-premultiplied colors, where
e.g. the red value is greater than the alpha value. Such colors are replaced by
opaque black and not re-interpreted as gradients.

Assigning names such as "skin", "hair" or "bow_tie" to the integer indexes of
that 64 color palette is out of scope of the IconVG format per se.


Numbers

Like colors, numbers are encoded in the instruction stream in either 1, 2 or 4
bytes. Unlike colors, the encoding length is not determined by context.
Instead, the low two bits of the first byte indicate the encoding length.

If the least significant bit (the 0x01 bit) of the first byte is 0, the number
is encoded in 1 byte. Otherwise, it is encoded in 2 or 4 bytes depending on the
second least significant bit (the 0x02 bit) of the first byte being 0 or 1.


Natural Numbers

For a 1 byte encoding, the remaining 7 bits form an integer value in the range
[0, 1<<7). For example, 0x28 encodes the value 0x14 or, in decimal, 20.

For a 2 byte encoding, the remaining 14 bits, interpreted as little endian,
form an integer in the range [0, 1<<14). For example, 0x59 0x83 encodes the
value 0x20d6 or, in decimal, 8406.

For a 4 byte encoding, the remaining 30 bits, interpreted as little endian,
form an integer in the range [0, 1<<30). For example, 0x07 0x00 0x80 0x3f
encodes the value 0xfe00001 or, in decimal, 266338305.


Real Numbers

The encoding of a real number resembles the encoding of a natural number. For 1
and 2 byte encodings, the decoded real number equals the decoded natural
number. For example, 0x28 encodes the real number 20.0, just as it encodes the
natural number 20.

For a 4 byte encoding, the decoded natural number, in the range [0, 1<<30), is
shifted left by 2, to make a uint32 value that is a multiple of 4. The decoded
real number is the floating point number corresponding to the IEEE 754 binary
representation of that uint32 (i.e. a reinterpretation as a float32). For
example, 0x07 0x00 0x80 0x3f encodes the value 1.000000476837158203125.

It is valid for the 4 byte encoding to represent infinities and NaNs, but if
not loaded into LOD0 or LOD1, the subsequent rendering is undefined.


Coordinate Numbers

The encoding of a coordinate number resembles the encoding of a real number.
For 1 and 2 byte encodings, the decoded coordinate number equals (R*scale -
bias), where R is the decoded real number as above. The scale and bias depends
on the number of bytes in the encoding.

For a 1 byte encoding, the scale is 1 and the bias is 64, so that a 1 byte
coordinate ranges in [-64, +64) at integer granularity. For example, the
coordinate 7 can be encoded as 0x8e.

For a 2 byte encoding, the scale is 1/64 and the bias is 128, so that a 2 byte
coordinate ranges in [-128, +128) at 1/64 granularity. For example, the
coordinate 7.5 can be encoded as 0x81 0x87.

For a 4 byte encoding, the decoded coordinate number simply equals R. For
example, the coordinate 7.5 can also be encoded as 0x03 0x00 0xf0 0x40.


Zero-to-One Numbers

A zero-to-one number is a real number that is typically in the range [0, 1],
although it is valid for a value to be outside of that range. For example,
angles are expressed as a zero-to-one number: a fraction of a complete
revolution (360 degrees). Gradient stop offsets are another example.

The encoding of a zero-to-one number resembles the encoding of a real number.
For 1 and 2 byte encodings, the decoded number equals R*scale, where R is the
decoded real number as above. The scale depends on the number of bytes in the
encoding.

For a 1 byte encoding, the real number (ranging up to 128) is scaled by 1/120.
The denominator is 2*2*2 * 3 * 5, so that 15 degrees (2*π/24 radians) can be
encoded as 0x0a.

For a 2 byte encoding, the real number (ranging up to 16384) is scaled by
1/15120. The denominator is 2*2*2*2 * 3*3*3 * 5 * 7. For example, 40 degrees
(2*π/9 radians) can be encoded as 0x41 0x1a.

For a 4 byte encoding, the decoded zero-to-one number simply equals R. For
example, 1 degree (2*π/360 radians), or 0.002777777..., can be approximated by
the encoding 0x63 0x0b 0x36 0x3b.


Magic Identifier

An IconVG graphic starts with the four bytes 0x89 0x49 0x56 0x47 ("\x89IVG").


Metadata

The encoded metadata starts with a natural number (see encoding above) of the
number of metadata chunks in the metadata, followed by that many chunks. Each
chunk starts with the length remaining in the chunk (again, encoded as a
natural number), not including the chunk length itself. After that is a MID
(Metadata Identifier) natural number, then MID-specific data. Chunks must be
presented in increasing MID order. MIDs cannot be repeated. All MIDs are
optional.


MID 0 - ViewBox

Metadata Identifier 0 means that the MID-specific data contains four coordinate
values (see above for the coordinate encoding). These are the minX, minY, maxX,
maxY of the graphic's viewBox: its bounding rectangle in (scalable) vector
space. Note that these are abstract units, and not necessarily 1:1 with pixels.
If this MID is not present, the viewBox defaults to (-32, -32, +32, +32). A
viewBox is invalid if minX > maxX or if minY > maxY or if at least one of those
four values are a NaN or an infinity.


MID 1 - Suggested Palette

Metadata Identifier 1 means that the MID-specific data contains a suggested
palette, e.g. to provide a default rendering of variable colors such as an
emoji's skin and hair. The suggested palette is encoded in at least one byte.
The low 6 bits of that byte form a number N. The high 2 bits denote the palette
color format: those high 2 bits being 0, 1, 2 or 3 mean 1, 2, 3 (direct) or 4
byte colors (see above for the color encoding). The chunk then contains N+1
explicit colors, in that 1, 2, 3 or 4 byte encoding. A palette has exactly 64
colors, the 63-N implicit colors of the suggested palette are set to opaque
black. A 1 byte color that refers to the custom palette or a CREG color
register resolves to opaque black. If this MID is not present, the suggested
palette consists entirely of opaque black, as black is always fashionable.


Styling Opcodes

Some opcode descriptions refer to an adjustment value, ADJ. That value is the
low three bits of the opcode, nominally in the range [0, 8), although in
practice the range is [0, 7) as no ADJ-using opcode has the low three bits set.

Opcodes 0x00 to 0x3f sets CSEL to the low 6 bits of the opcode.

Opcodes 0x40 to 0x7f sets NSEL to the low 6 bits of the opcode.

Opcodes 0x80 to 0x86 sets CREG[CSEL-ADJ] to the 1 byte encoded color following
the opcode.

Opcodes 0x88 to 0x8e sets CREG[CSEL-ADJ] to the 2 byte encoded color following
the opcode.

Opcodes 0x90 to 0x96 sets CREG[CSEL-ADJ] to the 3 byte direct encoded color
following the opcode.

Opcodes 0x98 to 0x9e sets CREG[CSEL-ADJ] to the 4 byte encoded color following
the opcode.

Opcodes 0xa0 to 0xa6 sets CREG[CSEL-ADJ] to the 3 byte indirect encoded color
following the opcode.

Opcodes 0x87, 0x8f, 0x97, 0x9f and 0xa7 sets CREG[CSEL] to the 1, 2, 3
(direct), 4 and 3 (indirect) byte encoded color, following the opcode, and then
increments CSEL by 1.

Opcodes 0xa8 to 0xae sets NREG[NSEL-ADJ] to the real number following the
opcode.

Opcodes 0xb0 to 0xb6 sets NREG[NSEL-ADJ] to the coordinate number following the
opcode.

Opcodes 0xb8 to 0xbe sets NREG[NSEL-ADJ] to the zero-to-one number following
the opcode.

Opcode 0xaf, 0xb7 and 0xbf sets NREG[NSEL] to the real, coordinate and
zero-to-one number following the opcode, and then increments NSEL by 1.

Opcodes 0xc0 to 0xc6 switches to the drawing mode, and is followed by two
coordinates that is the path's starting location. In effect, there is an
implicit M (absolute moveto) op. CREG[CSEL-ADJ], either a flat color or a
gradient, will fill the path once it is complete.

Opcode 0xc7 sets the Level of Detail bounds LOD0 and LOD1 to the two real
numbers following the opcode.

All other opcodes are reserved.


Drawing Opcodes

The drawing model is based on SVG path data
(https://www.w3.org/TR/SVG/paths.html#PathData) and this description re-uses
SVG's one-letter mnemonics: M means absolute moveto, m means relative moveto, L
means absolute lineto, l means relative lineto, H means absolute horizontal
lineto, etc. Upper and lower case mean absolute and relative coordinates. The
upper case mnemonics of the SVG operations used in IconVG's drawing mode are:
M, Z, L, H, V, C, S, Q, T, A.

IconVG differs from SVG with multiple consecutive moveto ops. SVG treats all
but the first one as lineto ops. IconVG treats them all as moveto ops.

Almost all opcodes, i.e. those in the range [0x00, 0xdf], come in contiguous
groups of 16 or 32. For example, there are 16 Q (absolute quadratic Bézier
curveto) opcodes, from 0x60 to 0x6f. Those opcodes' meaning differ only in
their repeat count RC: how often that drawing operation is repeated. The lowest
valued opcode has a repeat count of 1, the next lowest has a repeat count of 2
and so on. For example, the opcode 0x68 means 9 consecutive Q drawing ops.

Opcodes 0x00 to 0x1f means RC consecutive L ops, for RC in [1, 32]. The opcode
is followed by 2*RC coordinates, RC sets of (x, y).

Opcodes 0x20 to 0x3f are like the previous paragraph, except L (absolute)
becomes l (relative).

Opcodes 0x40 to 0x4f means RC consecutive T ops, for RC in [1, 16]. The opcode
is followed by 2*RC coordinates, RC sets of (x, y).

Opcodes 0x50 to 0x5f are like the previous paragraph, except T (absolute)
becomes t (relative).

Opcodes 0x60 to 0x6f means RC consecutive Q ops, for RC in [1, 16]. The opcode
is followed by 4*RC coordinates, RC sets of (x1, y1, x, y).

Opcodes 0x70 to 0x7f are like the previous paragraph, except Q (absolute)
becomes q (relative).

Opcodes 0x80 to 0x8f means RC consecutive S ops, for RC in [1, 16]. The opcode
is followed by 4*RC coordinates, RC sets of (x2, y2, x, y).

Opcodes 0x90 to 0x9f are like the previous paragraph, except S (absolute)
becomes s (relative).

Opcodes 0xa0 to 0xaf means RC consecutive C ops, for RC in [1, 16]. The opcode
is followed by 6*RC coordinates, RC sets of (x1, y1, x2, y2, x, y).

Opcodes 0xb0 to 0xbf are like the previous paragraph, except C (absolute)
becomes c (relative).

Opcodes 0xc0 to 0xcf means RC consecutive A ops, for RC in [1, 16]. The opcode
is followed by 6*RC numbers, RC sets of (rx, ry, xAxisRotation, flags, x, y).
The rx, ry, x and y numbers are coordinates. The xAxisRotation number is an
angle (a zero-to-one number being a fraction of 360 degrees). The flags are
encoded as a natural number. The 0x01 bit of the decoded natural number is the
large-arc-flag and the 0x02 bit is the sweep-flag.

Opcodes 0xd0 to 0xdf are like the previous paragraph, except A (absolute)
becomes a (relative).

Opcode 0xe0 is reserved. (A future version of IconVG may use this opcode to
mean the same as 0xe1 without the one z op, which will matter for stroked
paths).

Opcode 0xe1 means one z op and then end the path: fill the path with the color
chosen when we switched to the drawing mode, and switch back to the styling
mode. (The Z and z ops are equivalent).

Opcode 0xe2 means one z op and then an implicit M op to the (x, y) coordinates
after the opcode.

Opcode 0xe3 means one z op and then an implicit m op to the (x, y) coordinates
after the opcode.

Opcodes 0xe4 and 0xe5 are reserved. (A future version of IconVG may use these
for M and m ops, if we allow stroked paths).

Opcode 0xe6 means one H op to the x coordinate after the opcode.

Opcode 0xe7 means one h op to the x coordinate after the opcode.

Opcode 0xe8 means one V op to the y coordinate after the opcode.

Opcode 0xe9 means one v op to the y coordinate after the opcode.

All other opcodes are reserved.

These opcode descriptions all assume that the Level of Detail constraint (see
above) is satisfied. If not, the opcodes and their variable length data are
consumed, but no further action is taken (other than leaving drawing mode).


Example

The production version of the "action/info" icon from the Material Design icon
set is defined by the following SVG, also available at
https://github.com/google/material-design-icons/blob/master/action/svg/production/ic_info_48px.svg:

	<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48">
	<path d="M24 4C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4z
	m2 30h-4V22h4v12zm0-16h-4v-4h4v4z"/></svg>

This is 202 bytes, or 174 bytes after "gzip --best". The PNG renderings at
various sizes:

	18x18: 207 bytes
	24x24: 222 bytes
	36x36: 321 bytes
	48x48: 412 bytes

The corresponding IconVG is 73 bytes:

	89 49 56 47 02 0a 00 50 50 b0 b0 c0 80 58 a0 cf
	cc 30 c1 58 58 cf cc 30 c1 58 80 91 37 33 0f 41
	a8 a8 a8 a8 37 33 0f c1 a8 58 80 cf cc 30 41 58
	80 58 e3 84 bc e7 78 e8 7c e7 88 e9 98 e3 80 60
	e7 78 e9 78 e7 88 e9 88 e1

The annotated version is below. Note that the IconVG viewBox ranges from -24 to
+24 while the SVG viewBox ranges from 0 to 48.

	89 49 56 47   IconVG Magic identifier
	02            Number of metadata chunks: 1
	0a            Metadata chunk length: 5
	00            Metadata Identifier: 0 (viewBox)
	50                -24
	50                -24
	b0                +24
	b0                +24
	c0            Start path, filled with CREG[CSEL-0]; M (absolute moveTo)
	80                +0
	58                -20
	a0            C (absolute cubeTo), 1 reps
	cf cc 30 c1       -11.049999
	58                -20
	58                -20
	cf cc 30 c1       -11.049999
	58                -20
	80                +0
	91            s (relative smooth cubeTo), 2 reps
	37 33 0f 41       +8.950001
	a8                +20
	a8                +20
	a8                +20
	              s (relative smooth cubeTo), implicit
	a8                +20
	37 33 0f c1       -8.950001
	a8                +20
	58                -20
	80            S (absolute smooth cubeTo), 1 reps
	cf cc 30 41       +11.049999
	58                -20
	80                +0
	58                -20
	e3            z (closePath); m (relative moveTo)
	84                +2
	bc                +30
	e7            h (relative horizontal lineTo)
	78                -4
	e8            V (absolute vertical lineTo)
	7c                -2
	e7            h (relative horizontal lineTo)
	88                +4
	e9            v (relative vertical lineTo)
	98                +12
	e3            z (closePath); m (relative moveTo)
	80                +0
	60                -16
	e7            h (relative horizontal lineTo)
	78                -4
	e9            v (relative vertical lineTo)
	78                -4
	e7            h (relative horizontal lineTo)
	88                +4
	e9            v (relative vertical lineTo)
	88                +4
	e1            z (closePath); end path

There are more examples in the ./testdata directory.


Appendix - Gradient Transformation Matrices

This appendix derives the affine transformation matrices [a, b, c; d, e, f] for
linear, circular and elliptical gradients.


Linear Gradients

For a linear gradient from (x1, y1) to (x2, y2), let dx, dy = x2-x1, y2-y1. In
gradient coordinate space, the y-coordinate is ignored, so the transformation
matrix simplifies to [a, b, c; 0, 0, 0]. It satisfies the three simultaneous
equations:

	a*(x1   ) + b*(y1   ) + c = 0   (eq L.0)
	a*(x1+dy) + b*(y1-dx) + c = 0   (eq L.1)
	a*(x1+dx) + b*(y1+dy) + c = 1   (eq L.2)

Subtracting equation L.0 from equations L.1 and L.2 yields:

	a*dy - b*dx = 0
	a*dx + b*dy = 1

So that

	a*dy*dy - b*dx*dy = 0
	a*dx*dx + b*dx*dy = dx

Overall:

	a = dx / (dx*dx + dy*dy)
	b = dy / (dx*dx + dy*dy)
	c = -a*x1 - b*y1
	d = 0
	e = 0
	f = 0


Circular Gradients

For a circular gradient with center (cx, cy) and radius vector (rx, ry), such
that (cx+rx, cy+ry) is on the circle, let

	r = math.Sqrt(rx*rx + ry*ry)

The transformation matrix maps (cx, cy) to (0, 0), maps (cx+r, cy) to (1, 0)
and maps (cx, cy+r) to (0, 1). Solving those six simultaneous equations give:

	a = +1  / r
	b = +0  / r
	c = -cx / r
	d = +0  / r
	e = +1  / r
	f = -cy / r


Elliptical Gradients

For an elliptical gradient with center (cx, cy) and axis vectors (rx, ry) and
(sx, sy), such that (cx+rx, cx+ry) and (cx+sx, cx+sy) are on the ellipse, the
transformation matrix satisfies the six simultaneous equations:

	a*(cx   ) + b*(cy   ) + c = 0   (eq E.0)
	a*(cx+rx) + b*(cy+ry) + c = 1   (eq E.1)
	a*(cx+sx) + b*(cy+sy) + c = 0   (eq E.2)
	d*(cx   ) + e*(cy   ) + f = 0   (eq E.3)
	d*(cx+rx) + e*(cy+ry) + f = 0   (eq E.4)
	d*(cx+sx) + e*(cy+sy) + f = 1   (eq E.5)

Subtracting equation E.0 from equations E.1 and E.2 yields:

	a*rx + b*ry = 1
	a*sx + b*sy = 0

Solving these two simultaneous equations yields:

	a = +sy / (rx*sy - sx*ry)
	b = -sx / (rx*sy - sx*ry)

Re-arranging E.0 yields:

	c = -a*cx - b*cy

Similarly for d, e and f so that, overall:

	a = +sy / (rx*sy - sx*ry)
	b = -sx / (rx*sy - sx*ry)
	c = -a*cx - b*cy
	d = -ry / (rx*sy - sx*ry)
	e = +rx / (rx*sy - sx*ry)
	f = -d*cx - e*cy

Note that if rx = r, ry = 0, sx = 0 and sy = r then this simplifies to the
circular gradient transformation matrix formula, above.
*/
package iconvg

// TODO: shapes (circles, rects) and strokes? Or can we assume that authoring
// tools will convert shapes and strokes to paths?

// TODO: mark somehow that a graphic (such as a back arrow) should be flipped
// horizontally or its paths otherwise varied when presented in a Right-To-Left
// context, such as among Arabic and Hebrew text? Or should that be the
// responsibility of higher layers, selecting different IconVG graphics based
// on context, the way they would select different PNG graphics.

// TODO: hinting?