Merge add text support. from guzba/text2

* Simple API for both drawing basic text and complex text layouts with spans.
* Fill and stroke text with a color, gradient or even an image.
* Kerning adjustments with both KERN and GPOS OpenType pair adjustments.
* Text wrapping, horizontal and vertical alignment for simple and rich text.
This commit is contained in:
treeform 2021-05-11 20:45:14 -07:00 committed by GitHub
commit 3538de5ae6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
313 changed files with 66855 additions and 122 deletions
README.md
examples
pixie.nimble
src
tests

View file

@ -9,6 +9,7 @@ This library is being actively developed and we'd be happy for you to use it.
`nimble install pixie`
Features:
* Typesetting and rasterizing text, including styled rich text via spans.
* Drawing paths, shapes and curves with even-odd and non-zero windings.
* Pixel-perfect AA quality.
* Supported file formats are PNG, BMP, JPG, SVG + more in development.
@ -16,13 +17,13 @@ Features:
* Shadows, glows and blurs.
* Complex masking: Subtract, Intersect, Exclude.
* Complex blends: Darken, Multiply, Color Dodge, Hue, Luminosity... etc.
* Many operations are SIMD accelerated where possible.
* Many operations are SIMD accelerated.
### Documentation
API reference: https://treeform.github.io/pixie/pixie.html
### File formats
### Image file formats
Format | Read | Write |
------------- | ------------- | ------------- |
@ -32,6 +33,14 @@ BMP | ✅ | ✅ |
GIF | ✅ | |
SVG | ✅ | |
### Font file formats
Format | Read
------------- | -------------
TTF | ✅
OTF | ✅
SVG | ✅
### Joins and caps
Supported Caps:
@ -91,6 +100,40 @@ z | ✅ | close path |
## Examples
### Text
[examples/text.nim](examples/text.nim)
```nim
var font = readFont("tests/fonts/Roboto-Regular_1.ttf")
font.size = 20
let text = "Typesetting is the arrangement and composition of text in graphic design and publishing in both digital and traditional medias."
image.fillText(font.typeset(text, bounds = vec2(180, 180)), vec2(10, 10))
```
![example output](examples/text.png)
### Text spans
[examples/text_spans.nim](examples/text_spans.nim)
```nim
let font = readFont("tests/fonts/Ubuntu-Regular_1.ttf")
proc style(font: Font, size: float32, color: ColorRGBA): Font =
result = font
result.size = size
result.paint.color = color
let spans = @[
newSpan("verb [with object] ", font.style(12, rgba(200, 200, 200, 255))),
newSpan("strallow\n", font.style(36, rgba(0, 0, 0, 255))),
newSpan("\nstral·low\n", font.style(13, rgba(0, 127, 244, 255))),
newSpan("\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ",
font.style(14, rgba(80, 80, 80, 255)))
]
image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10))
```
![example output](examples/text_spans.png)
### Square
[examples/square.nim](examples/square.nim)
```nim

Binary file not shown.

Before

(image error) Size: 88 KiB

After

(image error) Size: 88 KiB

Binary file not shown.

Before

(image error) Size: 11 KiB

After

(image error) Size: 11 KiB

Binary file not shown.

Before

(image error) Size: 4.6 KiB

After

(image error) Size: 4.6 KiB

Binary file not shown.

Before

(image error) Size: 40 KiB

After

(image error) Size: 40 KiB

Binary file not shown.

Before

(image error) Size: 2.5 KiB

After

(image error) Size: 2.4 KiB

Binary file not shown.

Before

(image error) Size: 5.9 KiB

After

(image error) Size: 5.9 KiB

Binary file not shown.

Before

(image error) Size: 2.2 KiB

After

(image error) Size: 2.2 KiB

Binary file not shown.

Before

(image error) Size: 9.3 KiB

After

(image error) Size: 9.3 KiB

Binary file not shown.

Before

(image error) Size: 918 B

After

(image error) Size: 915 B

12
examples/text.nim Normal file
View file

@ -0,0 +1,12 @@
import pixie
let image = newImage(200, 200)
image.fill(rgba(255, 255, 255, 255))
var font = readFont("tests/fonts/Roboto-Regular_1.ttf")
font.size = 20
let text = "Typesetting is the arrangement and composition of text in graphic design and publishing in both digital and traditional medias."
image.fillText(font.typeset(text, bounds = vec2(180, 180)), vec2(10, 10))
image.writeFile("examples/text.png")

BIN
examples/text.png Normal file

Binary file not shown.

After

(image error) Size: 20 KiB

22
examples/text_spans.nim Normal file
View file

@ -0,0 +1,22 @@
import pixie
let image = newImage(200, 200)
image.fill(rgba(255, 255, 255, 255))
let font = readFont("tests/fonts/Ubuntu-Regular_1.ttf")
proc style(font: Font, size: float32, color: ColorRGBA): Font =
result = font
result.size = size
result.paint.color = color
let spans = @[
newSpan("verb [with object] ", font.style(12, rgba(200, 200, 200, 255))),
newSpan("strallow\n", font.style(36, rgba(0, 0, 0, 255))),
newSpan("\nstral·low\n", font.style(13, rgba(0, 127, 244, 255))),
newSpan("\n1. free (something) from restrictive restrictions \"the regulations are intended to strallow changes in public policy\" ",
font.style(14, rgba(80, 80, 80, 255)))
]
image.fillText(typeset(spans, bounds = vec2(180, 180)), vec2(10, 10))
image.writeFile("examples/text_spans.png")

BIN
examples/text_spans.png Normal file

Binary file not shown.

After

(image error) Size: 18 KiB

Binary file not shown.

Before

(image error) Size: 42 KiB

After

(image error) Size: 42 KiB

View file

@ -6,7 +6,7 @@ license = "MIT"
srcDir = "src"
requires "nim >= 1.2.6"
requires "vmath >= 1.0.3"
requires "vmath >= 1.0.4"
requires "chroma >= 0.2.5"
requires "zippy >= 0.3.5"
requires "flatty >= 0.1.3"

View file

@ -1,14 +1,28 @@
import bumpy, chroma, flatty/binny, os, pixie/blends, pixie/common,
pixie/fileformats/bmp, pixie/fileformats/gif, pixie/fileformats/jpg,
pixie/fileformats/png, pixie/fileformats/svg, pixie/images, pixie/masks,
pixie/paints, pixie/paths, vmath
pixie/fileformats/png, pixie/fileformats/svg, pixie/fonts, pixie/images,
pixie/masks, pixie/paints, pixie/paths, strutils, vmath
export blends, bumpy, chroma, common, images, masks, paints, paths, vmath
export blends, bumpy, chroma, common, fonts, images, masks, paints, paths, vmath
type
FileFormat* = enum
ffPng, ffBmp, ffJpg, ffGif
proc readFont*(filePath: string): Font =
## Loads a font from a file.
result =
case splitFile(filePath).ext.toLowerAscii():
of ".ttf":
parseTtf(readFile(filePath))
of ".otf":
parseOtf(readFile(filePath))
of ".svg":
parseSvgFont(readFile(filePath))
else:
raise newException(PixieError, "Unsupported font format")
result.typeface.filePath = filePath
converter autoStraightAlpha*(c: ColorRGBX): ColorRGBA {.inline.} =
## Convert a paremultiplied alpha RGBA to a straight alpha RGBA.
c.rgba()
@ -55,7 +69,7 @@ proc writeFile*(image: Image, filePath: string, fileFormat: FileFormat) =
proc writeFile*(image: Image, filePath: string) =
## Writes an image to a file.
let fileFormat = case splitFile(filePath).ext:
let fileFormat = case splitFile(filePath).ext.toLowerAscii():
of ".png": ffPng
of ".bmp": ffBmp
of ".jpg", ".jpeg": ffJpg
@ -313,3 +327,80 @@ proc strokePolygon*(
var path: Path
path.polygon(pos, size, sides)
mask.strokePath(path, strokeWidth)
proc fillText*(
target: Image | Mask,
arrangement: Arrangement,
transform: Vec2 | Mat3 = vec2(0, 0)
) =
## Fills the text arrangement.
for spanIndex, (start, stop) in arrangement.spans:
let font = arrangement.fonts[spanIndex]
for runeIndex in start .. stop:
var path = font.typeface.getGlyphPath(arrangement.runes[runeIndex])
path.transform(
translate(arrangement.positions[runeIndex]) *
scale(vec2(font.scale))
)
when type(target) is Image:
target.fillPath(path, font.paint, transform)
else: # target is Mask
target.fillPath(path, transform)
proc fillText*(
target: Image | Mask,
font: Font,
text: string,
transform: Vec2 | Mat3 = vec2(0, 0),
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop
) {.inline.} =
## Typesets and fills the text. Optional parameters:
## transform: translation or matrix to apply
## bounds: width determines wrapping and hAlign, height for vAlign
## hAlign: horizontal alignment of the text
## vAlign: vertical alignment of the text
fillText(target, font.typeset(text, bounds, hAlign, vAlign), transform)
proc strokeText*(
target: Image | Mask,
arrangement: Arrangement,
transform: Vec2 | Mat3 = vec2(0, 0),
strokeWidth = 1.0
) =
## Strokes the text arrangement.
for spanIndex, (start, stop) in arrangement.spans:
let font = arrangement.fonts[spanIndex]
for runeIndex in start .. stop:
var path = font.typeface.getGlyphPath(arrangement.runes[runeIndex])
path.transform(
translate(arrangement.positions[runeIndex]) *
scale(vec2(font.scale))
)
when type(target) is Image:
target.strokePath(path, font.paint, transform, strokeWidth)
else: # target is Mask
target.strokePath(path, transform, strokeWidth)
proc strokeText*(
target: Image | Mask,
font: Font,
text: string,
transform: Vec2 | Mat3 = vec2(0, 0),
strokeWidth = 1.0,
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop
) {.inline.} =
## Typesets and strokes the text. Optional parameters:
## transform: translation or matrix to apply
## bounds: width determines wrapping and hAlign, height for vAlign
## hAlign: horizontal alignment of the text
## vAlign: vertical alignment of the text
strokeText(
target,
font.typeset(text, bounds, hAlign, vAlign),
transform,
strokeWidth
)

View file

@ -1,7 +1,6 @@
import staticglfw except Image
import opengl, pixie
export pixie
export staticglfw except Image
import opengl, pixie, staticglfw except Image
export pixie, staticglfw except Image
var
screen* = newImage(800, 600)

View file

@ -104,9 +104,11 @@ proc unfilter(
let filterType = uncompressed[uncompressedIdx(0, y)]
case filterType:
of 0: # None
for x in 0 ..< rowBytes:
var value = uncompressed[uncompressedIdx(x + 1, y)]
result[unfiteredIdx(x, y)] = value
copyMem(
result[unfiteredIdx(0, y)].addr,
uncompressed[uncompressedIdx(1, y)].unsafeAddr,
rowBytes
)
of 1: # Sub
for x in 0 ..< rowBytes:
var value = uncompressed[uncompressedIdx(x + 1, y)]
@ -413,7 +415,7 @@ proc decodePng*(data: seq[uint8]): Image =
prevChunkType = chunkType
if pos == data.len:
if pos == data.len or prevChunkType == "IEND":
break
if prevChunkType != "IEND":

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,106 @@
import pixie/common, pixie/paths, strutils, tables, unicode, vmath, xmlparser, xmltree
type SvgFont* = ref object
unitsPerEm*, ascent*, descent*: float32
advances: Table[Rune, float32]
glyphPaths: Table[Rune, Path]
kerningPairs: Table[(Rune, Rune), float32]
missingGlyphAdvance: float32
missingGlyphPath: Path
proc getGlyphPath*(svgFont: SvgFont, rune: Rune): Path =
if rune in svgFont.glyphPaths:
svgFont.glyphPaths[rune]
else:
svgFont.missingGlyphPath
proc getAdvance*(svgFont: SvgFont, rune: Rune): float32 =
if rune in svgFont.advances:
svgFont.advances[rune]
else:
svgFont.missingGlyphAdvance
proc getKerningAdjustment*(svgFont: SvgFont, left, right: Rune): float32 =
let pair = (left, right)
if pair in svgFont.kerningPairs:
result = svgFont.kerningPairs[pair]
proc failInvalid() =
raise newException(PixieError, "Invalid SVG font data")
proc parseFloat(node: XmlNode, attr: string): float32 =
let value = node.attr(attr)
if value.len == 0:
raise newException(PixieError, "SVG font missing attr " & attr)
try:
result = parseFloat(value)
except:
failInvalid()
proc parseSvgFont*(buf: string): SvgFont =
result = SvgFont()
let
root = parseXml(buf)
defs = root.child("defs")
if defs == nil:
failInvalid()
let font = defs.child("font")
if font == nil:
failInvalid()
let defaultAdvance = font.parseFloat("horiz-adv-x")
for node in font.items:
case node.tag:
of "font-face":
result.unitsPerEm = node.parseFloat("units-per-em")
result.ascent = node.parseFloat("ascent")
result.descent = node.parseFloat("descent")
of "glyph":
let
name = node.attr("glyph-name")
unicode = node.attr("unicode")
if unicode.len > 0 or name == "space":
var
i: int
rune: Rune
if name == "space":
rune = Rune(32)
else:
fastRuneAt(unicode, i, rune, true)
if i == unicode.len:
var advance = defaultAdvance
if node.attr("horiz-adv-x").len > 0:
advance = node.parseFloat("horiz-adv-x")
result.advances[rune] = advance
result.glyphPaths[rune] = parsePath(node.attr("d"))
result.glyphPaths[rune].transform(scale(vec2(1, -1)))
else:
discard # Multi-rune unicode?
of "hkern":
# TODO "g" kerning
let
u1 = node.attr("u1")
u2 = node.attr("u2")
if u1.len > 0 and u2.len > 0:
var
i1, i2: int
left, right: Rune
fastRuneAt(u1, i1, left, true)
fastRuneAt(u2, i2, right, true)
if i1 == u1.len and i2 == u2.len:
let adjustment = -node.parseFloat("k")
result.kerningPairs[(left, right)] = adjustment
else:
discard # Multi-rune unicode?
of "missing-glyph":
var advance = defaultAdvance
if node.attr("horiz-adv-x").len > 0:
advance = node.parseFloat("horiz-adv-x")
result.missingGlyphAdvance = advance
result.missingGlyphPath = parsePath(node.attr("d"))
result.missingGlyphPath.transform(scale(vec2(1, -1)))
else:
discard # Unrecognized font node child

402
src/pixie/fonts.nim Normal file
View file

@ -0,0 +1,402 @@
import bumpy, chroma, pixie/fontformats/opentype, pixie/fontformats/svgfont,
pixie/paints, pixie/paths, unicode, vmath
const
AutoLineHeight* = -1.float32 ## Use default line height for the font size
LF = Rune(10)
SP = Rune(32)
type
Typeface* = ref object
opentype: OpenType
svgFont: SvgFont
filePath*: string
Font* = object
typeface*: Typeface
size*: float32 ## Font size in pixels.
lineHeight*: float32 ## The line height in pixels or AutoLineHeight for the font's default line height.
paint*: Paint
textCase*: TextCase
noKerningAdjustments*: bool ## Optionally disable kerning pair adjustments
Span* = ref object
text*: string
font*: Font
Arrangement* = ref object
spans*: seq[(int, int)]
fonts*: seq[Font]
runes*: seq[Rune]
positions*: seq[Vec2]
selectionRects*: seq[Rect]
HAlignMode* = enum
haLeft
haCenter
haRight
VAlignMode* = enum
vaTop
vaMiddle
vaBottom
TextCase* = enum
tcNormal
tcUpper
tcLower
tcTitle
# tcSmallCaps
# tcSmallCapsForced
proc ascent*(typeface: Typeface): float32 {.inline.} =
## The font ascender value in font units.
if typeface.opentype != nil:
typeface.opentype.hhea.ascender.float32
else:
typeface.svgFont.ascent
proc descent*(typeface: Typeface): float32 {.inline.} =
## The font descender value in font units.
if typeface.opentype != nil:
typeface.opentype.hhea.descender.float32
else:
typeface.svgFont.descent
proc lineGap*(typeface: Typeface): float32 {.inline.} =
## The font line gap value in font units.
if typeface.opentype != nil:
result = typeface.opentype.hhea.lineGap.float32
proc lineHeight*(typeface: Typeface): float32 {.inline.} =
## The default line height in font units.
typeface.ascent - typeface.descent + typeface.lineGap
proc getGlyphPath*(typeface: Typeface, rune: Rune): Path {.inline.} =
## The glyph path for the rune.
if rune.uint32 > SP.uint32: # Empty paths for control runes (not tofu)
if typeface.opentype != nil:
result = typeface.opentype.getGlyphPath(rune)
else:
result = typeface.svgFont.getGlyphPath(rune)
proc getAdvance*(typeface: Typeface, rune: Rune): float32 {.inline.} =
## The advance for the rune in pixels.
if typeface.opentype != nil:
typeface.opentype.getAdvance(rune)
else:
typeface.svgFont.getAdvance(rune)
proc getKerningAdjustment*(
typeface: Typeface, left, right: Rune
): float32 {.inline.} =
## The kerning adjustment for the rune pair, in pixels.
if typeface.opentype != nil:
typeface.opentype.getKerningAdjustment(left, right)
else:
typeface.svgfont.getKerningAdjustment(left, right)
proc scale*(font: Font): float32 {.inline.} =
## The scale factor to transform font units into pixels.
if font.typeface.opentype != nil:
font.size / font.typeface.opentype.head.unitsPerEm.float32
else:
font.size / font.typeface.svgFont.unitsPerEm
proc defaultLineHeight*(font: Font): float32 {.inline.} =
## The default line height in pixels for the current font size.
let fontUnits =
font.typeface.ascent - font.typeface.descent + font.typeface.lineGap
round(fontUnits * font.scale)
proc newSpan*(text: string, font: Font): Span =
result = Span()
result.text = text
result.font = font
proc convertTextCase(runes: var seq[Rune], textCase: TextCase) =
case textCase:
of tcNormal:
discard
of tcUpper:
for rune in runes.mitems:
rune = rune.toUpper()
of tcLower:
for rune in runes.mitems:
rune = rune.toLower()
of tcTitle:
var prevRune = SP
for rune in runes.mitems:
if prevRune.isWhiteSpace:
rune = rune.toUpper()
prevRune = rune
proc canWrap(rune: Rune): bool {.inline.} =
rune == Rune(32) or rune.isWhiteSpace()
proc typeset*(
spans: seq[Span],
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop,
wrap = true
): Arrangement =
## Lays out the character glyphs and returns the arrangement.
## Optional parameters:
## bounds: width determines wrapping and hAlign, height for vAlign
## hAlign: horizontal alignment of the text
## vAlign: vertical alignment of the text
## wrap: enable/disable text wrapping
result = Arrangement()
block: # Walk and filter the spans
var start: int
for span in spans:
var
i = 0
rune: Rune
runes: seq[Rune]
while i < span.text.len:
fastRuneAt(span.text, i, rune, true)
# Ignore control runes (0 - 31) except LF for now
if rune.uint32 >= SP.uint32 or rune.uint32 == LF.uint32:
runes.add(rune)
if runes.len > 0:
runes.convertTextCase(span.font.textCase)
result.runes.add(runes)
result.spans.add((start, start + runes.len - 1))
result.fonts.add(span.font)
start += runes.len
if result.runes.len == 0:
return
result.positions.setLen(result.runes.len)
result.selectionRects.setLen(result.runes.len)
var lines = @[(0, 0)] # (start, stop)
block: # Arrange the glyphs horizontally first (handling line breaks)
proc advance(font: Font, runes: seq[Rune], i: int): float32 {.inline.} =
if not font.noKerningAdjustments and i + 1 < runes.len:
result += font.typeface.getKerningAdjustment(runes[i], runes[i + 1])
result += font.typeface.getAdvance(runes[i])
result *= font.scale
var
at: Vec2
prevCanWrap: int
for spanIndex, (start, stop) in result.spans:
let font = result.fonts[spanIndex]
for runeIndex in start .. stop:
let rune = result.runes[runeIndex]
if rune == LF:
let advance = font.typeface.getAdvance(SP) * font.scale
result.positions[runeIndex] = at
result.selectionRects[runeIndex] = rect(at.x, at.y, advance, 0)
at.x = 0
at.y += 1
prevCanWrap = 0
lines[^1][1] = runeIndex
# Start a new line if we are not at the end
if runeIndex + 1 < result.runes.len:
lines.add((runeIndex + 1, 0))
else:
let advance = advance(font, result.runes, runeIndex)
if wrap and rune != SP and bounds.x > 0 and at.x + advance > bounds.x:
# Wrap to new line
at.x = 0
at.y += 1
var lineStart = runeIndex
# Go back and wrap glyphs after the wrap index down to the next line
if prevCanWrap > 0 and prevCanWrap != runeIndex:
for i in prevCanWrap + 1 ..< runeIndex:
result.positions[i] = at
result.selectionRects[i].xy = vec2(at.x, at.y)
at.x += advance(font, result.runes, i)
dec lineStart
lines[^1][1] = lineStart - 1
lines.add((lineStart, 0))
if rune.canWrap():
prevCanWrap = runeIndex
result.positions[runeIndex] = at
result.selectionRects[runeIndex] = rect(at.x, at.y, advance, 0)
at.x += advance
lines[^1][1] = result.runes.len - 1
if hAlign != haLeft:
# Since horizontal alignment adjustments are different for each line,
# find the start and stop of each line of text.
for (start, stop) in lines:
var furthestX: float32
for i in countdown(stop, start):
if result.runes[i] != SP and result.runes[i] != LF:
furthestX = result.selectionRects[i].x + result.selectionRects[i].w
break
var xAdjustment: float32
case hAlign:
of haLeft:
discard
of haCenter:
xAdjustment = (bounds.x - furthestX) / 2
of haRight:
xAdjustment = bounds.x - furthestX
if xAdjustment != 0:
for i in start .. stop:
result.positions[i].x += xAdjustment
result.selectionRects[i].x += xAdjustment
block: # Nudge selection rects to pixel grid
var at = result.selectionRects[0]
at.x = round(at.x)
for rect in result.selectionRects.mitems:
if rect.y == at.y:
rect.x = at.x
rect.w = round(rect.w)
at.x = rect.x + rect.w
else:
rect.w = round(rect.w)
at.x = rect.w
at.y = rect.y
block: # Arrange the lines vertically
let initialY = block:
var maxInitialY: float32
block outer:
for spanIndex, (start, stop) in result.spans:
let
font = result.fonts[spanIndex]
lineHeight =
if font.lineheight >= 0:
font.lineheight
else:
font.defaultLineHeight
var fontUnitInitialY = font.typeface.ascent + font.typeface.lineGap / 2
if lineHeight != font.defaultLineHeight:
fontUnitInitialY += (
(lineHeight / font.scale) - font.typeface.lineHeight
) / 2
maxInitialY = max(maxInitialY, round(fontUnitInitialY * font.scale))
for runeIndex in start .. stop:
if runeIndex == lines[0][1]:
break outer
maxInitialY
var lineHeights = newSeq[float32](lines.len)
block: # Compute each line's line height
var line: int
for spanIndex, (start, stop) in result.spans:
let
font = result.fonts[spanIndex]
fontLineHeight =
if font.lineheight >= 0:
font.lineheight
else:
font.defaultLineHeight
lineHeights[line] = max(lineHeights[line], fontLineHeight)
for runeIndex in start .. stop:
if line + 1 < lines.len and runeIndex == lines[line + 1][0]:
inc line
lineHeights[line] = max(lineHeights[line], fontLineHeight)
# Handle when span and line endings coincide
if line + 1 < lines.len and stop == lines[line][1]:
inc line
block: # Vertically position the glyphs
var
line: int
baseline = initialY
for spanIndex, (start, stop) in result.spans:
let
font = result.fonts[spanIndex]
lineHeight =
if font.lineheight >= 0:
font.lineheight
else:
font.defaultLineHeight
for runeIndex in start .. stop:
if line + 1 < lines.len and runeIndex == lines[line + 1][0]:
inc line
baseline += lineHeights[line]
result.positions[runeIndex].y = baseline
result.selectionRects[runeIndex].y =
baseline - round(font.typeface.ascent * font.scale)
result.selectionRects[runeIndex].h = lineHeight
if vAlign != vaTop:
let
finalSelectionRect = result.selectionRects[^1]
furthestY = finalSelectionRect.y + finalSelectionRect.h
var yAdjustment: float32
case vAlign:
of vaTop:
discard
of vaMiddle:
yAdjustment = round((bounds.y - furthestY) / 2)
of vaBottom:
yAdjustment = bounds.y - furthestY
if yAdjustment != 0:
for i in 0 ..< result.positions.len:
result.positions[i].y += yAdjustment
result.selectionRects[i].y += yAdjustment
proc typeset*(
font: Font,
text: string,
bounds = vec2(0, 0),
hAlign = haLeft,
vAlign = vaTop,
wrap = true
): Arrangement {.inline.} =
## Lays out the character glyphs and returns the arrangement.
## Optional parameters:
## bounds: width determines wrapping and hAlign, height for vAlign
## hAlign: horizontal alignment of the text
## vAlign: vertical alignment of the text
## wrap: enable/disable text wrapping
typeset(@[newSpan(text, font)], bounds, hAlign, vAlign, wrap)
proc computeBounds*(arrangement: Arrangement): Vec2 =
if arrangement.runes.len > 0:
for i in 0 ..< arrangement.runes.len:
if arrangement.runes[i] != LF:
let rect = arrangement.selectionRects[i]
result.x = max(result.x, rect.x + rect.w)
let finalRect = arrangement.selectionRects[^1]
result.y = finalRect.y + finalRect.h
proc computeBounds*(font: Font, text: string): Vec2 {.inline.} =
## Computes the width and height of the text in pixels.
font.typeset(text).computeBounds()
proc computeBounds*(spans: seq[Span]): Vec2 {.inline.} =
typeset(spans).computeBounds()
proc parseOtf*(buf: string): Font =
result.typeface = Typeface()
result.typeface.opentype = parseOpenType(buf)
result.size = 12
result.lineHeight = AutoLineHeight
result.paint = Paint(kind: pkSolid, color: rgbx(0, 0, 0, 255))
proc parseTtf*(buf: string): Font =
parseOtf(buf)
proc parseSvgFont*(buf: string): Font =
result.typeface = Typeface()
result.typeface.svgFont = svgfont.parseSvgFont(buf)
result.size = 12
result.lineHeight = AutoLineHeight
result.paint = Paint(kind: pkSolid, color: rgbx(0, 0, 0, 255))

View file

@ -1,4 +1,4 @@
import blends, chroma, images, vmath
import blends, chroma, common, images, vmath
type
PaintKind* = enum
@ -9,7 +9,7 @@ type
pkGradientRadial
pkGradientAngular
Paint* = ref object
Paint* = object
## Paint used to fill paths.
case kind*: PaintKind
of pkSolid:
@ -27,7 +27,7 @@ type
color*: ColorRGBX ## Color of the stop
position*: float32 ## Gradient Stop position 0..1.
proc toLineSpace(at, to, point: Vec2): float32 =
proc toLineSpace(at, to, point: Vec2): float32 {.inline.} =
## Convert position on to where it would fall on a line between at and to.
let
d = to - at
@ -60,25 +60,44 @@ proc gradientPut(image: Image, x, y: int, a: float32, stops: seq[ColorStop]) =
)
image.setRgbaUnsafe(x, y, color.rgba.rgbx())
proc fillLinearGradient*(
image: Image,
at, to: Vec2,
stops: seq[ColorStop]
) =
proc fillGradientLinear*(image: Image, paint: Paint) =
## Fills a linear gradient.
if paint.kind != pkGradientLinear:
raise newException(PixieError, "Paint kind must be " & $pkGradientLinear)
if paint.gradientHandlePositions.len != 2:
raise newException(PixieError, "Linear gradient requires 2 handles")
if paint.gradientStops.len == 0:
raise newException(PixieError, "Gradient must have at least 1 color stop")
let
at = paint.gradientHandlePositions[0]
to = paint.gradientHandlePositions[1]
for y in 0 ..< image.height:
for x in 0 ..< image.width:
let xy = vec2(x.float32, y.float32)
let a = toLineSpace(at, to, xy)
image.gradientPut(x, y, a, stops)
let
xy = vec2(x.float32, y.float32)
a = toLineSpace(at, to, xy)
image.gradientPut(x, y, a, paint.gradientStops)
proc fillRadialGradient*(
image: Image,
center, edge, skew: Vec2,
stops: seq[ColorStop]
) =
proc fillGradientRadial*(image: Image, paint: Paint) =
## Fills a radial gradient.
if paint.kind != pkGradientRadial:
raise newException(PixieError, "Paint kind must be " & $pkGradientRadial)
if paint.gradientHandlePositions.len != 3:
raise newException(PixieError, "Radial gradient requires 3 handles")
if paint.gradientStops.len == 0:
raise newException(PixieError, "Gradient must have at least 1 color stop")
let
center = paint.gradientHandlePositions[0]
edge = paint.gradientHandlePositions[1]
skew = paint.gradientHandlePositions[2]
distanceX = dist(center, edge)
distanceY = dist(center, skew)
gradientAngle = normalize(center - edge).angle().fixAngle()
@ -89,23 +108,32 @@ proc fillRadialGradient*(
).inverse()
for y in 0 ..< image.height:
for x in 0 ..< image.width:
let xy = vec2(x.float32, y.float32)
let b = (mat * xy).length()
image.gradientPut(x, y, b, stops)
let
xy = vec2(x.float32, y.float32)
b = (mat * xy).length()
image.gradientPut(x, y, b, paint.gradientStops)
proc fillGradientAngular*(image: Image, paint: Paint) =
## Fills an angular gradient.
if paint.kind != pkGradientAngular:
raise newException(PixieError, "Paint kind must be " & $pkGradientAngular)
if paint.gradientHandlePositions.len != 3:
raise newException(PixieError, "Angular gradient requires 2 handles")
if paint.gradientStops.len == 0:
raise newException(PixieError, "Gradient must have at least 1 color stop")
proc fillAngularGradient*(
image: Image,
center, edge, skew: Vec2,
stops: seq[ColorStop]
) =
## Angular gradient.
# TODO: make edge between start and end anti-aliased.
let
gradientAngle = normalize(edge - center).angle().fixAngle()
center = paint.gradientHandlePositions[0]
edge = paint.gradientHandlePositions[1]
# TODO: make edge between start and end anti-aliased.
let gradientAngle = normalize(edge - center).angle().fixAngle()
for y in 0 ..< image.height:
for x in 0 ..< image.width:
let
xy = vec2(x.float32, y.float32)
angle = normalize(xy - center).angle()
a = (angle + gradientAngle + PI/2).fixAngle() / 2 / PI + 0.5
image.gradientPut(x, y, a, stops)
image.gradientPut(x, y, a, paint.gradientStops)

View file

@ -48,6 +48,11 @@ proc maxScale(m: Mat3): float32 =
vec2(m[1, 0], m[1, 1]).length
)
proc isRelative(kind: PathCommandKind): bool =
kind in {
RMove, RLine, TQuad, RTQuad, RHLine, RVLine, RCubic, RSCubic, RQuad, RArc
}
proc parameterCount(kind: PathCommandKind): int =
## Returns number of parameters a path command has.
case kind:
@ -231,7 +236,17 @@ proc parsePath*(path: string): Path =
proc transform*(path: var Path, mat: Mat3) =
## Apply a matrix transform to a path.
if mat == mat3():
return
if path.commands.len > 0 and path.commands[0].kind == RMove:
path.commands[0].kind = Move
for command in path.commands.mitems:
var mat = mat
if command.kind.isRelative():
mat.pos = vec2(0)
case command.kind:
of Close:
discard
@ -984,7 +999,7 @@ proc partitionSegments(
numPartitions = min(maxPartitions, max(1, segmentCount div 10).uint32)
partitionHeight = (height.uint32 div numPartitions)
var partitions = newSeq[seq[(Segment, int16)]](numPartitions)
result.setLen(numPartitions)
for shape in shapes:
for segment in shape.segments:
if segment.at.y == segment.to.y: # Skip horizontal
@ -997,17 +1012,15 @@ proc partitionSegments(
winding = -1
if partitionHeight == 0:
partitions[0].add((segment, winding))
result[0].add((segment, winding))
else:
var
atPartition = max(0, segment.at.y).uint32 div partitionHeight
toPartition = max(0, ceil(segment.to.y)).uint32 div partitionHeight
atPartition = clamp(atPartition, 0, partitions.high.uint32)
toPartition = clamp(toPartition, 0, partitions.high.uint32)
atPartition = clamp(atPartition, 0, result.high.uint32)
toPartition = clamp(toPartition, 0, result.high.uint32)
for i in atPartition .. toPartition:
partitions[i].add((segment, winding))
partitions
result[i].add((segment, winding))
template computeCoverages(
coverages: var seq[uint8],
@ -1415,6 +1428,18 @@ proc parseSomePath(
elif type(path) is seq[seq[Vec2]]:
path
proc transform(shapes: var seq[seq[Vec2]], transform: Vec2 | Mat3) =
when type(transform) is Vec2:
if transform != vec2(0, 0):
for shape in shapes.mitems:
for segment in shape.mitems:
segment += transform
else:
if transform != mat3():
for shape in shapes.mitems:
for segment in shape.mitems:
segment = transform * segment
proc fillPath*(
image: Image,
path: SomePath,
@ -1439,12 +1464,7 @@ proc fillPath*(
else:
let pixelScale = 1.0
var shapes = parseSomePath(path, pixelScale)
for shape in shapes.mitems:
for segment in shape.mitems:
when type(transform) is Vec2:
segment += transform
else:
segment = transform * segment
shapes.transform(transform)
image.fillShapes(shapes, color, windingRule, blendMode)
proc fillPath*(
@ -1467,30 +1487,26 @@ proc fillPath*(
else:
let pixelScale = 1.0
var shapes = parseSomePath(path, pixelScale)
for shape in shapes.mitems:
for segment in shape.mitems:
when type(transform) is Vec2:
segment += transform
else:
segment = transform * segment
shapes.transform(transform)
mask.fillShapes(shapes, windingRule)
proc fillPath*(
image: Image,
path: SomePath,
paint: Paint,
windingRule = wrNonZero,
transform: Vec2 | Mat3 = vec2(),
windingRule = wrNonZero
) =
## Fills a path.
if paint.kind == pkSolid:
image.fillPath(path, paint.color)
image.fillPath(path, paint.color, transform)
return
let
mask = newMask(image.width, image.height)
fill = newImage(image.width, image.height)
mask.fillPath(parseSomePath(path), windingRule)
mask.fillPath(parseSomePath(path), transform, windingRule)
case paint.kind:
of pkSolid:
@ -1500,25 +1516,11 @@ proc fillPath*(
of pkImageTiled:
fill.drawTiled(paint.image, paint.imageMat)
of pkGradientLinear:
fill.fillLinearGradient(
paint.gradientHandlePositions[0],
paint.gradientHandlePositions[1],
paint.gradientStops
)
fill.fillGradientLinear(paint)
of pkGradientRadial:
fill.fillRadialGradient(
paint.gradientHandlePositions[0],
paint.gradientHandlePositions[1],
paint.gradientHandlePositions[2],
paint.gradientStops
)
fill.fillGradientRadial(paint)
of pkGradientAngular:
fill.fillAngularGradient(
paint.gradientHandlePositions[0],
paint.gradientHandlePositions[1],
paint.gradientHandlePositions[2],
paint.gradientStops
)
fill.fillGradientAngular(paint)
fill.draw(mask)
image.draw(fill, blendMode = paint.blendMode)
@ -1556,12 +1558,7 @@ proc strokePath*(
var strokeShapes = strokeShapes(
parseSomePath(path, pixelScale), strokeWidth, lineCap, lineJoin
)
for shape in strokeShapes.mitems:
for segment in shape.mitems:
when type(transform) is Vec2:
segment += transform
else:
segment = transform * segment
strokeShapes.transform(transform)
image.fillShapes(strokeShapes, color, wrNonZero, blendMode)
proc strokePath*(
@ -1593,13 +1590,47 @@ proc strokePath*(
var strokeShapes = strokeShapes(
parseSomePath(path, pixelScale), strokeWidth, lineCap, lineJoin
)
for shape in strokeShapes.mitems:
for segment in shape.mitems:
when type(transform) is Vec2:
segment += transform
else:
segment = transform * segment
strokeShapes.transform(transform)
mask.fillShapes(strokeShapes, wrNonZero)
proc strokePath*(
image: Image,
path: SomePath,
paint: Paint,
transform: Vec2 | Mat3 = vec2(),
strokeWidth = 1.0,
lineCap = lcButt,
lineJoin = ljMiter
) =
## Fills a path.
if paint.kind == pkSolid:
image.strokePath(
path, paint.color, transform, strokeWidth, lineCap, lineJoin
)
return
let
mask = newMask(image.width, image.height)
fill = newImage(image.width, image.height)
mask.strokePath(parseSomePath(path), transform)
case paint.kind:
of pkSolid:
discard # Handled above
of pkImage:
fill.draw(paint.image, paint.imageMat)
of pkImageTiled:
fill.drawTiled(paint.image, paint.imageMat)
of pkGradientLinear:
fill.fillGradientLinear(paint)
of pkGradientRadial:
fill.fillGradientRadial(paint)
of pkGradientAngular:
fill.fillGradientAngular(paint)
fill.draw(mask)
image.draw(fill, blendMode = paint.blendMode)
when defined(release):
{.pop.}

19
tests/benchmark_fonts.nim Normal file
View file

@ -0,0 +1,19 @@
import benchy, pixie
const text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis in quam in nulla bibendum luctus. Integer dui lectus, ultricies commodo enim quis, laoreet lacinia erat. Vivamus ultrices maximus risus, non aliquam quam sagittis quis. Ut nec diam vitae tortor interdum ullamcorper in aliquet velit. Ut sed lobortis mi. Nulla venenatis lectus varius justo lacinia, quis sollicitudin nunc ultrices. Donec a suscipit arcu, id egestas neque. Nullam commodo pharetra est. Nullam gravida nibh eget quam venenatis lacinia. Vestibulum et libero arcu. Sed dignissim enim eros. Nullam eleifend luctus erat sed luctus. Nunc tincidunt, mi nec tincidunt tristique, ex nulla lobortis sem, sit amet finibus purus justo non massa."
var font = readFont("tests/fonts/Roboto-Regular_1.ttf")
font.size = 16
let
image = newImage(500, 300)
mask = newMask(500, 300)
timeIt "typeset":
discard font.typeset(text, bounds = image.wh)
timeIt "rasterize":
image.fill(rgba(255, 255, 255, 255))
image.fillText(font, text, bounds = image.wh)
# mask.fill(0)
# mask.fillText(font, text, bounds = mask.wh)

7
tests/common.nim Normal file
View file

@ -0,0 +1,7 @@
import algorithm, os
proc findAllFonts*(rootPath: string): seq[string] =
for fontPath in walkDirRec(rootPath):
if splitFile(fontPath).ext in [".ttf", ".otf"]:
result.add(fontPath)
result.sort()

Binary file not shown.

2420
tests/fonts/Changa-Bold.svg Normal file

File diff suppressed because it is too large Load diff

After

(image error) Size: 314 KiB

18479
tests/fonts/DejaVuSans.svg Normal file

File diff suppressed because it is too large Load diff

After

(image error) Size: 2 MiB

File diff suppressed because it is too large Load diff

After

(image error) Size: 998 KiB

Binary file not shown.

616
tests/fonts/Moon-Bold.svg Normal file
View file

@ -0,0 +1,616 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<metadata>
Created by FontForge 20170910 at Sat Feb 7 18:47:58 2015
By Jimmy Wärting
Moon (c) Jack Harvatt 2015. All Rights Reserved
</metadata>
<defs>
<font id="Moon-Bold" horiz-adv-x="1014" >
<font-face
font-family="Moon"
font-weight="700"
font-stretch="normal"
units-per-em="2048"
panose-1="2 0 5 0 0 0 0 0 0 0"
ascent="1638"
descent="-410"
x-height="1422"
cap-height="1429"
bbox="-342 -418 2048 1716"
underline-thickness="150"
underline-position="-292"
unicode-range="U+001D-F002"
/>
<missing-glyph horiz-adv-x="1024"
d="M100 0v1434h824v-1434h-824zM150 50h724v1334h-724v-1334zM325 1148q31 28 58 43q53 30 112 30q92 0 148 -47.5t56 -127.5q0 -49 -23 -98.5t-87 -129.5q-63 -80 -99 -132t-36 -99q0 -38 24 -133h-32q-35 97 -35 148q0 76 81.5 218t81.5 217q0 57 -33 90t-91 33
q-38 0 -69 -17q-26 -15 -56 -40v45zM389 334l57 58q11 10 20 10q10 0 22 -11l56 -60q9 -11 9 -20q0 -11 -10 -22l-56 -62q-14 -14 -21 -14q-11 0 -20 10l-61 71q-7 9 -7 18q0 10 11 22z" />
<glyph glyph-name=".notdef" horiz-adv-x="1024"
d="M100 0v1434h824v-1434h-824zM150 50h724v1334h-724v-1334zM325 1148q31 28 58 43q53 30 112 30q92 0 148 -47.5t56 -127.5q0 -49 -23 -98.5t-87 -129.5q-63 -80 -99 -132t-36 -99q0 -38 24 -133h-32q-35 97 -35 148q0 76 81.5 218t81.5 217q0 57 -33 90t-91 33
q-38 0 -69 -17q-26 -15 -56 -40v45zM389 334l57 58q11 10 20 10q10 0 22 -11l56 -60q9 -11 9 -20q0 -11 -10 -22l-56 -62q-14 -14 -21 -14q-11 0 -20 10l-61 71q-7 9 -7 18q0 10 11 22z" />
<glyph glyph-name=".null" horiz-adv-x="0"
/>
<glyph glyph-name=".null" horiz-adv-x="0"
/>
<glyph glyph-name="nonmarkingreturn" horiz-adv-x="508"
/>
<glyph glyph-name="space" unicode=" " horiz-adv-x="508"
/>
<glyph glyph-name="space" unicode="&#xa0;" horiz-adv-x="508"
/>
<glyph glyph-name="exclam" unicode="!" horiz-adv-x="970"
d="M424 1431q-49 0 -83 -35t-34 -83l4 -865q0 -49 34 -83q35 -34 83 -34h1q49 0 83 35q34 34 34 83l-4 865q0 48 -34 83q-35 34 -83 34h-1zM343 201q-35 -34 -35 -83t35 -83q35 -35 83 -35q49 0 83 35q35 34 35 83t-35 83q-34 34 -83 34t-83 -34z" />
<glyph glyph-name="quotedbl" unicode="&#x22;" horiz-adv-x="1072"
d="M279 1398q-34 -35 -34 -83v-187q0 -49 34 -84q35 -34 84 -34q48 0 83 34q34 35 34 84v187q0 48 -34 83q-35 34 -83 34q-49 0 -84 -34zM563 1398q-34 -35 -34 -83v-187q0 -49 34 -84q34 -34 83 -34t83 34q35 35 35 84v187q0 48 -35 83q-34 34 -83 34t-83 -34z" />
<glyph glyph-name="numbersign" unicode="#" horiz-adv-x="1478"
d="M827 603h-284l19 228h283zM1101 1067l20 238q4 49 -28 86t-80 41q-49 4 -86 -28q-37 -31 -41 -80l-21 -257h-284l20 238q4 49 -28 86q-31 37 -80 41t-86 -28q-37 -31 -41 -80l-21 -257h-139q-49 0 -84 -35q-34 -34 -34 -83t34 -84q35 -34 84 -34h120l-19 -228h-139
q-49 0 -83 -34q-35 -35 -35 -84t35 -83q34 -35 83 -35h120l-20 -240q-4 -48 28 -85q31 -38 80 -42h10q45 0 79 31t38 77l21 259h283l-19 -240q-4 -48 27 -85q32 -38 81 -42h9q46 0 80 31t38 77l21 259h133q49 0 83 35q35 34 35 83t-35 84q-34 34 -83 34h-114l19 228h133
q49 0 83 34q35 35 35 84t-35 83q-34 35 -83 35h-114z" />
<glyph glyph-name="dollar" unicode="$" horiz-adv-x="1146"
d="M698 490q-3 -67 -59 -109v194q21 -11 35 -25q25 -27 24 -60zM403 857q-23 11 -37 25q-25 27 -24 60q3 69 61 111v-196zM756 919q42 -25 89 -13q48 13 72 55q25 42 13 89q-25 97 -103 165q-76 67 -188 93v8q0 49 -35 84q-34 34 -83 34t-83 -34q-35 -35 -35 -84v-7
q-125 -33 -207 -130q-84 -99 -89 -226q-6 -133 88 -232q78 -84 208 -111v-237q-53 26 -65 69q-12 47 -54 72t-90 12q-47 -12 -72 -54q-24 -42 -12 -90q25 -97 103 -165q77 -67 190 -93v-6q0 -49 35 -83q34 -35 83 -35t83 35q35 34 35 83v7q125 33 206 129q83 99 88 226
q6 133 -88 232q-77 83 -206 110v237q51 -26 62 -68q13 -48 55 -72z" />
<glyph glyph-name="percent" unicode="%" horiz-adv-x="1608"
d="M318 1181q18 18 43 18q26 0 44 -18t18 -44q0 -25 -18 -43t-44 -18q-25 0 -43 18t-18 43q0 26 18 44zM571 1347q-87 88 -210 88t-210 -88q-87 -87 -87 -210q0 -122 87 -210q87 -87 210 -87t210 87q87 88 87 210q0 123 -87 210zM1102 262q-18 18 -18 44q0 25 18 43t44 18
q25 0 43 -18t18 -43q0 -26 -18 -44t-43 -18q-26 0 -44 18zM936 516q-87 -87 -87 -210t87 -210t210 -87t210 87t87 210t-87 210t-210 87t-210 -87zM1173 1430q-48 -7 -77 -47l-869 -1196q-29 -39 -22 -88q8 -48 48 -76q31 -23 69 -23q60 0 95 49l870 1196q29 39 21 87
q-7 49 -47 77q-39 29 -88 21z" />
<glyph glyph-name="ampersand" unicode="&#x26;" horiz-adv-x="1400"
d="M367 305q-61 61 -61 147t61 147q61 60 147 60t147 -60q60 -61 60 -147t-60 -147q-61 -61 -147 -61t-147 61zM687 1160q34 -34 34 -82t-34 -83q-34 -34 -82 -34q-49 0 -83 34q-34 35 -34 83t34 82q34 35 83 35q48 0 82 -35zM835 800q130 109 130 278q0 149 -105 255
q-106 106 -255 106q-150 0 -256 -106q-105 -106 -105 -255q0 -122 74 -219q-115 -56 -185 -164q-71 -111 -71 -243q0 -187 132 -320q133 -132 320 -132q134 0 247 74q109 71 163 190l144 -197q37 -50 99 -50q40 0 72 23q40 30 48 80t-22 91z" />
<glyph glyph-name="quotesingle" unicode="'" horiz-adv-x="801"
d="M286 1399q-34 -34 -34 -83v-187q0 -49 34 -84q35 -34 84 -34t83 34q35 35 35 84v187q0 49 -35 83q-34 35 -83 35t-84 -35z" />
<glyph glyph-name="parenleft" unicode="(" horiz-adv-x="1033"
d="M653 1253q25 42 13 89q-11 47 -53 72t-89 13q-47 -11 -72 -53q-170 -283 -170 -659q0 -375 170 -658q34 -57 101 -57q32 0 60 17q42 25 53 72q12 47 -13 89q-136 227 -136 537q0 311 136 538z" />
<glyph glyph-name="parenright" unicode=")" horiz-adv-x="1058"
d="M263 1342q-12 -47 13 -89q136 -227 136 -538q0 -310 -136 -537q-25 -42 -13 -89t53 -72q28 -17 61 -17q66 0 100 57q170 283 170 658q0 376 -170 659q-25 42 -72 53q-47 12 -89 -13q-41 -25 -53 -72z" />
<glyph glyph-name="asterisk" unicode="*" horiz-adv-x="1170"
d="M728 1434q-49 0 -84 -34l-98 -99l-98 99q-35 34 -83 34q-49 0 -84 -34q-34 -35 -34 -83q0 -49 34 -84l99 -98l-99 -98q-34 -35 -34 -83q0 -49 34 -84q35 -34 84 -34q48 0 83 35l98 98l98 -98q35 -35 84 -35q48 0 83 34q34 35 34 84q0 48 -34 83l-99 98l99 98q34 35 34 84
q0 48 -34 83q-35 34 -83 34z" />
<glyph glyph-name="plus" unicode="+" horiz-adv-x="1164"
d="M634 842v132q0 49 -34 84q-35 34 -84 34q-48 0 -83 -34q-34 -35 -34 -84v-132h-132q-49 0 -84 -34q-34 -35 -34 -83q0 -49 34 -84q35 -34 84 -34h132v-132q0 -49 34 -83q35 -35 83 -35q49 0 84 35q34 34 34 83v132h132q49 0 83 34q35 35 35 84q0 48 -35 83q-34 34 -83 34
h-132z" />
<glyph glyph-name="comma" unicode="," horiz-adv-x="813"
d="M294 395q-34 -35 -34 -83v-187q0 -48 34 -83q35 -34 83 -34q49 0 83 34q35 35 35 83v187q0 48 -35 83q-34 34 -83 34q-48 0 -83 -34z" />
<glyph glyph-name="hyphen" unicode="-" horiz-adv-x="1191"
d="M284 837q-49 0 -83 -35q-35 -34 -35 -83t35 -83q34 -35 83 -35h501q49 0 83 35q35 34 35 83t-35 83q-34 35 -83 35h-501z" />
<glyph glyph-name="hyphen" unicode="&#xad;" horiz-adv-x="1191"
d="M284 837q-49 0 -83 -35q-35 -34 -35 -83t35 -83q34 -35 83 -35h501q49 0 83 35q35 34 35 83t-35 83q-34 35 -83 35h-501z" />
<glyph glyph-name="period" unicode="." horiz-adv-x="731"
d="M255 208q-34 -34 -34 -83t34 -83q35 -34 83 -34q49 0 83 34q35 34 35 83t-35 83q-34 34 -83 34q-48 0 -83 -34z" />
<glyph glyph-name="slash" unicode="/" horiz-adv-x="1000"
d="M425 1401q-37 -31 -41 -80l-98 -1194q-4 -48 28 -85q32 -38 80 -42h10q45 0 79 31t38 77l98 1194q4 49 -28 86t-80 41q-49 4 -86 -28z" />
<glyph glyph-name="zero" unicode="0" horiz-adv-x="1175"
d="M780 416q0 -75 -53 -128q-54 -53 -129 -53t-128 53t-53 128v598q0 75 53 129q53 53 128 53t129 -53q53 -54 53 -129v-598zM304 1309q-122 -122 -122 -295v-598q0 -172 122 -294t294 -122q173 0 295 122t122 294v598q0 173 -122 295t-295 122q-172 0 -294 -122z" />
<glyph glyph-name="one" unicode="1" horiz-adv-x="1175"
d="M552 1143v-1025q0 -49 35 -83q34 -35 83 -35t84 35q34 34 34 83v1193q0 61 -50 96t-108 15l-308 -112q-46 -17 -67 -61q-20 -44 -4 -90q17 -46 61 -67q44 -20 90 -4z" />
<glyph glyph-name="two" unicode="2" horiz-adv-x="1175"
d="M1003 202q-34 34 -83 34h-378l413 600q6 9 10 19q36 80 36 168q0 171 -121 292t-292 121q-170 0 -291 -121t-121 -292q0 -13 1 -27q3 -49 40 -81q36 -32 85 -29t81 40q33 36 30 85q-1 6 -1 12q0 73 52 125q52 51 124 51q73 0 125 -51q52 -52 52 -125q0 -33 -12 -63
l-533 -775q-40 -59 -7 -122t104 -63h603q49 0 83 35q35 34 35 83t-35 84z" />
<glyph glyph-name="three" unicode="3" horiz-adv-x="1175"
d="M947 649q-68 102 -180 152l214 465q27 59 -8 113t-99 54h-575q-49 0 -83 -34q-35 -35 -35 -84t35 -83q34 -35 83 -35h391l-198 -430q-27 -58 8 -113q34 -54 99 -54q75 0 129 -53q53 -54 53 -129t-53 -129q-54 -53 -129 -53t-129 53q-53 54 -53 129q0 49 -35 83
q-34 35 -83 35t-83 -35q-35 -34 -35 -83q0 -173 123 -295q122 -123 295 -123t295 123q123 122 123 295q0 126 -70 231z" />
<glyph glyph-name="four" unicode="4" horiz-adv-x="1174"
d="M481 614l225 325v-325h-225zM706 118q0 -49 35 -83q35 -35 83 -35q49 0 84 35q34 34 34 83v1197q0 39 -23 70q-22 31 -59 43q-37 11 -74 -1q-36 -13 -59 -44l-569 -820q-40 -58 -7 -122q33 -63 104 -63h451v-260z" />
<glyph glyph-name="five" unicode="5" horiz-adv-x="1175"
d="M908 713q-122 123 -295 123h-146v359h444q49 0 83 34q35 35 35 84t-35 83q-34 35 -83 35h-562q-49 0 -83 -35q-35 -34 -35 -83v-595q0 -49 35 -83q34 -35 83 -35h264q75 0 129 -53q53 -54 53 -129t-53 -129q-54 -53 -129 -53t-129 53q-53 54 -53 129q0 49 -35 83
q-34 35 -83 35t-83 -35q-35 -34 -35 -83q0 -173 123 -295q122 -123 295 -123t295 123q123 122 123 295t-123 295z" />
<glyph glyph-name="six" unicode="6" horiz-adv-x="1175"
d="M485 289q-53 54 -53 129t53 129q54 53 129 53t129 -53q53 -54 53 -129t-53 -129q-54 -53 -129 -53t-129 53zM568 833l157 444q16 47 -5 91t-67 60t-90 -5t-60 -67l-281 -793q0 -1 -2 -5l-1 -4q0 1 -1 -2q-22 -65 -22 -134q0 -173 123 -295q122 -123 295 -123t295 123
q123 122 123 295t-123 295q-122 123 -295 123q-23 0 -46 -3z" />
<glyph glyph-name="seven" unicode="7" horiz-adv-x="1175"
d="M265 1437q-49 0 -83 -34q-35 -35 -35 -84t35 -83q34 -35 83 -35h443l-401 -1040q-18 -46 2 -91q20 -44 65 -62q21 -8 43 -8q36 0 66 20q31 21 44 56l464 1201q23 58 -13 109q-35 51 -97 51h-616z" />
<glyph glyph-name="eight" unicode="8" horiz-adv-x="1175"
d="M472 1143q53 53 128 53t129 -53q53 -54 53 -129t-53 -128q-54 -53 -129 -53t-128 53t-53 128t53 129zM729 288q-54 -53 -129 -53t-128 53t-53 128q0 76 53 129t128 53t129 -53q53 -53 53 -129q0 -75 -53 -128zM895 1309q-122 122 -295 122q-172 0 -294 -122t-122 -295
q0 -176 127 -299q-127 -123 -127 -299q0 -172 122 -294t294 -122q173 0 295 122t122 294q0 176 -127 299q127 123 127 299q0 173 -122 295z" />
<glyph glyph-name="nine" unicode="9" horiz-adv-x="1175"
d="M473 1142q54 53 129 53t128 -53t53 -129q0 -75 -53 -128t-128 -53t-129 53q-53 53 -53 128q0 76 53 129zM307 1308q-122 -122 -122 -295q0 -172 122 -294t295 -122q22 0 45 2l-156 -442q-16 -46 4 -90q21 -44 67 -60q19 -7 40 -7q36 0 67 21q31 22 43 57l280 791l2 5l2 4
q-1 -2 0 2q22 65 22 133q0 173 -122 295t-294 122q-173 0 -295 -122z" />
<glyph glyph-name="colon" unicode=":" horiz-adv-x="540"
d="M142 543q-34 -35 -34 -84q0 -48 34 -83q35 -34 83 -34q49 0 83 34q35 35 35 83q0 49 -35 84q-34 34 -83 34t-83 -34zM142 1059q-34 -35 -34 -84q0 -48 34 -83q35 -34 83 -34q49 0 83 34q35 35 35 83q0 49 -35 84q-34 34 -83 34q-48 0 -83 -34z" />
<glyph glyph-name="semicolon" unicode=";" horiz-adv-x="548"
d="M136 1059q-34 -34 -34 -83t34 -83q35 -35 83 -35q49 0 84 35q34 34 34 83q0 48 -34 83q-35 35 -84 35q-48 0 -83 -35zM136 543q-34 -35 -34 -83v-125q0 -48 34 -83q35 -34 83 -34q49 0 84 34q34 35 34 83v125q0 48 -34 83q-35 34 -84 34q-48 0 -83 -34z" />
<glyph glyph-name="semicolon" unicode="&#x37e;" horiz-adv-x="548"
d="M136 1059q-34 -34 -34 -83t34 -83q35 -35 83 -35q49 0 84 35q34 34 34 83q0 48 -34 83q-35 35 -84 35q-48 0 -83 -35zM136 543q-34 -35 -34 -83v-125q0 -48 34 -83q35 -34 83 -34q49 0 84 34q34 35 34 83v125q0 48 -34 83q-35 34 -84 34q-48 0 -83 -34z" />
<glyph glyph-name="less" unicode="&#x3c;" horiz-adv-x="839"
d="M546 1085q-47 11 -88 -16l-417 -272v0q-4 -2 -8 -6h-1q0 -1 -1 -1q-1 -1 -6 -5l-3 -3l-3 -4l-5 -5q2 2 -1 -2q-4 -5 -6 -8v0q1 2 -1 -2q-3 -5 -5 -8q1 1 -2 -4q-2 -4 -2 -6q-1 -1 -2 -6q-2 -5 -2 -4q0 -2 -2 -7q-1 -5 -1 -4q0 -2 -1 -7v-5q-1 -1 -1 -6v-5v-6t1 -6v-5
q1 -4 1 -6l1 -5q2 -5 2 -6l2 -5q1 -4 2 -6q0 -1 2 -6q3 -4 2 -4q2 -3 5 -7q2 -5 1 -3v0q4 -6 9 -11q-1 0 2 -2q3 -4 7 -8q2 -1 4 -3q3 -3 6 -5q4 -3 5 -4q2 -1 1 -1l417 -271q29 -20 64 -20q64 0 99 54q26 41 16 88q-10 48 -51 75l-265 173l265 173q41 26 51 74t-16 89
q-27 40 -75 50z" />
<glyph glyph-name="equal" unicode="=" horiz-adv-x="971"
d="M182 619q-48 0 -83 -34q-34 -34 -34 -83q0 -48 34 -83q35 -34 83 -34h498q49 0 83 34q34 35 34 83q0 49 -34 83t-83 34h-498zM182 1006q-48 0 -83 -34q-34 -34 -34 -83q0 -48 34 -83q35 -34 83 -34h498q49 0 83 34q34 35 34 83q0 49 -34 83t-83 34h-498z" />
<glyph glyph-name="greater" unicode="&#x3e;" horiz-adv-x="853"
d="M735 733q0 5 -1 7l-1 4q-1 5 -1 7l-2 4q-1 5 -2 6l-3 6t-2 5q-1 2 -4 7q-4 5 -2 2q1 0 0 1q-2 3 -5 7l-1 1l-1 1q-1 2 -5 6q-4 5 -3 3q1 -1 -3 3t-6 5l-1 1l-1 1q-4 3 -7 5h-1l-416 272q-41 26 -88 16q-48 -10 -75 -50q-26 -41 -16 -89t51 -74l265 -173l-265 -173
q-41 -27 -51 -74q-10 -48 16 -89q35 -53 99 -53q35 0 64 19l416 271l2 2q1 0 4 3q4 2 7 5q2 2 4 3q3 4 7 8l2 2q4 5 8 11v1v0q-2 -3 2 2q3 4 4 7q0 1 2 5q2 3 3 5t2 6q1 5 2 5q0 1 1 7l1 4q1 2 1 7q1 3 1 4v7v5v5v7q0 1 -1 4z" />
<glyph glyph-name="question" unicode="?" horiz-adv-x="1069"
d="M396 201q-34 -34 -34 -83t34 -83q35 -35 84 -35q48 0 83 35q35 34 35 83t-35 83q-34 35 -83 35t-84 -35zM187 1311q-123 -123 -123 -295q0 -49 35 -84q34 -34 83 -34t83 34q35 35 35 84q0 75 53 128q54 54 129 54t129 -54q53 -53 53 -128q0 -76 -53 -129
q-54 -53 -129 -53q-49 0 -83 -35q-35 -35 -35 -83v-256q0 -49 35 -83q34 -35 83 -35t83 35q35 34 35 83v155q131 38 215 148q85 112 85 253q0 172 -123 295q-122 123 -295 123t-295 -123z" />
<glyph glyph-name="at" unicode="@" horiz-adv-x="1718"
d="M720 632q-36 36 -36 86t36 86q36 35 86 35t86 -35q35 -36 35 -86t-35 -86q-36 -36 -86 -36t-86 36zM298 1225q-210 -210 -210 -507t210 -508q211 -210 508 -210q150 0 287 60q45 19 63 65t-2 91t-65 62q-46 18 -91 -1q-91 -40 -192 -40q-199 0 -340 141t-141 340t141 340
t340 141t340 -141t141 -340q0 -83 -28 -161l-106 74q11 44 11 87q0 148 -105 253t-253 105t-253 -105t-105 -253t105 -253t253 -105q120 0 217 73l212 -148q41 -28 90 -19q48 9 76 50q123 182 123 402q0 297 -211 507q-210 211 -507 211t-508 -211z" />
<glyph glyph-name="A" unicode="A" horiz-adv-x="1349"
d="M446 540l192 464l193 -464h-385zM144 0q79 0 109 73l96 232h579l96 -232q30 -73 109 -73q23 0 45 9q45 19 64 64q18 45 0 90l-127 305v1l-368 888v0q-2 5 -5 10q0 1 -3 5t-3 5t-4 5l-3 4q0 1 -4 5q-3 3 -3 4q-2 1 -5 4t-4 3q-1 1 -5 4l-4 3q-1 1 -6 4t-4 2q-10 6 -22 9
q2 0 -4 1q-5 2 -7 2l-5 1l-6 1h-6h-6h-5h-6l-5 -1t-7 -1l-4 -1q-6 -2 -7 -2q-2 -1 -7 -2q-6 -3 -4 -2t-3 -2q-5 -2 -7 -3q-1 0 -6 -3l-4 -3q-1 -1 -5 -4q-5 -3 -4 -3q-1 0 -5 -4q-3 -2 -4 -3q0 -1 -4 -5q-3 -3 -3 -4l-4 -4q-3 -4 -3 -5q-1 -1 -4 -5l-2 -5q-3 -5 -5 -10v0
l-368 -888v-1l-127 -305q-18 -45 0 -90q19 -45 64 -64q22 -9 45 -9z" />
<glyph glyph-name="B" unicode="B" horiz-adv-x="1290"
d="M350 596h302h16h9q88 0 149 -52q61 -51 61 -125q0 -76 -62 -129q-62 -54 -150 -54h-325v360zM350 1195l302 2q88 0 149 -52q61 -51 61 -126q0 -76 -62 -132q-63 -55 -148 -55h-302v363zM675 0q185 0 316 123q132 123 132 296q0 187 -148 309q123 123 123 291
q0 174 -129 294q-130 120 -318 120l-420 -2q-48 -1 -83 -35q-34 -35 -34 -83v-1195q0 -49 35 -83q34 -35 83 -35h443z" />
<glyph glyph-name="C" unicode="C" horiz-adv-x="1385"
d="M1233 186q36 33 38 82t-31 85q-33 37 -82 39t-85 -31q-136 -124 -322 -124q-197 0 -337 140t-140 337q0 198 140 338t337 140q163 0 291 -99q39 -29 88 -23q48 6 78 45t24 88q-7 48 -45 78q-193 148 -436 148q-295 0 -505 -210q-209 -209 -209 -505q0 -295 209 -505
q210 -209 505 -209q277 0 482 186z" />
<glyph glyph-name="D" unicode="D" horiz-adv-x="1429"
d="M351 1197h184q198 0 338 -141q140 -140 140 -337q0 -198 -140 -338t-339 -140l-183 -3v959zM234 0l301 4q296 0 506 210q209 209 209 505q0 295 -209 505q-210 209 -506 209h-303q-49 0 -83 -34q-35 -35 -35 -84v-1197q0 -49 35 -84q35 -34 83 -34h2z" />
<glyph glyph-name="E" unicode="E" horiz-adv-x="1183"
d="M351 237v363h436q49 0 84 34q35 35 35 84t-35 84q-35 34 -84 34h-436v363l604 -2h1q49 0 83 35q35 34 35 83t-34 84q-35 35 -84 35l-723 2h-1q-49 0 -83 -35q-35 -34 -35 -84v-1199q0 -49 35 -83q34 -35 83 -35h724q49 0 83 35q35 34 35 83t-35 84q-34 35 -83 35h-605z
" />
<glyph glyph-name="F" unicode="F" horiz-adv-x="1154"
d="M230 1436h-1q-49 0 -83 -35q-35 -34 -35 -84v-1199q0 -49 35 -83q34 -35 83 -35t84 35q35 34 35 83v482h436q49 0 84 34q35 35 35 84t-35 84q-35 34 -84 34h-436v363l604 -2h1q49 0 83 35q35 34 35 83t-34 84q-35 35 -84 35z" />
<glyph glyph-name="G" unicode="G" horiz-adv-x="1490"
d="M1079 86q10 -37 41 -61q32 -25 72 -25h1q49 0 83 35q35 34 35 83l3 634q0 49 -35 84t-84 35h-510q-50 0 -84 -35q-35 -35 -35 -84t35 -84q34 -34 84 -34h391l-1 -262q-5 -4 -7 -6q-137 -125 -322 -125q-198 0 -339 140q-140 141 -140 339q0 197 140 338q141 140 339 140
q162 0 291 -99q39 -30 88 -23q48 6 78 45t24 87q-7 49 -46 79q-192 148 -435 148q-296 0 -506 -210q-210 -209 -210 -505t210 -506t506 -210q176 0 333 82z" />
<glyph glyph-name="H" unicode="H" horiz-adv-x="1426"
d="M1170 35q35 35 35 84v1195q0 49 -35 84t-84 35t-84 -35t-35 -84v-479h-616v479q0 49 -34 84q-35 35 -84 35t-84 -35t-35 -84v-1195q0 -49 35 -84t84 -35t84 35q34 35 34 84v479h616v-479q0 -49 35 -84t84 -35t84 35z" />
<glyph glyph-name="I" unicode="I" horiz-adv-x="549"
d="M315 35q35 34 35 83v1193q0 49 -35 83q-34 35 -83 35t-83 -35q-35 -34 -35 -83v-1193q0 -49 35 -83q34 -35 83 -35t83 35z" />
<glyph glyph-name="J" unicode="J" horiz-adv-x="753"
d="M310 435q0 -82 -58 -140t-140 -58q-49 0 -83 -35q-35 -35 -35 -84t35 -83q34 -35 83 -35q180 0 308 127q127 128 127 308v880q0 49 -35 84q-34 35 -83 35t-84 -35t-35 -84v-880z" />
<glyph glyph-name="K" unicode="K" horiz-adv-x="1246"
d="M314 44q34 34 34 82v322l99 105l491 -517q35 -36 85 -36q47 0 81 32q35 34 36 82t-32 84l-499 525l480 505q34 35 32 84q-1 48 -36 81q-35 34 -83 33q-49 -2 -82 -37l-572 -601v526q0 48 -34 82q-35 35 -83 35t-83 -35q-34 -34 -34 -82v-1188q0 -48 34 -82q35 -35 83 -35
t83 35z" />
<glyph glyph-name="L" unicode="L" horiz-adv-x="1077"
d="M153 1399q-35 -34 -35 -83v-1198q0 -49 35 -83q34 -35 83 -35h647q49 0 84 35q34 34 34 83t-34 83q-35 35 -84 35h-529v1080q0 49 -35 83q-34 35 -83 35t-83 -35z" />
<glyph glyph-name="M" unicode="M" horiz-adv-x="1758"
d="M1375 1430q-37 -15 -57 -49l-492 -813l-492 813q-21 34 -58 49q-37 14 -75 4q-39 -11 -63 -43q-24 -31 -24 -71v-1202q0 -49 35 -83q34 -35 83 -35t84 35q35 34 35 83v778l372 -616q1 0 1 -1v-1q1 0 1 -1l1 -1q3 -5 5 -7q0 -1 2 -4q4 -3 5 -5l4 -4l4 -4q2 -2 6 -5
q3 -3 3 -2q3 -3 7 -5l1 -1l1 -1h1v0q3 -2 8 -4q3 -2 2 -2q2 -1 7 -3q6 -2 4 -1q-1 0 4 -1q13 -4 26 -5q6 -1 4 -1h2q25 -1 48 9q5 2 6 2q-1 0 3 2q5 2 7 4h1l1 1q1 0 1 1q4 2 7 4l3 3q4 3 6 5l4 4l4 4l5 5l3 4q1 2 4 7l1 1l1 1l1 1v1l373 616v-778q0 -49 34 -83
q35 -35 84 -35t84 35q34 34 34 83v1202q0 40 -24 71q-24 32 -62 43q-39 10 -76 -4z" />
<glyph glyph-name="N" unicode="N" horiz-adv-x="1500"
d="M1077 37v-1l1 -1q4 -4 9 -8q1 -1 4 -3q4 -3 7 -5q1 -1 4 -3q3 -1 7 -3q2 -2 4 -2q3 -2 8 -3q3 -2 4 -2q3 -1 8 -2q5 -2 4 -1q4 -1 10 -2q4 -1 2 0q7 -1 13 -1v0q8 0 17 1l3 1q9 1 17 4q-2 -1 2 1q8 3 16 7v0h1q7 4 15 10v0l1 1q4 3 1 1q2 1 5 4q4 3 4 4q1 0 4 4l4 4l3 4
t4 6l3 3l3 6l3 5l2 5q1 2 2 6q2 4 2 5q1 1 2 6l1 5q1 2 1 6q1 4 1 6v5q1 4 1 6v1200q0 49 -35 83q-34 35 -83 35t-84 -35q-34 -34 -34 -83v-854l-719 926q-23 30 -59 41q-37 11 -72 -2q-36 -12 -58 -43q-22 -30 -22 -68v-1198q0 -49 35 -83q34 -35 83 -35t83 35q35 34 35 83
v853l719 -925v-1h1q3 -4 7 -8z" />
<glyph glyph-name="O" unicode="O" horiz-adv-x="1644"
d="M1090 1059q141 -142 141 -341t-141 -340q-142 -142 -341 -142t-340 142q-142 141 -142 340t142 341q141 141 340 141t341 -141zM1257 211q210 210 210 507t-210 508q-211 210 -508 210t-507 -210q-211 -211 -211 -508t211 -507q210 -211 507 -211t508 211z" />
<glyph glyph-name="P" unicode="P" horiz-adv-x="1226"
d="M347 835v366h299q88 0 150 -54t62 -129q0 -74 -60 -128q-60 -53 -145 -55h-306zM229 1437q-49 0 -83 -35q-35 -34 -35 -83v-1201q0 -49 35 -83q34 -35 83 -35t84 35q34 34 34 83v481h293l6 -1q1 0 12 1h2h1h1q180 6 306 127q127 122 127 292q0 173 -132 296
q-131 123 -317 123h-417z" />
<glyph glyph-name="Q" unicode="Q" horiz-adv-x="1639"
d="M414 377q-141 141 -141 340t141 340t340 141t340 -141t141 -340q0 -124 -60 -232l-79 80q-34 34 -83 34t-84 -34q-34 -35 -34 -84t34 -83l85 -85q-119 -77 -260 -77q-199 0 -340 141zM1347 314q124 182 124 403q0 297 -210 507t-507 210q-296 0 -507 -210
q-210 -210 -210 -507q0 -296 210 -507q211 -210 507 -210q239 0 430 143l108 -108q35 -35 84 -35t83 35q35 34 35 83t-35 83z" />
<glyph glyph-name="R" unicode="R" horiz-adv-x="1226"
d="M345 838v363h296q87 0 149 -53t62 -129q0 -73 -59 -126q-60 -52 -144 -55h-304zM956 1314q-130 122 -315 122h-414q-48 0 -83 -35q-34 -34 -34 -83v-1192q0 -48 34 -83q35 -34 83 -34q49 0 83 34q35 35 35 83v477h203l265 -537q32 -66 105 -66q27 0 52 12q44 22 59 68
q16 46 -5 89l-227 460q129 45 208 151q82 107 82 239q0 173 -131 295z" />
<glyph glyph-name="S" unicode="S" horiz-adv-x="1174"
d="M921 692q-130 138 -375 142h-5q-146 2 -208 67q-39 42 -37 94q4 85 71 144q68 59 162 59q92 0 163 -33q81 -38 99 -105q12 -47 54 -72q42 -24 89 -12t71 54q25 42 13 89q-42 160 -197 244q-129 70 -292 70q-189 0 -324 -124t-143 -304q-7 -151 100 -265
q130 -137 375 -141h2q-2 0 2 0h1q146 -2 208 -68q39 -41 37 -93q-4 -86 -72 -144q-67 -59 -161 -59q-92 0 -164 33q-80 38 -98 105q-12 47 -54 72q-42 24 -89 12t-72 -54q-24 -42 -12 -89q42 -160 197 -244q129 -70 292 -70q188 0 324 124q135 124 143 303q7 152 -100 265z
" />
<glyph glyph-name="T" unicode="T" horiz-adv-x="1127"
d="M413 118q0 -49 35 -84q34 -34 83 -34t83 34q35 35 35 84v1082h298q48 0 83 35q34 34 34 83t-34 83q-35 35 -83 35h-831q-49 0 -84 -35q-34 -34 -34 -83t34 -83q35 -35 84 -35h297v-1082z" />
<glyph glyph-name="U" unicode="U" horiz-adv-x="1317"
d="M916 1400q-34 -34 -34 -82v-806q0 -116 -82 -198t-197 -82q-116 0 -198 82t-82 198v806q0 48 -34 82t-82 34t-82 -34t-34 -82v-806q0 -212 150 -362t362 -150q211 0 361 150t150 362v806q0 48 -34 82t-82 34t-82 -34z" />
<glyph glyph-name="V" unicode="V" horiz-adv-x="1215"
d="M933 1417q-44 -21 -60 -67l-308 -877l-308 877q-16 46 -60 67t-90 5t-67 -60t-5 -90l419 -1193v-1q3 -7 7 -15q1 -2 2 -3q4 -7 8 -13q0 -1 2 -3q4 -5 9 -10q3 -3 3 -2q5 -6 12 -10l1 -1l1 -1q6 -4 12 -7l3 -1q6 -3 12 -5q4 -2 2 -1q5 -2 13 -3q8 -2 5 -1q10 -2 19 -2
t19 2q-3 -1 5 1q8 1 13 3q-2 -1 2 1q6 2 12 5l2 1q7 3 13 7q4 3 2 2q7 5 12 10q-1 -1 2 2l10 10q4 5 2 3q4 6 8 13q1 1 2 3q4 8 7 15v1l419 1193q16 46 -5 90t-67 60t-90 -5z" />
<glyph glyph-name="W" unicode="W" horiz-adv-x="2053"
d="M1777 1422q-44 -22 -60 -68l-309 -880l-309 880v1q-1 2 -3 7l-2 4l-2 5q-8 15 -20 27q-13 13 -29 21l-4 3l-5 1l-6 3h-1v1h-2t-1 1q-5 1 -8 2l-4 1q-5 1 -7 1h-5q-4 1 -7 1h-11h-5q-5 -1 -7 -1t-5 -1q-4 -1 -6 -1q-2 -1 -6 -2q-5 -2 -4 -1q-2 -1 -1 -1q-1 0 -6 -2l-5 -2
q1 0 -3 -2q-17 -9 -30 -22q-12 -12 -20 -28q-2 -4 -3 -4q1 1 -2 -5q-1 -4 -2 -6v0v-1l-309 -880l-309 880q-17 46 -61 68q-44 21 -90 5q-46 -17 -67 -61t-5 -90l420 -1197l1 -1q2 -7 6 -15q1 -1 2 -3q4 -7 9 -13l1 -2q5 -6 10 -11q3 -3 2 -2l12 -10q1 0 1 -1q1 0 2 -1
q6 -4 12 -7q3 -1 2 -1q7 -3 13 -5q4 -2 1 -1q6 -2 14 -3q8 -2 5 -1q9 -2 19 -2q9 0 18 2q-2 -1 5 1q8 1 14 3q-3 -1 2 1t12 5q-1 0 2 1q6 3 12 7q5 3 3 2q7 5 12 10q-1 -1 2 2l10 10q4 6 2 3q4 6 8 13q1 1 2 3q4 8 7 15v1l309 880l309 -880v-1q3 -7 7 -15q1 -1 2 -3
q4 -7 8 -13l2 -2q4 -6 9 -11q3 -3 3 -2q5 -5 12 -10l1 -1q1 0 1 -1q6 -4 12 -7l3 -1q6 -3 12 -5q4 -2 2 -1q5 -2 13 -3q8 -2 5 -1q10 -2 19 -2t19 2q-3 -1 5 1q8 1 14 3q-3 -1 1 1q6 2 13 5q-1 0 2 1q6 3 12 7q4 3 3 2l12 10q-1 -1 2 2q5 5 9 10q4 6 2 3q5 6 9 13q0 1 2 3
q4 8 6 15v1l421 1197q16 46 -5 90t-67 61q-47 16 -91 -5z" />
<glyph glyph-name="X" unicode="X" horiz-adv-x="1261"
d="M981 1429q-48 -9 -76 -48l-327 -462l-327 462q-28 39 -76 48q-48 8 -88 -20q-40 -29 -48 -77t20 -88l375 -529l-375 -529q-28 -40 -20 -88t48 -76q30 -22 68 -22q61 0 96 50l327 462l327 -462q35 -50 96 -50q38 0 68 22q40 28 48 76t-20 88l-375 529l375 529q28 40 20 88
t-48 77q-40 28 -88 20z" />
<glyph glyph-name="Y" unicode="Y" horiz-adv-x="1250"
d="M1016 1430q-48 -6 -78 -44l-368 -460l-367 460q-31 38 -79 44q-49 5 -87 -26q-38 -30 -43 -78q-6 -49 25 -87l433 -542v-579q0 -49 35 -84q34 -34 83 -34t83 34q35 35 35 84v579l433 542q31 38 26 87q-6 48 -44 78q-38 31 -87 26z" />
<glyph glyph-name="Z" unicode="Z" horiz-adv-x="1314"
d="M1088 1435h-914q-49 0 -84 -35q-35 -34 -35 -83t35 -84q35 -34 84 -34h671l-789 -1008q-46 -58 -14 -125q33 -66 107 -66h914q49 0 83 35q35 34 35 83t-35 84q-34 34 -83 34h-672l790 1008q45 58 13 124q-33 67 -106 67z" />
<glyph glyph-name="bracketleft" unicode="[" horiz-adv-x="537"
d="M423 238l-187 -1v965h166q48 0 83 35q35 34 35 83t-35 84q-35 34 -83 34h-284q-49 0 -83 -34q-35 -35 -35 -84v-1202q0 -49 35 -84q34 -34 83 -34h1l306 2q49 1 83 35q35 35 34 84q0 49 -35 83q-34 34 -83 34h-1z" />
<glyph glyph-name="backslash" unicode="\" horiz-adv-x="355"
d="M235 1321q-4 49 -41 80q-37 32 -86 28q-48 -4 -80 -41t-28 -86l98 -1194q4 -46 38 -77t79 -31h10q48 4 80 42q32 37 28 85z" />
<glyph glyph-name="bracketright" unicode="]" horiz-adv-x="559"
d="M141 1438q-49 0 -84 -34q-34 -35 -34 -84t34 -83q35 -35 84 -35h165v-965l-187 1h-1q-49 0 -83 -34q-35 -34 -35 -83t34 -84q34 -34 83 -35l306 -2h1q49 0 83 34q35 35 35 84v1202q0 49 -34 84q-35 34 -84 34h-283z" />
<glyph glyph-name="asciicircum" unicode="^" horiz-adv-x="806"
d="M488 1361v0q-2 3 -6 8v1l-1 1l-5 5t-3 4q1 -1 -3 3q-4 3 -6 5q2 -2 -2 1l-8 6v0v0q1 0 -2 1q-4 3 -8 5q1 -1 -4 2l-6 3q-1 0 -6 2q-4 1 -5 1q-1 1 -6 2q-4 1 -5 1q-2 0 -6 1q-3 0 -5 1h-6h-6h-5h-6q-2 -1 -5 -1q-4 -1 -6 -1q-1 0 -5 -1q-5 -1 -6 -2q-1 0 -5 -1
q-4 -2 -6 -2l-6 -3q-5 -3 -4 -2q-3 -2 -8 -5q-3 -2 -2 -1v0q-4 -2 -8 -6h-1q0 -1 -1 -1q-2 -2 -6 -5q-4 -5 -3 -3q1 1 -3 -4l-5 -5q1 1 -1 -2q-4 -5 -6 -8v0l-272 -417q-26 -40 -16 -88t51 -74q29 -20 64 -20q64 0 98 54l173 265l173 -265q35 -54 99 -54q35 0 64 20
q41 26 51 74t-16 88z" />
<glyph glyph-name="underscore" unicode="_" horiz-adv-x="759"
d="M120 134q-49 0 -83 -34t-34 -82q0 -49 34 -83t83 -34h495q48 0 83 34q34 34 34 83q0 48 -34 82q-35 34 -83 34h-495z" />
<glyph glyph-name="grave" unicode="`" horiz-adv-x="1024"
d="M673 1079h-69l-330 202q-31 20 -46.5 40t-15.5 42q0 31 20.5 51t53.5 20q20 0 40.5 -12t55.5 -47z" />
<glyph glyph-name="a" unicode="a" horiz-adv-x="1408"
d="M508 540l192 464l193 -464h-385zM206 0q79 0 109 73l96 232h579l96 -232q30 -73 109 -73q23 0 45 9q45 19 64 64q18 45 0 90l-127 305v1l-368 888v0q-2 5 -5 10q0 1 -3 5t-3 5t-4 5l-3 4q0 1 -4 5q-3 3 -3 4q-2 1 -5 4t-4 3q-1 1 -5 4l-4 3q-1 1 -6 4t-4 2q-10 6 -22 9
q2 0 -4 1q-5 2 -7 2l-5 1l-6 1h-6h-6h-5h-6l-5 -1t-7 -1l-4 -1q-6 -2 -7 -2q-2 -1 -7 -2q-6 -3 -4 -2t-3 -2q-5 -2 -7 -3q-1 0 -6 -3l-4 -3q-1 -1 -5 -4q-5 -3 -4 -3q-1 0 -5 -4q-3 -2 -4 -3q0 -1 -4 -5q-3 -3 -3 -4l-4 -4q-3 -4 -3 -5q-1 -1 -4 -5l-2 -5q-3 -5 -5 -10v0
l-368 -888v-1l-127 -305q-18 -45 0 -90q19 -45 64 -64q22 -9 45 -9z" />
<glyph glyph-name="b" unicode="b" horiz-adv-x="1393"
d="M421 596h302h16h9q88 0 149 -52q61 -51 61 -125q0 -76 -62 -129q-62 -54 -150 -54h-325v360zM421 1195l302 2q88 0 149 -52q61 -51 61 -126q0 -76 -62 -132q-63 -55 -148 -55h-302v363zM746 0q185 0 316 123q132 123 132 296q0 187 -148 309q123 123 123 291
q0 174 -129 294q-130 120 -318 120l-420 -2q-48 -1 -83 -35q-34 -35 -34 -83v-1195q0 -49 35 -83q34 -35 83 -35h443z" />
<glyph glyph-name="c" unicode="c" horiz-adv-x="1477"
d="M1288 186q36 33 38 82t-31 85q-33 37 -82 39t-85 -31q-136 -124 -322 -124q-197 0 -337 140t-140 337q0 198 140 338t337 140q163 0 291 -99q39 -29 88 -23q48 6 78 45t24 88q-7 48 -45 78q-193 148 -436 148q-295 0 -505 -210q-209 -209 -209 -505q0 -295 209 -505
q210 -209 505 -209q277 0 482 186z" />
<glyph glyph-name="d" unicode="d" horiz-adv-x="1487"
d="M420 1197h184q198 0 338 -141q140 -140 140 -337q0 -198 -140 -338t-339 -140l-183 -3v959zM303 0l301 4q296 0 506 210q209 209 209 505q0 295 -209 505q-210 209 -506 209h-303q-49 0 -83 -34q-35 -35 -35 -84v-1197q0 -49 35 -84q35 -34 83 -34h2z" />
<glyph glyph-name="e" unicode="e" horiz-adv-x="1271"
d="M421 237v363h436q49 0 84 34q35 35 35 84t-35 84q-35 34 -84 34h-436v363l604 -2h1q49 0 83 35q35 34 35 83t-34 84q-35 35 -84 35l-723 2h-1q-49 0 -83 -35q-35 -34 -35 -84v-1199q0 -49 35 -83q34 -35 83 -35h724q49 0 83 35q35 34 35 83t-35 84q-34 35 -83 35h-605z
" />
<glyph glyph-name="f" unicode="f" horiz-adv-x="1218"
d="M304 1436h-1q-49 0 -83 -35q-35 -34 -35 -84v-1199q0 -49 35 -83q34 -35 83 -35t84 35q35 34 35 83v482h436q49 0 84 34q35 35 35 84t-35 84q-35 34 -84 34h-436v363l604 -2h1q49 0 83 35q35 34 35 83t-34 84q-35 35 -84 35z" />
<glyph glyph-name="g" unicode="g" horiz-adv-x="1572"
d="M1147 86q10 -37 41 -61q32 -25 72 -25h1q49 0 83 35q35 34 35 83l3 634q0 49 -35 84t-84 35h-510q-50 0 -84 -35q-35 -35 -35 -84t35 -84q34 -34 84 -34h391l-1 -262q-5 -4 -7 -6q-137 -125 -322 -125q-198 0 -339 140q-140 141 -140 339q0 197 140 338q141 140 339 140
q162 0 291 -99q39 -30 88 -23q48 6 78 45t24 87q-7 49 -46 79q-192 148 -435 148q-296 0 -506 -210q-210 -209 -210 -505t210 -506t506 -210q176 0 333 82z" />
<glyph glyph-name="h" unicode="h" horiz-adv-x="1524"
d="M1241 35q35 35 35 84v1195q0 49 -35 84t-84 35t-84 -35t-35 -84v-479h-616v479q0 49 -34 84q-35 35 -84 35t-84 -35t-35 -84v-1195q0 -49 35 -84t84 -35t84 35q34 35 34 84v479h616v-479q0 -49 35 -84t84 -35t84 35z" />
<glyph glyph-name="i" unicode="i" horiz-adv-x="668"
d="M386 35q35 34 35 83v1193q0 49 -35 83q-34 35 -83 35t-83 -35q-35 -34 -35 -83v-1193q0 -49 35 -83q34 -35 83 -35t83 35z" />
<glyph glyph-name="j" unicode="j" horiz-adv-x="834"
d="M374 435q0 -82 -58 -140t-140 -58q-49 0 -83 -35q-35 -35 -35 -84t35 -83q34 -35 83 -35q180 0 308 127q127 128 127 308v880q0 49 -35 84q-34 35 -83 35t-84 -35t-35 -84v-880z" />
<glyph glyph-name="k" unicode="k" horiz-adv-x="1339"
d="M384 44q34 34 34 82v322l99 105l491 -517q35 -36 85 -36q47 0 81 32q35 34 36 82t-32 84l-499 525l480 505q34 35 32 84q-1 48 -36 81q-35 34 -83 33q-49 -2 -82 -37l-572 -601v526q0 48 -34 82q-35 35 -83 35t-83 -35q-34 -34 -34 -82v-1188q0 -48 34 -82q35 -35 83 -35
t83 35z" />
<glyph glyph-name="l" unicode="l" horiz-adv-x="1146"
d="M222 1399q-35 -34 -35 -83v-1198q0 -49 35 -83q34 -35 83 -35h647q49 0 84 35q34 34 34 83t-34 83q-35 35 -84 35h-529v1080q0 49 -35 83q-34 35 -83 35t-83 -35z" />
<glyph glyph-name="m" unicode="m" horiz-adv-x="1857"
d="M1446 1430q-37 -15 -57 -49l-492 -813l-492 813q-21 34 -58 49q-37 14 -75 4q-39 -11 -63 -43q-24 -31 -24 -71v-1202q0 -49 35 -83q34 -35 83 -35t84 35q35 34 35 83v778l372 -616q1 0 1 -1v-1q1 0 1 -1l1 -1q3 -5 5 -7q0 -1 2 -4q4 -3 5 -5l4 -4l4 -4q2 -2 6 -5
q3 -3 3 -2q3 -3 7 -5l1 -1l1 -1h1v0q3 -2 8 -4q3 -2 2 -2q2 -1 7 -3q6 -2 4 -1q-1 0 4 -1q13 -4 26 -5q6 -1 4 -1h2q25 -1 48 9q5 2 6 2q-1 0 3 2q5 2 7 4h1l1 1q1 0 1 1q4 2 7 4l3 3q4 3 6 5l4 4l4 4l5 5l3 4q1 2 4 7l1 1l1 1l1 1v1l373 616v-778q0 -49 34 -83
q35 -35 84 -35t84 35q34 34 34 83v1202q0 40 -24 71q-24 32 -62 43q-39 10 -76 -4z" />
<glyph glyph-name="n" unicode="n" horiz-adv-x="1600"
d="M1148 37v-1l1 -1q4 -4 9 -8q1 -1 4 -3q4 -3 7 -5q1 -1 4 -3q3 -1 7 -3q2 -2 4 -2q3 -2 8 -3q3 -2 4 -2q3 -1 8 -2q5 -2 4 -1q4 -1 10 -2q4 -1 2 0q7 -1 13 -1v0q8 0 17 1l3 1q9 1 17 4q-2 -1 2 1q8 3 16 7v0h1q7 4 15 10v0l1 1q4 3 1 1q2 1 5 4q4 3 4 4q1 0 4 4l4 4l3 4
t4 6l3 3l3 6l3 5l2 5q1 2 2 6q2 4 2 5q1 1 2 6l1 5q1 2 1 6q1 4 1 6v5q1 4 1 6v1200q0 49 -35 83q-34 35 -83 35t-84 -35q-34 -34 -34 -83v-854l-719 926q-23 30 -59 41q-37 11 -72 -2q-36 -12 -58 -43q-22 -30 -22 -68v-1198q0 -49 35 -83q34 -35 83 -35t83 35q35 34 35 83
v853l719 -925v-1h1q3 -4 7 -8z" />
<glyph glyph-name="o" unicode="o" horiz-adv-x="1698"
d="M1152 1059q141 -142 141 -341t-141 -340q-142 -142 -341 -142t-340 142q-142 141 -142 340t142 341q141 141 340 141t341 -141zM1319 211q210 210 210 507t-210 508q-211 210 -508 210t-507 -210q-211 -211 -211 -508t211 -507q210 -211 507 -211t508 211z" />
<glyph glyph-name="p" unicode="p" horiz-adv-x="1298"
d="M421 835v366h299q88 0 150 -54t62 -129q0 -74 -60 -128q-60 -53 -145 -55h-306zM303 1437q-49 0 -83 -35q-35 -34 -35 -83v-1201q0 -49 35 -83q34 -35 83 -35t84 35q34 34 34 83v481h293l6 -1q1 0 12 1h2h1h1q180 6 306 127q127 122 127 292q0 173 -132 296
q-131 123 -317 123h-417z" />
<glyph glyph-name="q" unicode="q" horiz-adv-x="1721"
d="M469 377q-141 141 -141 340t141 340t340 141t340 -141t141 -340q0 -124 -60 -232l-79 80q-34 34 -83 34t-84 -34q-34 -35 -34 -84t34 -83l85 -85q-119 -77 -260 -77q-199 0 -340 141zM1402 314q124 182 124 403q0 297 -210 507t-507 210q-296 0 -507 -210
q-210 -210 -210 -507q0 -296 210 -507q211 -210 507 -210q239 0 430 143l108 -108q35 -35 84 -35t83 35q35 34 35 83t-35 83z" />
<glyph glyph-name="r" unicode="r" horiz-adv-x="1317"
d="M417 838v363h296q87 0 149 -53t62 -129q0 -73 -59 -126q-60 -52 -144 -55h-304zM1028 1314q-130 122 -315 122h-414q-48 0 -83 -35q-34 -34 -34 -83v-1192q0 -48 34 -83q35 -34 83 -34q49 0 83 34q35 35 35 83v477h203l265 -537q32 -66 105 -66q27 0 52 12q44 22 59 68
q16 46 -5 89l-227 460q129 45 208 151q82 107 82 239q0 173 -131 295z" />
<glyph glyph-name="s" unicode="s" horiz-adv-x="1270"
d="M979 692q-130 138 -375 142h-5q-146 2 -208 67q-39 42 -37 94q4 85 71 144q68 59 162 59q92 0 163 -33q81 -38 99 -105q12 -47 54 -72q42 -24 89 -12t71 54q25 42 13 89q-42 160 -197 244q-129 70 -292 70q-189 0 -324 -124t-143 -304q-7 -151 100 -265
q130 -137 375 -141h2q-2 0 2 0h1q146 -2 208 -68q39 -41 37 -93q-4 -86 -72 -144q-67 -59 -161 -59q-92 0 -164 33q-80 38 -98 105q-12 47 -54 72q-42 24 -89 12t-72 -54q-24 -42 -12 -89q42 -160 197 -244q129 -70 292 -70q188 0 324 124q135 124 143 303q7 152 -100 265z
" />
<glyph glyph-name="t" unicode="t" horiz-adv-x="1189"
d="M461 118q0 -49 35 -84q34 -34 83 -34t83 34q35 35 35 84v1082h298q48 0 83 35q34 34 34 83t-34 83q-35 35 -83 35h-831q-49 0 -84 -35q-34 -34 -34 -83t34 -83q35 -35 84 -35h297v-1082z" />
<glyph glyph-name="u" unicode="u" horiz-adv-x="1400"
d="M985 1400q-34 -34 -34 -82v-806q0 -116 -82 -198t-197 -82q-116 0 -198 82t-82 198v806q0 48 -34 82t-82 34t-82 -34t-34 -82v-806q0 -212 150 -362t362 -150q211 0 361 150t150 362v806q0 48 -34 82t-82 34t-82 -34z" />
<glyph glyph-name="v" unicode="v" horiz-adv-x="1281"
d="M993 1417q-44 -21 -60 -67l-308 -877l-308 877q-16 46 -60 67t-90 5t-67 -60t-5 -90l419 -1193v-1q3 -7 7 -15q1 -2 2 -3q4 -7 8 -13q0 -1 2 -3q4 -5 9 -10q3 -3 3 -2q5 -6 12 -10l1 -1l1 -1q6 -4 12 -7l3 -1q6 -3 12 -5q4 -2 2 -1q5 -2 13 -3q8 -2 5 -1q10 -2 19 -2
t19 2q-3 -1 5 1q8 1 13 3q-2 -1 2 1q6 2 12 5l2 1q7 3 13 7q4 3 2 2q7 5 12 10q-1 -1 2 2l10 10q4 5 2 3q4 6 8 13q1 1 2 3q4 8 7 15v1l419 1193q16 46 -5 90t-67 60t-90 -5z" />
<glyph glyph-name="w" unicode="w" horiz-adv-x="2106"
d="M1837 1422q-44 -22 -60 -68l-309 -880l-309 880v1q-1 2 -3 7l-2 4l-2 5q-8 15 -20 27q-13 13 -29 21l-4 3l-5 1l-6 3h-1v1h-2t-1 1q-5 1 -8 2l-4 1q-5 1 -7 1h-5q-4 1 -7 1h-11h-5q-5 -1 -7 -1t-5 -1q-4 -1 -6 -1q-2 -1 -6 -2q-5 -2 -4 -1q-2 -1 -1 -1q-1 0 -6 -2l-5 -2
q1 0 -3 -2q-17 -9 -30 -22q-12 -12 -20 -28q-2 -4 -3 -4q1 1 -2 -5q-1 -4 -2 -6v0v-1l-309 -880l-309 880q-17 46 -61 68q-44 21 -90 5q-46 -17 -67 -61t-5 -90l420 -1197l1 -1q2 -7 6 -15q1 -1 2 -3q4 -7 9 -13l1 -2q5 -6 10 -11q3 -3 2 -2l12 -10q1 0 1 -1q1 0 2 -1
q6 -4 12 -7q3 -1 2 -1q7 -3 13 -5q4 -2 1 -1q6 -2 14 -3q8 -2 5 -1q9 -2 19 -2q9 0 18 2q-2 -1 5 1q8 1 14 3q-3 -1 2 1t12 5q-1 0 2 1q6 3 12 7q5 3 3 2q7 5 12 10q-1 -1 2 2l10 10q4 6 2 3q4 6 8 13q1 1 2 3q4 8 7 15v1l309 880l309 -880v-1q3 -7 7 -15q1 -1 2 -3
q4 -7 8 -13l2 -2q4 -6 9 -11q3 -3 3 -2q5 -5 12 -10l1 -1q1 0 1 -1q6 -4 12 -7l3 -1q6 -3 12 -5q4 -2 2 -1q5 -2 13 -3q8 -2 5 -1q10 -2 19 -2t19 2q-3 -1 5 1q8 1 14 3q-3 -1 1 1q6 2 13 5q-1 0 2 1q6 3 12 7q4 3 3 2l12 10q-1 -1 2 2q5 5 9 10q4 6 2 3q5 6 9 13q0 1 2 3
q4 8 6 15v1l421 1197q16 46 -5 90t-67 61q-47 16 -91 -5z" />
<glyph glyph-name="x" unicode="x" horiz-adv-x="1349"
d="M1068 1429q-48 -9 -76 -48l-327 -462l-327 462q-28 39 -76 48q-48 8 -88 -20q-40 -29 -48 -77t20 -88l375 -529l-375 -529q-28 -40 -20 -88t48 -76q30 -22 68 -22q61 0 96 50l327 462l327 -462q35 -50 96 -50q38 0 68 22q40 28 48 76t-20 88l-375 529l375 529
q28 40 20 88t-48 77q-40 28 -88 20z" />
<glyph glyph-name="y" unicode="y" horiz-adv-x="1307"
d="M1080 1430q-48 -6 -78 -44l-368 -460l-367 460q-31 38 -79 44q-49 5 -87 -26q-38 -30 -43 -78q-6 -49 25 -87l433 -542v-579q0 -49 35 -84q34 -34 83 -34t83 34q35 35 35 84v579l433 542q31 38 26 87q-6 48 -44 78q-38 31 -87 26z" />
<glyph glyph-name="z" unicode="z" horiz-adv-x="1394"
d="M1151 1435h-914q-49 0 -84 -35q-35 -34 -35 -83t35 -84q35 -34 84 -34h671l-789 -1008q-46 -58 -14 -125q33 -66 107 -66h914q49 0 83 35q35 34 35 83t-35 84q-34 34 -83 34h-672l790 1008q45 58 13 124q-33 67 -106 67z" />
<glyph glyph-name="braceleft" unicode="{" horiz-adv-x="550"
d="M335 702q39 34 42 87q16 269 135 466q25 42 13 89q-12 48 -53 73q-42 25 -89 13q-48 -12 -73 -53q-131 -220 -162 -505q-64 -20 -96 -44q-52 -39 -52 -102v-20q1 -58 47 -99q26 -25 91 -57q13 -7 12 -7q33 -275 160 -486q35 -57 101 -57q33 0 61 17q41 25 53 72t-13 89
q-111 185 -132 436q-5 50 -45 88z" />
<glyph glyph-name="bar" unicode="|" horiz-adv-x="247"
d="M202 35q34 34 34 83v1193q0 49 -34 84q-35 35 -84 35t-83 -35q-35 -35 -35 -84v-1193q0 -49 35 -83q34 -35 83 -35t84 35z" />
<glyph glyph-name="braceright" unicode="}" horiz-adv-x="550"
d="M482 827q-26 24 -91 57l-6 3l-6 3q-33 275 -160 487q-25 41 -73 53q-47 12 -89 -13q-41 -25 -53 -73q-12 -47 13 -89q111 -185 132 -435q5 -51 45 -88q-39 -35 -42 -88q-16 -268 -135 -466q-25 -42 -13 -89t53 -72q28 -17 61 -17q66 0 101 57q131 219 162 505
q64 20 96 43q52 39 52 103v19q-1 58 -47 100z" />
<glyph glyph-name="asciitilde" unicode="~"
d="M923 878v-156q-63 -72 -122 -97.5t-116 -25.5q-60 0 -177.5 48.5t-176.5 48.5q-51 0 -107.5 -28t-129.5 -112v156q64 73 123 99t114 26q64 0 181.5 -49.5t172.5 -49.5q52 0 108.5 28t129.5 112z" />
<glyph glyph-name="exclamdown" unicode="&#xa1;" horiz-adv-x="672"
/>
<glyph glyph-name="cent" unicode="&#xa2;" horiz-adv-x="1139"
/>
<glyph glyph-name="sterling" unicode="&#xa3;" horiz-adv-x="823"
d="M518 1166q46 -30 67 -81q19 -45 64 -63q46 -18 91 1q44 19 63 64q18 45 -1 90q-49 116 -154 186q-104 69 -230 69q-173 0 -296 -122q-122 -123 -122 -296v-896q0 -49 35 -83q34 -35 83 -35h573q49 0 83 35q35 34 35 83t-35 83q-34 35 -83 35h-455v272h206q49 0 83 34
q35 35 35 83q0 49 -35 84q-34 34 -83 34h-206v271q0 76 53 129t129 53q54 0 100 -30z" />
<glyph glyph-name="currency" unicode="&#xa4;"
d="M350 560q41 -40 99 -57q29 -8 58 -8t58 8q58 17 99 57q40 41 57 99q9 29 9 58t-9 58q-17 58 -57 99q-41 40 -100 57q-29 8 -58 8t-58 -9q-58 -17 -98 -56q-39 -40 -56 -98q-10 -30 -10 -60q0 -28 9 -56q16 -59 57 -100zM240 903l-118 118l80 81l118 -118q44 30 99 46
q44 14 89 14q41 0 83 -12q57 -17 102 -48l118 118l80 -81l-117 -117q31 -46 48 -102q12 -42 12 -85q0 -42 -12 -85q-17 -56 -48 -102l117 -117l-80 -81l-118 118q-45 -32 -101 -48q-42 -12 -85 -12q-42 0 -85 12q-57 16 -102 48l-118 -118l-80 81l118 117q-32 46 -48 103
q-12 42 -12 84q0 44 13 87q16 55 47 99z" />
<glyph glyph-name="yen" unicode="&#xa5;" horiz-adv-x="1262"
d="M547 225l-2 242q0 19 -1.5 35t-4.5 32l-484 1q-14 0 -21 6.5t-7 19.5t6.5 19t21.5 6h467l-121 172h-344q-17 0 -23.5 5.5t-6.5 18.5q0 14 6 19.5t22 5.5h307q-43 57 -108 155q-131 197 -227 197q-7 0 -13 5.5t-6 11.5q0 19 10.5 27.5t32.5 8.5q27 0 123 -8t164 -8h88
q33 0 41 -6.5t8 -26.5q0 -8 -15 -14t-38 -6q-6 0 -18.5 2t-18.5 2q-24 0 -37.5 -9.5t-13.5 -25.5q0 -18 16.5 -52t46.5 -77l158 -221q13 -19 33 -53q41 -70 71 -70q9 0 16.5 5t14.5 15l277 396q8 12 13 26.5t5 24.5q0 18 -10 27t-37 14q-15 2 -41 4q-47 3 -47 25
q0 15 8 22.5t25 7.5q3 0 15 -1q56 -7 108 -7h139q30 0 65 1t37 1q11 0 18.5 -4.5t8.5 -11.5q0 -28 -38 -34q-18 -3 -27 -5q-63 -15 -147 -117q-7 -9 -12 -15l-169 -206h323q15 0 24 -6t9 -17q0 -15 -6 -20.5t-23 -5.5h-366q-46 -57 -96.5 -112.5t-52.5 -59.5h511
q18 0 25.5 -5.5t7.5 -17.5q0 -14 -7 -21t-22 -7h-530q0 -11 -1 -30.5t-1 -29.5l2 -215q0 -114 5.5 -150t20.5 -44q30 -17 107.5 -19t77.5 -31q0 -12 -10 -20t-25 -8q-2 0 -35.5 4t-64.5 4q-91 0 -208.5 -4t-142.5 -4q-31 0 -40 4t-9 16t8 18.5t37 12.5q9 2 25 5q74 16 92 32
q17 13 24 47t7 102z" />
<glyph glyph-name="brokenbar" unicode="&#xa6;"
d="M427 371h160v-789h-160v789zM427 1578h160v-789h-160v789z" />
<glyph glyph-name="section" unicode="&#xa7;"
d="M545 321q56 16 97 53q73 65 73 166q0 5 -1 10h-2q-1 14 -4 27q-22 61 -113 127q-59 29 -126 29q-78 0 -125 -44.5t-47 -117.5q0 -123 248 -250zM466 -346q113 6 185 69q72 64 72 165q0 125 -316 276q-123 64 -175.5 137t-52.5 177q0 148 89 237q67 65 170 82l-40 19
q-123 64 -175.5 137t-52.5 177q0 148 89 237q82 79 216 86q8 1 17 1h3q66 0 163 -16.5t97 -41.5v-194h-51q-5 81 -80 132q-70 47 -149 51h-15q-78 0 -125 -44.5t-47 -117.5q0 -132 287 -269q149 -67 204.5 -143.5t55.5 -187.5q0 -171 -101 -282q-47 -39 -99 -64
q108 -56 154 -118q55 -77 55 -187q0 -171 -101 -283q-124 -102 -277 -105v1q-6 -1 -13 -1h-3q-66 0 -163 16.5t-97 41.5v194h51q5 -81 80 -132q68 -45 145 -50z" />
<glyph glyph-name="dieresis" unicode="&#xa8;" horiz-adv-x="1024"
d="M223 1289l71 72q13 12 25 12q11 0 27 -14l69 -73q10 -14 10 -25q0 -13 -12 -27l-69 -75q-17 -17 -25 -17q-14 0 -25 12l-76 86q-9 12 -9 23q0 13 14 26zM588 1289l71 72q13 12 25 12q11 0 27 -13l69 -74q10 -14 10 -25q0 -13 -12 -26l-69 -76q-17 -17 -25 -17
q-14 0 -25 12l-76 87q-9 11 -9 22q0 13 14 26z" />
<glyph glyph-name="copyright" unicode="&#xa9;" horiz-adv-x="2047"
d="M713 973q-105 -105 -105 -254t105 -255q106 -105 255 -105q127 0 226 80q38 30 43 79q6 49 -25 87q-31 39 -80 44t-87 -26q-34 -27 -77 -27q-51 0 -87 36t-36 87t36 87t87 36q58 0 95 -45q31 -38 80 -43t87 26q38 32 43 81q4 48 -27 86q-108 132 -278 132
q-149 0 -255 -106zM627 378q-141 142 -141 341t141 340q142 142 341 142t340 -142q142 -141 142 -340t-142 -341q-141 -141 -340 -141t-341 141zM460 1227q-211 -211 -211 -508t211 -508t508 -211t508 211t211 508t-211 508t-508 211t-508 -211z" />
<glyph glyph-name="ordfeminine" unicode="&#xaa;" horiz-adv-x="648"
/>
<glyph glyph-name="guillemotleft" unicode="&#xab;" horiz-adv-x="944"
d="M174 479l342 303h14v-37l-205 -266l205 -266v-37h-14zM487 479l342 303h14v-37l-205 -266l205 -266v-37h-14z" />
<glyph glyph-name="logicalnot" unicode="&#xac;"
d="M87 767h840v-491l-1 -1h-98v392h-741v100z" />
<glyph glyph-name="registered" unicode="&#xae;" horiz-adv-x="1674"
d="M751 1099v-374l3 -8q23 -56 56 -81q29 -22 56 -22h6q31 4 61.5 38.5t46.5 97.5q13 50 13 103q0 13 -1 27q-4 67 -28 124.5t-56.5 76t-63.5 18.5h-93zM984 576l82 -116q100 -141 150 -141h34v-50h-346v50h45q30 0 30 22q0 29 -69 114l-75 102q-42 0 -84 42v-159
q0 -121 36 -121h53v-50h-316v50h43q37 0 37 121v538q0 121 -37 121h-43v70h356q64 -1 125 -42q60 -41 92.5 -114t32.5 -152q0 -78 -32 -150.5t-114 -134.5zM840 1456q145 0 280 -56.5t239 -160.5q102 -101 158.5 -238t56.5 -283q0 -147 -56.5 -282t-162.5 -240
q-105 -105 -239 -159.5t-283 -54.5q-146 0 -278 55.5t-238 160.5q-106 104 -161.5 237.5t-55.5 282.5q0 148 55.5 283t159.5 238q102 104 238.5 160.5t286.5 56.5zM357 1197q-95 -96 -146 -219.5t-51 -259.5q0 -137 51 -259t148 -219q98 -96 219 -147t256 -51
q137 0 259.5 50.5t219.5 145.5q97 98 149 221.5t52 258.5q0 134 -52 259.5t-145 219.5q-96 96 -220 147.5t-258 51.5q-137 0 -262 -51.5t-220 -147.5z" />
<glyph glyph-name="macron" unicode="&#xaf;" horiz-adv-x="670"
/>
<glyph glyph-name="degree" unicode="&#xb0;" horiz-adv-x="674"
d="M339 1372q-86 0 -147.5 -61t-61.5 -148t61 -147t148 -60t147 60t60 147t-60.5 148t-146.5 61zM339 1442q115 0 196 -81.5t81 -196.5q0 -114 -82 -196t-197 -82q-117 0 -197 81t-80 197t81.5 197t197.5 81z" />
<glyph glyph-name="plusminus" unicode="&#xb1;"
/>
<glyph glyph-name="uni00B2" unicode="&#xb2;"
/>
<glyph glyph-name="uni00B3" unicode="&#xb3;"
/>
<glyph glyph-name="acute" unicode="&#xb4;" horiz-adv-x="1024"
d="M607 1375q35 35 55.5 47t40.5 12q33 0 53.5 -20t20.5 -51q0 -22 -15.5 -42t-46.5 -40l-330 -203h-69z" />
<glyph glyph-name="mu" unicode="&#xb5;" horiz-adv-x="1180"
/>
<glyph glyph-name="paragraph" unicode="&#xb6;" horiz-adv-x="1024"
d="M929 1435v-70h-127v-1365h-82v1365h-166v-1365h-84v738q-174 8 -275.5 102.5t-101.5 245.5q0 157 107.5 253t285.5 96h443z" />
<glyph glyph-name="periodcentered" unicode="&#xb7;" horiz-adv-x="508"
d="M145 740l82 84q15 14 29 14q13 0 31 -16l80 -86q12 -16 12 -29q0 -15 -14 -31l-80 -88q-20 -20 -29 -20q-16 0 -29 14l-88 101q-10 13 -10 26q0 15 16 31z" />
<glyph glyph-name="periodcentered" unicode="&#x2219;" horiz-adv-x="508"
d="M145 740l82 84q15 14 29 14q13 0 31 -16l80 -86q12 -16 12 -29q0 -15 -14 -31l-80 -88q-20 -20 -29 -20q-16 0 -29 14l-88 101q-10 13 -10 26q0 15 16 31z" />
<glyph glyph-name="cedilla" unicode="&#xb8;" horiz-adv-x="1024"
d="M360 -290q85 -52 152 -52q66 0 94.5 21.5t28.5 66.5t-49 64q-40 16 -102 16q-16 0 -34 -2l48 176h63l-37 -104q32 4 62 5q86 0 134 -40.5t48 -113.5q0 -76 -58.5 -120.5t-160.5 -44.5q-109 0 -189 32v96z" />
<glyph glyph-name="uni00B9" unicode="&#xb9;"
/>
<glyph glyph-name="ordmasculine" unicode="&#xba;" horiz-adv-x="718"
/>
<glyph glyph-name="guillemotright" unicode="&#xbb;" horiz-adv-x="944"
d="M115 176h-14v37l205 266l-205 266v37h14l342 -303zM428 176h-14v37l205 266l-205 266v37h14l342 -303z" />
<glyph glyph-name="onequarter" unicode="&#xbc;" horiz-adv-x="1708"
/>
<glyph glyph-name="onehalf" unicode="&#xbd;" horiz-adv-x="1964"
/>
<glyph glyph-name="threequarters" unicode="&#xbe;" horiz-adv-x="1708"
/>
<glyph glyph-name="questiondown" unicode="&#xbf;" horiz-adv-x="748"
/>
<glyph glyph-name="Agrave" unicode="&#xc0;" horiz-adv-x="1540"
/>
<glyph glyph-name="Aacute" unicode="&#xc1;" horiz-adv-x="1540"
/>
<glyph glyph-name="Acircumflex" unicode="&#xc2;" horiz-adv-x="1540"
/>
<glyph glyph-name="Atilde" unicode="&#xc3;" horiz-adv-x="1540"
/>
<glyph glyph-name="Adieresis" unicode="&#xc4;" horiz-adv-x="1540"
/>
<glyph glyph-name="Aring" unicode="&#xc5;" horiz-adv-x="1540"
/>
<glyph glyph-name="AE" unicode="&#xc6;" horiz-adv-x="2118"
/>
<glyph glyph-name="Ccedilla" unicode="&#xc7;" horiz-adv-x="1399"
/>
<glyph glyph-name="Egrave" unicode="&#xc8;" horiz-adv-x="1151"
/>
<glyph glyph-name="Eacute" unicode="&#xc9;" horiz-adv-x="1151"
/>
<glyph glyph-name="Ecircumflex" unicode="&#xca;" horiz-adv-x="1151"
/>
<glyph glyph-name="Edieresis" unicode="&#xcb;" horiz-adv-x="1151"
/>
<glyph glyph-name="Igrave" unicode="&#xcc;" horiz-adv-x="657"
/>
<glyph glyph-name="Iacute" unicode="&#xcd;" horiz-adv-x="657"
/>
<glyph glyph-name="Icircumflex" unicode="&#xce;" horiz-adv-x="657"
/>
<glyph glyph-name="Idieresis" unicode="&#xcf;" horiz-adv-x="657"
/>
<glyph glyph-name="Eth" unicode="&#xd0;" horiz-adv-x="1518"
/>
<glyph glyph-name="Ntilde" unicode="&#xd1;" horiz-adv-x="1554"
/>
<glyph glyph-name="Ograve" unicode="&#xd2;" horiz-adv-x="1614"
/>
<glyph glyph-name="Oacute" unicode="&#xd3;" horiz-adv-x="1614"
/>
<glyph glyph-name="Ocircumflex" unicode="&#xd4;" horiz-adv-x="1614"
/>
<glyph glyph-name="Otilde" unicode="&#xd5;" horiz-adv-x="1614"
/>
<glyph glyph-name="Odieresis" unicode="&#xd6;" horiz-adv-x="1614"
/>
<glyph glyph-name="multiply" unicode="&#xd7;"
d="M507 618l-247 -247l-99 99l247 247l-247 248l99 98l247 -247l248 247l98 -99l-247 -247l247 -247l-99 -99z" />
<glyph glyph-name="Oslash" unicode="&#xd8;" horiz-adv-x="1614"
/>
<glyph glyph-name="Ugrave" unicode="&#xd9;" horiz-adv-x="1501"
/>
<glyph glyph-name="Uacute" unicode="&#xda;" horiz-adv-x="1501"
/>
<glyph glyph-name="Ucircumflex" unicode="&#xdb;" horiz-adv-x="1501"
/>
<glyph glyph-name="Udieresis" unicode="&#xdc;" horiz-adv-x="1501"
/>
<glyph glyph-name="Yacute" unicode="&#xdd;" horiz-adv-x="1233"
/>
<glyph glyph-name="Thorn" unicode="&#xde;" horiz-adv-x="1120"
/>
<glyph glyph-name="germandbls" unicode="&#xdf;" horiz-adv-x="1251"
/>
<glyph glyph-name="agrave" unicode="&#xe0;" horiz-adv-x="922"
/>
<glyph glyph-name="aacute" unicode="&#xe1;" horiz-adv-x="922"
/>
<glyph glyph-name="acircumflex" unicode="&#xe2;" horiz-adv-x="922"
/>
<glyph glyph-name="atilde" unicode="&#xe3;" horiz-adv-x="922"
/>
<glyph glyph-name="adieresis" unicode="&#xe4;" horiz-adv-x="922"
/>
<glyph glyph-name="aring" unicode="&#xe5;" horiz-adv-x="922"
/>
<glyph glyph-name="ae" unicode="&#xe6;" horiz-adv-x="1454"
/>
<glyph glyph-name="ccedilla" unicode="&#xe7;" horiz-adv-x="905"
/>
<glyph glyph-name="egrave" unicode="&#xe8;" horiz-adv-x="909"
/>
<glyph glyph-name="eacute" unicode="&#xe9;" horiz-adv-x="909"
/>
<glyph glyph-name="ecircumflex" unicode="&#xea;" horiz-adv-x="909"
/>
<glyph glyph-name="edieresis" unicode="&#xeb;" horiz-adv-x="909"
/>
<glyph glyph-name="igrave" unicode="&#xec;" horiz-adv-x="514"
/>
<glyph glyph-name="iacute" unicode="&#xed;" horiz-adv-x="514"
/>
<glyph glyph-name="icircumflex" unicode="&#xee;" horiz-adv-x="514"
/>
<glyph glyph-name="idieresis" unicode="&#xef;" horiz-adv-x="514"
/>
<glyph glyph-name="eth" unicode="&#xf0;" horiz-adv-x="1139"
/>
<glyph glyph-name="ntilde" unicode="&#xf1;" horiz-adv-x="1108"
/>
<glyph glyph-name="ograve" unicode="&#xf2;" horiz-adv-x="1010"
/>
<glyph glyph-name="oacute" unicode="&#xf3;" horiz-adv-x="1010"
/>
<glyph glyph-name="ocircumflex" unicode="&#xf4;" horiz-adv-x="1010"
/>
<glyph glyph-name="otilde" unicode="&#xf5;" horiz-adv-x="1010"
/>
<glyph glyph-name="odieresis" unicode="&#xf6;" horiz-adv-x="1010"
/>
<glyph glyph-name="divide" unicode="&#xf7;"
d="M87 647v140h839l1 -1v-139h-840zM398 408l82 84q15 14 29 14q13 0 31 -16l80 -86q12 -16 12 -29q0 -15 -14 -31l-80 -88q-20 -20 -29 -20q-16 0 -29 14l-88 101q-10 13 -10 26q0 15 16 31zM398 1101l82 84q15 14 29 14q13 0 31 -16l80 -86q12 -16 12 -29q0 -15 -14 -31
l-80 -88q-20 -20 -29 -20q-16 0 -29 14l-88 101q-10 13 -10 26q0 15 16 31z" />
<glyph glyph-name="oslash" unicode="&#xf8;" horiz-adv-x="1010"
/>
<glyph glyph-name="ugrave" unicode="&#xf9;" horiz-adv-x="1059"
/>
<glyph glyph-name="uacute" unicode="&#xfa;" horiz-adv-x="1059"
/>
<glyph glyph-name="ucircumflex" unicode="&#xfb;" horiz-adv-x="1059"
/>
<glyph glyph-name="udieresis" unicode="&#xfc;" horiz-adv-x="1059"
/>
<glyph glyph-name="yacute" unicode="&#xfd;" horiz-adv-x="868"
/>
<glyph glyph-name="thorn" unicode="&#xfe;" horiz-adv-x="1010"
/>
<glyph glyph-name="ydieresis" unicode="&#xff;" horiz-adv-x="868"
/>
<glyph glyph-name="dotlessi" unicode="&#x131;" horiz-adv-x="514"
d="M328 223q0 -173 100 -173h46v-50h-442v50h46q100 0 100 173v432q0 77 -111 77h-48v44q222 69 261 182h48v-735z" />
<glyph glyph-name="circumflex" unicode="&#x2c6;" horiz-adv-x="1024"
d="M221 1079l232 355h118l232 -355h-58l-233 216l-233 -216h-58z" />
<glyph glyph-name="caron" unicode="&#x2c7;" horiz-adv-x="1024"
d="M221 1434h58l233 -214l233 214h58l-232 -356h-118z" />
<glyph glyph-name="uni02C9" unicode="&#x2c9;" horiz-adv-x="1024"
d="M254 1195v125h516v-125h-516z" />
<glyph glyph-name="breve" unicode="&#x2d8;" horiz-adv-x="1024"
d="M219 1349h51q17 -73 75 -107t167 -34t166 33.5t74 107.5h51q-20 -133 -94 -201.5t-197 -68.5q-122 0 -197 69t-96 201z" />
<glyph glyph-name="dotaccent" unicode="&#x2d9;" horiz-adv-x="1024"
d="M422 1289l69 72q6 6 13 9t14 3q6 0 12.5 -3t12.5 -9l71 -76q5 -4 7 -10t2 -14q-1 -9 -3 -15t-8 -12l-71 -76q-12 -11 -16 -13.5t-7 -2.5q-10 0 -16.5 2.5t-10.5 8.5l-75 87q-4 4 -6 9.5t-2 13.5q0 6 3 12.5t11 13.5z" />
<glyph glyph-name="ring" unicode="&#x2da;" horiz-adv-x="1024"
d="M411 1257q0 -42 29 -71t71 -29t71 29t29 71q0 40 -29.5 69.5t-70.5 29.5t-70.5 -29.5t-29.5 -69.5zM335 1257q0 75 51 126t125 51q76 0 127.5 -51.5t51.5 -125.5q0 -75 -51.5 -126.5t-127.5 -51.5q-74 0 -125 51.5t-51 126.5z" />
<glyph glyph-name="ogonek" unicode="&#x2db;" horiz-adv-x="1024"
d="M640 0q-71 -62 -110.5 -119.5t-39.5 -112.5q0 -47 27 -75t73 -28q40 0 69.5 15.5t49.5 48.5l28 -16q-36 -63 -90.5 -97t-119.5 -34q-70 0 -114 35.5t-44 90.5q0 76 60.5 156.5t161.5 135.5h49z" />
<glyph glyph-name="tilde" unicode="&#x2dc;" horiz-adv-x="1024"
d="M808 1382q-20 -103 -68.5 -154t-126.5 -51h-4q-50 0 -113 23q-66 24 -114 24q-39 0 -60.5 -20.5t-33.5 -71.5h-54q19 106 68 158.5t129 52.5q46 -1 113 -24q64 -23 112 -23h4q36 0 58 20t36 66h54z" />
<glyph glyph-name="hungarumlaut" unicode="&#x2dd;" horiz-adv-x="1072"
d="M279 1398q-34 -35 -34 -83v-187q0 -49 34 -84q35 -34 84 -34q48 0 83 34q34 35 34 84v187q0 48 -34 83q-35 34 -83 34q-49 0 -84 -34zM563 1398q-34 -35 -34 -83v-187q0 -49 34 -84q34 -34 83 -34t83 34q35 35 35 84v187q0 48 -35 83q-34 34 -83 34t-83 -34z" />
<glyph glyph-name="endash" unicode="&#x2013;" horiz-adv-x="1108"
d="M56 419v120h996v-120h-996z" />
<glyph glyph-name="emdash" unicode="&#x2014;" horiz-adv-x="2048"
d="M0 419v120h2048v-120h-2048z" />
<glyph glyph-name="quoteleft" unicode="&#x2018;" horiz-adv-x="801"
d="M286 1399q-34 -34 -34 -83v-187q0 -49 34 -84q35 -34 84 -34t83 34q35 35 35 84v187q0 49 -35 83q-34 35 -83 35t-84 -35z" />
<glyph glyph-name="quoteright" unicode="&#x2019;" horiz-adv-x="801"
d="M286 1399q-34 -34 -34 -83v-187q0 -49 34 -84q35 -34 84 -34t83 34q35 35 35 84v187q0 49 -35 83q-34 35 -83 35t-84 -35z" />
<glyph glyph-name="quotesinglbase" unicode="&#x201a;" horiz-adv-x="813"
d="M294 395q-34 -35 -34 -83v-187q0 -48 34 -83q35 -34 83 -34q49 0 83 34q35 35 35 83v187q0 48 -35 83q-34 34 -83 34q-48 0 -83 -34z" />
<glyph glyph-name="quotedblleft" unicode="&#x201c;" horiz-adv-x="1072"
d="M279 1398q-34 -35 -34 -83v-187q0 -49 34 -84q35 -34 84 -34q48 0 83 34q34 35 34 84v187q0 48 -34 83q-35 34 -83 34q-49 0 -84 -34zM563 1398q-34 -35 -34 -83v-187q0 -49 34 -84q34 -34 83 -34t83 34q35 35 35 84v187q0 48 -35 83q-34 34 -83 34t-83 -34z" />
<glyph glyph-name="quotedblright" unicode="&#x201d;" horiz-adv-x="1072"
d="M279 1398q-34 -35 -34 -83v-187q0 -49 34 -84q35 -34 84 -34q48 0 83 34q34 35 34 84v187q0 48 -34 83q-35 34 -83 34q-49 0 -84 -34zM563 1398q-34 -35 -34 -83v-187q0 -49 34 -84q34 -34 83 -34t83 34q35 35 35 84v187q0 48 -35 83q-34 34 -83 34t-83 -34z" />
<glyph glyph-name="quotedblbase" unicode="&#x201e;" horiz-adv-x="910"
d="M238 281q44 0 88.5 -65.5t44.5 -151.5q0 -109 -71 -226.5t-139 -117.5v43q73 43 87 190q0 119 -129 161v42zM591 281q44 0 88.5 -65.5t44.5 -151.5q0 -109 -71 -226.5t-139 -117.5v43q73 43 87 190q0 119 -129 161v42z" />
<glyph glyph-name="dagger" unicode="&#x2020;"
d="M486 1022q-8 97 -54 178q-57 101 -57 129q0 49 36 78.5t96 29.5q57 0 94.5 -27.5t37.5 -71.5q0 -32 -55 -137q-46 -85 -55 -179q96 8 177 54q101 57 129 57q49 0 79 -36t30 -96q0 -57 -27.5 -94.5t-72.5 -37.5q-32 0 -136 55q-85 46 -179 57q8 -176 110 -277
q-106 -460 -112 -974h-38q-6 514 -114 974q102 101 111 277q-96 -10 -178 -55q-101 -57 -129 -57q-49 0 -78.5 36t-29.5 96q0 57 27.5 94.5t71.5 37.5q32 0 137 -56q85 -46 179 -55z" />
<glyph glyph-name="daggerdbl" unicode="&#x2021;"
d="M528 186q94 11 179 57q104 55 136 55q45 0 72.5 -37.5t27.5 -94.5q0 -60 -30 -96t-79 -36q-28 0 -129 57q-81 46 -177 54q9 -94 55 -179q55 -105 55 -137q0 -44 -37.5 -71.5t-94.5 -27.5q-60 0 -96 29.5t-36 78.5q0 28 57 129q46 81 54 178q-94 -9 -179 -55
q-105 -56 -137 -56q-44 0 -71.5 37.5t-27.5 94.5q0 60 29.5 96t78.5 36q28 0 129 -57q82 -45 178 -55q-9 226 -111 398q102 171 111 397q-96 -10 -178 -55q-101 -57 -129 -57q-49 0 -78.5 36t-29.5 96q0 57 27.5 94.5t71.5 37.5q32 0 137 -56q85 -46 179 -55q-8 97 -54 178
q-57 101 -57 129q0 49 36 78.5t96 29.5q57 0 94.5 -27.5t37.5 -71.5q0 -32 -55 -137q-46 -85 -55 -179q96 8 177 54q101 57 129 57q49 0 79 -36t30 -96q0 -57 -27.5 -94.5t-72.5 -37.5q-32 0 -136 55q-85 46 -179 57q8 -226 110 -397q-102 -172 -110 -398z" />
<glyph glyph-name="bullet" unicode="&#x2022;" horiz-adv-x="1024"
d="M216 718q0 123 87 209t210 86q122 0 208.5 -86.5t86.5 -208.5t-87.5 -209.5t-209.5 -87.5q-123 0 -209 87t-86 210z" />
<glyph glyph-name="ellipsis" unicode="&#x2026;" horiz-adv-x="2048"
d="M145 167l82 84q15 14 29 14q13 0 31 -16l80 -86q12 -16 12 -29q0 -15 -14 -31l-80 -88q-20 -20 -29 -20q-16 0 -29 14l-88 101q-10 13 -10 26q0 15 16 31zM828 167l82 84q15 14 29 14q13 0 31 -16l80 -86q12 -16 12 -29q0 -15 -14 -31l-80 -88q-20 -20 -29 -20
q-16 0 -29 14l-88 101q-10 13 -10 26q0 15 16 31zM1511 167l82 84q15 14 29 14q13 0 31 -16l80 -86q12 -16 12 -29q0 -15 -14 -31l-80 -88q-20 -20 -29 -20q-16 0 -29 14l-88 101q-10 13 -10 26q0 15 16 31z" />
<glyph glyph-name="guilsinglleft" unicode="&#x2039;" horiz-adv-x="631"
d="M174 479l342 303h14v-37l-205 -266l205 -266v-37h-14z" />
<glyph glyph-name="guilsinglright" unicode="&#x203a;" horiz-adv-x="631"
d="M115 176h-14v37l205 266l-205 266v37h14l342 -303z" />
<glyph glyph-name="fraction" unicode="&#x2044;" horiz-adv-x="342"
d="M-342 -29l940 1461h84l-938 -1461h-86z" />
<glyph glyph-name="fraction" unicode="&#x2215;" horiz-adv-x="342"
d="M-342 -29l940 1461h84l-938 -1461h-86z" />
<glyph glyph-name="franc" unicode="&#x20a3;"
d="M247 357h-194v60h194v732q0 235 -103 235h-96v50h915l103 -231h-49q-59 182 -190 182l-316 -1q-102 0 -102 -235v-352h361q100 0 100 63v58h50v-342h-50v60q0 62 -100 62h-361v-281h194v-60h-194v-72q0 -235 102 -235h97v-50h-560v50h96q103 0 103 235v72z" />
<glyph glyph-name="lira" unicode="&#x20a4;"
d="M748 1347q-72 31 -160 31h-2q-100 0 -190 -101q-84 -93 -84 -241q0 -15 1 -30q0 -106 33 -213h380v-60h-360q12 -30 26 -60h352v-60h-321q35 -63 35 -138q0 -161 -162 -375h402q130 0 189 132l49 -1l-103 -231h-719l1 50q187 238 187 418q0 77 -34 143l-2 2h-172v60h143
q-14 31 -26 60h-135v60h113q-36 107 -36 193q0 226 123.5 347t310.5 121q75 0 185.5 -14t110.5 -34v-161h-58q-5 61 -77 102z" />
<glyph glyph-name="peseta" unicode="&#x20a7;" horiz-adv-x="2028"
d="M409 1384v-662q3 -9 7 -17q41 -102 108 -153q57 -44 116 -44q10 0 19 1q68 8 127 75t87 177q22 87 22 179q0 24 -1 47q-7 116 -49.5 218.5t-108.5 144.5q-56 35 -112 35q-10 0 -21 -1h-194zM1496 908h-179v-685q0 -81 34 -119q28 -31 81 -37l-71 192l49 1
q55 -130 114 -174q57 -44 127 -44h7q92 0 151 52q59 53 59 136q0 102 -259 226q-101 52 -144 112t-43 145q0 121 73 194zM1039 910q-7 -101 -48 -194q-50 -114 -141 -177.5t-190 -63.5q-100 0 -191 64q-33 22 -60 51v-305q0 -235 102 -235h97v-50h-560v50h96q103 0 103 235
v864q0 235 -103 235h-96v50h618q92 -2 181 -62q91 -62 143 -177q50 -113 51 -237h10q216 0 216 355h50v-355h259q42 19 110 20h2q54 0 133.5 -13.5t79.5 -33.5v-159h-42q-4 66 -65.5 108t-133.5 42q-64 0 -102.5 -36.5t-38.5 -96.5q0 -108 235 -220q122 -55 167.5 -117.5
t45.5 -153.5q0 -140 -83 -231q-102 -84 -228 -86q-58 0 -105 11q-28 6 -56 6q-18 0 -36 -3q-28 -5 -59 -5q-124 0 -173.5 57t-57.5 176h-1v687h-129z" />
<glyph glyph-name="Euro" unicode="&#x20ac;" horiz-adv-x="1662"
d="M1426 369q-49 5 -87 -26q-131 -106 -300 -106q-116 0 -218 53q-99 51 -166 140h171q49 0 83 35q35 35 35 84t-35 84q-34 34 -83 34h-263q-2 25 -2 48q0 49 9 96h271q49 0 84 35t35 84t-35 84t-84 35h-145q141 145 343 145q166 0 296 -103q38 -30 87 -24q49 5 79 44
q31 39 25 87q-6 49 -45 79q-194 154 -442 154q-203 0 -374 -106q-167 -103 -259 -276h-52q-49 0 -84 -35q-34 -35 -34 -84q0 -43 27 -75q27 -33 67 -41q-7 -50 -7 -99q0 -21 2 -48q-44 -5 -75 -39q-30 -34 -30 -79q0 -49 35 -84q34 -35 84 -35h44q84 -192 259 -310
q180 -120 397 -120q252 0 449 158q38 31 43 80q6 49 -25 87t-80 44z" />
<glyph glyph-name="uni2116" unicode="&#x2116;" horiz-adv-x="2271"
/>
<glyph glyph-name="trademark" unicode="&#x2122;" horiz-adv-x="1497"
/>
<glyph glyph-name="partialdiff" unicode="&#x2202;"
d="M232 537q0 -41 5 -79q14 -122 61.5 -230t118.5 -165q64 -53 128 -53q6 0 13 1q70 5 127.5 70.5t80.5 179.5q16 73 16 149q0 42 -5 85q-14 122 -62.5 231.5t-119.5 165.5q-65 50 -128 50h-11q-68 -5 -126 -69.5t-82 -178.5q-16 -84 -16 -157zM937 477q0 -132 -56.5 -251
t-159 -185t-214.5 -66t-214.5 66t-159 185t-56.5 251q0 131 58 251t161 185t211 65q109 0 212 -65q29 -18 54 -41q-84 235 -233.5 377t-326.5 155v55q306 0 515 -285t209 -697z" />
<glyph glyph-name="Delta" unicode="&#x2206;" horiz-adv-x="1081"
d="M514 1195l-406 -1072h801zM547 1434l526 -1434h-1067z" />
<glyph glyph-name="product" unicode="&#x220f;" horiz-adv-x="1515"
d="M511 1384q-102 0 -102 -235v-1281q0 -235 102 -235h97v-51h-560v51h96q103 0 103 235v1281q0 235 -103 235h-96v50h1419v-50h-97q-102 0 -102 -235v-1281q0 -235 102 -235h97v-50h-560v50h96q103 0 103 235v1281q0 235 -103 235h-492z" />
<glyph glyph-name="summation" unicode="&#x2211;" horiz-adv-x="1206"
d="M1059 548l-788 -914h635q130 0 189 182h49l-103 -232h-921v50q62 0 106 53l663 781l-663 859q-44 57 -106 57v50h921l103 -232h-49q-59 182 -189 182h-485z" />
<glyph glyph-name="minus" unicode="&#x2212;"
d="M87 647v140h839l1 -1v-139h-840z" />
<glyph glyph-name="radical" unicode="&#x221a;"
d="M181 0l-164 359l74 35l85 -185l728 1470h150v-60h-72z" />
<glyph glyph-name="infinity" unicode="&#x221e;"
d="M439 755q-15 103 -74 133q-46 22 -84 22q-12 0 -23 -2q-49 -10 -92.5 -44.5t-65.5 -84.5q-20 -46 -20 -90v-8q2 -48 27.5 -89t71.5 -58q29 -11 61 -11q16 0 33 3q47 10 90.5 43.5t75.5 185.5zM466 687q12 -96 94 -153q69 -48 123 -48q11 0 21 2q62 12 117.5 52t84.5 101
q26 54 26 108v11q-2 60 -35.5 108.5t-91.5 68.5q-37 13 -76 13q-22 0 -44 -4q-67 -9 -127 -62t-92 -197zM450 827q9 35 21 69q34 88 95 137t128 49t128 -48t95 -135t34 -182t-34 -182t-95 -135t-128 -48t-128 49t-95 136q-12 35 -21 70q-5 -21 -12 -41q-27 -73 -74 -113
t-99 -40t-100 41t-73.5 113.5t-25.5 149.5q0 76 25.5 149t73.5 114t100 41t99 -40t74 -112q7 -21 12 -42z" />
<glyph glyph-name="integral" unicode="&#x222b;" horiz-adv-x="665"
d="M-12 -281q-60 0 -60 29v159h36q1 -43 34.5 -64.5t63.5 -21.5h1q82 0 115 162q32 162 40 316l70 734l8 62q27 238 135 429.5t234 191.5q60 0 60 -29v-159h-36q-1 43 -35 64.5t-63 21.5q-71 0 -116 -155.5t-49 -363.5l-73 -767q-20 -231 -130.5 -420t-234.5 -189z" />
<glyph glyph-name="approxequal" unicode="&#x2248;"
d="M923 1053v-156q-63 -72 -122 -97.5t-116 -25.5q-60 0 -177.5 48.5t-176.5 48.5q-51 0 -107.5 -28t-129.5 -112v156q64 73 123 99t114 26q64 0 181.5 -49.5t172.5 -49.5q52 0 108.5 28t129.5 112zM923 705v-156q-63 -72 -122 -97.5t-116 -25.5q-60 0 -177.5 48.5
t-176.5 48.5q-51 0 -107.5 -28t-129.5 -112v156q64 73 123 99t114 26q64 0 181.5 -49.5t172.5 -49.5q52 0 108.5 28t129.5 112z" />
<glyph glyph-name="lessequal" unicode="&#x2264;"
d="M927 1074l-625 -359l625 -355v-167l-840 481v83l840 484v-167zM87 1v140h839l1 -1v-139h-840z" />
<glyph glyph-name="greaterequal" unicode="&#x2265;"
d="M87 1241l840 -484v-83l-840 -481v167l625 355l-625 359v167zM87 2v140h839l1 -1v-139h-840z" />
<glyph glyph-name="uniF001" unicode="&#xf001;" horiz-adv-x="1073"
/>
<glyph glyph-name="uniF001" unicode="&#xfb01;" horiz-adv-x="1073"
/>
<glyph glyph-name="uniF002" unicode="&#xf002;" horiz-adv-x="1081"
/>
<glyph glyph-name="uniF002" unicode="&#xfb02;" horiz-adv-x="1081"
/>
</font>
</defs></svg>

After

(image error) Size: 61 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

19406
tests/fonts/Ubuntu.svg Normal file

File diff suppressed because it is too large Load diff

After

(image error) Size: 988 KiB

Binary file not shown.

After

(image error) Size: 42 KiB

Binary file not shown.

After

(image error) Size: 3.8 KiB

Binary file not shown.

After

(image error) Size: 5 KiB

Binary file not shown.

After

(image error) Size: 3.5 KiB

Binary file not shown.

After

(image error) Size: 2.5 KiB

Binary file not shown.

After

(image error) Size: 2.7 KiB

Binary file not shown.

After

(image error) Size: 3.7 KiB

Binary file not shown.

After

(image error) Size: 4.2 KiB

Binary file not shown.

After

(image error) Size: 5.5 KiB

Binary file not shown.

After

(image error) Size: 7.6 KiB

BIN
tests/fonts/diffs/huge1.png Normal file

Binary file not shown.

After

(image error) Size: 75 KiB

Binary file not shown.

After

(image error) Size: 75 KiB

BIN
tests/fonts/diffs/huge2.png Normal file

Binary file not shown.

After

(image error) Size: 70 KiB

Binary file not shown.

After

(image error) Size: 69 KiB

BIN
tests/fonts/diffs/huge3.png Normal file

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 9.3 KiB

Binary file not shown.

After

(image error) Size: 6.5 KiB

Binary file not shown.

After

(image error) Size: 52 KiB

Binary file not shown.

After

(image error) Size: 54 KiB

Binary file not shown.

After

(image error) Size: 38 KiB

Binary file not shown.

After

(image error) Size: 20 KiB

Binary file not shown.

After

(image error) Size: 73 KiB

Binary file not shown.

After

(image error) Size: 74 KiB

Binary file not shown.

After

(image error) Size: 20 KiB

Binary file not shown.

After

(image error) Size: 74 KiB

Binary file not shown.

After

(image error) Size: 74 KiB

Binary file not shown.

After

(image error) Size: 19 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 73 KiB

Binary file not shown.

After

(image error) Size: 19 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 19 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 73 KiB

Binary file not shown.

After

(image error) Size: 19 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 73 KiB

Binary file not shown.

After

(image error) Size: 20 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 20 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 72 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 84 KiB

Binary file not shown.

After

(image error) Size: 85 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 84 KiB

Binary file not shown.

After

(image error) Size: 85 KiB

Binary file not shown.

After

(image error) Size: 1.4 KiB

Binary file not shown.

After

(image error) Size: 1.8 KiB

Binary file not shown.

After

(image error) Size: 243 B

Binary file not shown.

After

(image error) Size: 27 KiB

Binary file not shown.

After

(image error) Size: 27 KiB

Binary file not shown.

After

(image error) Size: 73 KiB

Binary file not shown.

After

(image error) Size: 29 KiB

BIN
tests/fonts/image_fill.png Normal file

Binary file not shown.

After

(image error) Size: 1.4 KiB

Binary file not shown.

After

(image error) Size: 2.7 KiB

Binary file not shown.

After

(image error) Size: 6.9 KiB

BIN
tests/fonts/mask_fill.png Normal file

Binary file not shown.

After

(image error) Size: 712 B

BIN
tests/fonts/mask_stroke.png Normal file

Binary file not shown.

After

(image error) Size: 3.7 KiB

Some files were not shown because too many files have changed in this diff Show more