Showing preview only (449K chars total). Download the full file or copy to clipboard to get everything.
Repository: GiovineItalia/Compose.jl
Branch: master
Commit: 2a442dd2fcc8
Files: 57
Total size: 429.5 KB
Directory structure:
gitextract_ye7p7qi7/
├── .github/
│ └── workflows/
│ ├── CI.yml
│ ├── CompatHelper.yml
│ └── TagBot.yml
├── .gitignore
├── LICENSE.md
├── Project.toml
├── README.md
├── TODO.md
├── deps/
│ ├── glyphsize.c
│ ├── glyphsize.json
│ ├── mkfile
│ └── snap.svg-min.js
├── docs/
│ ├── Project.toml
│ ├── make.jl
│ └── src/
│ ├── gallery/
│ │ ├── forms.md
│ │ ├── properties.md
│ │ └── transforms.md
│ ├── index.md
│ ├── library.md
│ └── tutorial.md
├── src/
│ ├── Compose.jl
│ ├── abandoned.jl
│ ├── batch.jl
│ ├── cairo_backends.jl
│ ├── container.jl
│ ├── fontfallback.jl
│ ├── form.jl
│ ├── immerse_backend.jl
│ ├── list.jl
│ ├── measure.jl
│ ├── misc.jl
│ ├── pango.jl
│ ├── pgf_backend.jl
│ ├── property.jl
│ ├── stack.jl
│ ├── svg.jl
│ ├── table-jump.jl
│ └── table.jl
└── test/
├── .gitignore
├── Project.toml
├── examples/
│ ├── arc_sector.jl
│ ├── arrow.jl
│ ├── bezigon.jl
│ ├── dashedlines.jl
│ ├── forms_and_nans.jl
│ ├── golden_rect.jl
│ ├── linecaps.jl
│ ├── linejoins.jl
│ ├── polygon_forms.jl
│ ├── primitives.jl
│ ├── text.jl
│ ├── transformations.jl
│ └── unicode.jl
├── immerse.jl
├── misc.jl
├── runtests.jl
└── svg.jl
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/CI.yml
================================================
name: CI
on:
pull_request:
branches:
- master
push:
branches:
- master
tags: '*'
jobs:
test:
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version:
- '1.10'
- '1'
os:
- ubuntu-latest
- macOS-latest
- windows-latest
arch:
- x64
steps:
- uses: actions/checkout@v6
- uses: julia-actions/setup-julia@v2
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- uses: julia-actions/cache@v2
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-runtest@v1
- uses: julia-actions/julia-processcoverage@v1
- uses: codecov/codecov-action@v5
with:
files: lcov.info
token: ${{ secrets.CODECOV_TOKEN }}
docs:
name: Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: '1'
- run: |
julia --project=docs -e '
using Pkg
Pkg.develop(PackageSpec(path=pwd()))
Pkg.instantiate()'
- run: julia --project=docs docs/make.jl
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
================================================
FILE: .github/workflows/CompatHelper.yml
================================================
name: CompatHelper
on:
schedule:
- cron: '0 0 * * 0'
issues:
types: [opened, reopened]
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
julia-version: [1.2.0]
julia-arch: [x86]
os: [ubuntu-latest]
steps:
- uses: julia-actions/setup-julia@latest
with:
version: ${{ matrix.julia-version }}
- name: Pkg.add("CompatHelper")
run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
- name: CompatHelper.main()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: julia -e 'using CompatHelper; CompatHelper.main()'
================================================
FILE: .github/workflows/TagBot.yml
================================================
name: TagBot
on:
issue_comment:
types:
- created
workflow_dispatch:
jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
runs-on: ubuntu-latest
steps:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.TAGBOT_PAT }}
ssh: ${{ secrets.DOCUMENTER_KEY }}
================================================
FILE: .gitignore
================================================
*~
*swp
# System-specific files and directories generated by the BinaryProvider and BinDeps packages
# They contain absolute paths specific to the host computer, and so should not be committed
deps/deps.jl
deps/build.log
deps/downloads/
deps/usr/
deps/src/
# Build artifacts for creating documentation generated by the Documenter package
docs/build/
docs/site/
test/output
# File generated by Pkg, the package manager, based on a corresponding Project.toml
# It records a fixed state of all packages used by the project. As such, it should not be
# committed for packages, but should be committed for applications that require a static
# environment.
Manifest.toml
# System files generated by MacOS.
.DS_Store
================================================
FILE: LICENSE.md
================================================
Compose is licensed under the MIT License:
> Copyright (c) 2012--2015: Daniel C. Jones and other contributors
>
> Permission is hereby granted, free of charge, to any person obtaining
> a copy of this software and associated documentation files (the
> "Software"), to deal in the Software without restriction, including
> without limitation the rights to use, copy, modify, merge, publish,
> distribute, sublicense, and/or sell copies of the Software, and to
> permit persons to whom the Software is furnished to do so, subject to
> the following conditions:
>
> The above copyright notice and this permission notice shall be
> included in all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: Project.toml
================================================
name = "Compose"
uuid = "a81c6b42-2e10-5240-aca2-a61377ecd94b"
version = "0.9.6"
[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
[compat]
Colors = "0.9, 0.10, 0.11, 0.12, 0.13"
DataStructures = "0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19"
IterTools = "1"
JSON = "0.18, 0.19, 0.20, 0.21"
Measures = "0.3"
Requires = "0.5, 1.0"
julia = "1"
================================================
FILE: README.md
================================================
# Compose!
[![][docs-latest-img]][docs-latest-url] [![][travis-img]][travis-url] [![][codecov-img]][codecov-url]
Compose is a vector graphics library for Julia.
It forms the basis for the statistical graphics system
[Gadfly](https://github.com/GiovineItalia/Gadfly.jl).
## Synopsis
Unlike most vector graphics libraries, Compose is thoroughly declarative. Rather
than issue a sequence of drawing commands, graphics are formed by sticking
various things together and then letting the library figure out how to draw it.
The "things" in this case fall one of three types: Property, Form, and Canvas.
"Sticking together" is primary achieved with the `compose` function.
The semantics of composition are fairly simple, and once grasped provide a
consistent and powerful means of building vector graphics.
## Documentation
- [**LATEST**][docs-latest-url] — *in-development version of the documentation.*
[docs-latest-img]: https://img.shields.io/badge/docs-latest-blue.svg
[docs-latest-url]: https://giovineitalia.github.io/Compose.jl/latest
[travis-img]: http://img.shields.io/travis/GiovineItalia/Compose.jl.svg
[travis-url]: https://travis-ci.org/GiovineItalia/Compose.jl
[codecov-img]: https://codecov.io/gh/GiovineItalia/Compose.jl/branch/master/graph/badge.svg
[codecov-url]: https://codecov.io/gh/GiovineItalia/Compose.jl
================================================
FILE: TODO.md
================================================
* Coherent hstack and vstack functions.
* Documentation!!!
* Functions for arranging canvases in, e.g. grids.
* Embedding fonts in SVGs.
================================================
FILE: deps/glyphsize.c
================================================
/* Use freetype to read a font and dump typeface name and glyph sizes for
* printable ascii characters into an easily parsible JSON format. */
#include <stdio.h>
#include <ft2build.h>
#include FT_FREETYPE_H
/* Write a font's glyph extents to stdout. */
void dumpfont(FT_Library library, const char* fn)
{
FT_Error error;
FT_Face face;
int face_index;
int num_faces = 1;
for (face_index = 0; face_index < num_faces; ++face_index) {
error = FT_New_Face(library, fn, face_index, &face);
if (error) {
fprintf(stderr, "Error reading font from %s. (%d)\n", fn, (int) error);
exit(1);
}
num_faces = face->num_faces;
/* set dpi to micrometer per inch, so sizes are reported in micrometers. */
const FT_UInt dpi = 25400;
error = FT_Set_Char_Size(face, 0, 12*64, dpi, dpi);
if (error) {
fprintf(stderr, "Error setting font size.\n");
exit(1);
}
if (strcmp(face->style_name, "Regular") == 0) {
printf("\"%s\"", face->family_name);
}
else {
printf("\"%s %s\"", face->family_name, face->style_name);
}
printf(": {\n \"widths\": {\n ");
char c;
FT_UInt i;
FT_Pos max_height = 0;
for (c = 0x20; c <= 0x7e; ++c) {
i = FT_Get_Char_Index(face, c);
error = FT_Load_Glyph(face, i, FT_LOAD_DEFAULT);
if (error) {
fprintf(stderr, "Error loading glyph for '%c'.", c);
exit(1);
}
if (face->glyph->metrics.height > max_height) {
max_height = face->glyph->metrics.height;
}
printf(" \"");
if (c == '"' || c == '\\') putchar('\\');
printf("%c\": ", c);
if (c != '"' && c != '\\') putchar(' ');
printf("%5.2f", (double) face->glyph->advance.x / 64.0 / 1000.0);
if (c != 0x7e) putchar(',');
if ((c - 0x20 + 1) % 5 == 0) {
printf("\n ");
}
}
printf("},\n \"height\": %0.2f\n}", (double) max_height / 64.0 / 1000.0);
FT_Done_Face(face);
if (face_index + 1 < num_faces) puts(",");
}
}
int main(int argc, char* argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: glyphsize fontfile [fontfile2...] > stuff.json\n");
return 1;
}
FT_Library library;
FT_Error error;
error = FT_Init_FreeType(&library);
if (error) {
fprintf(stderr, "Error initalizing freetype.\n");
return 1;
}
puts("{");
int i;
for (i = 1; i < argc; ++i) {
dumpfont(library, argv[i]);
if (i != argc - 1) puts(",");
}
puts("}");
FT_Done_FreeType(library);
return 0;
}
================================================
FILE: deps/glyphsize.json
================================================
{
"Helvetica Neue Bold": {
"widths": {
" ": 1.18, "!": 1.18, "\"": 1.96, "#": 2.35, "$": 2.35,
"%": 4.23, "&": 2.90, "'": 1.18, "(": 1.25, ")": 1.25,
"*": 1.72, "+": 2.54, ",": 1.18, "-": 1.72, ".": 1.18,
"/": 1.57, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.35, "@": 3.39, "A": 2.90, "B": 2.98,
"C": 3.14, "D": 3.14, "E": 2.74, "F": 2.51, "G": 3.21,
"H": 3.14, "I": 1.25, "J": 2.35, "K": 3.06, "L": 2.51,
"M": 3.84, "N": 3.14, "O": 3.29, "P": 2.82, "Q": 3.29,
"R": 3.06, "S": 2.75, "T": 2.59, "U": 3.14, "V": 2.67,
"W": 4.00, "X": 2.82, "Y": 2.82, "Z": 2.74, "[": 1.41,
"\\": 1.57, "]": 1.41, "^": 2.54, "_": 2.12, "`": 1.10,
"a": 2.43, "b": 2.59, "c": 2.43, "d": 2.59, "e": 2.43,
"f": 1.41, "g": 2.59, "h": 2.51, "i": 1.09, "j": 1.18,
"k": 2.43, "l": 1.09, "m": 3.84, "n": 2.51, "o": 2.59,
"p": 2.59, "q": 2.59, "r": 1.65, "s": 2.27, "t": 1.49,
"u": 2.51, "v": 2.20, "w": 3.45, "x": 2.27, "y": 2.20,
"z": 2.20, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue": {
"widths": {
" ": 1.18, "!": 1.10, "\"": 1.80, "#": 2.35, "$": 2.35,
"%": 4.23, "&": 2.67, "'": 1.18, "(": 1.10, ")": 1.10,
"*": 1.49, "+": 2.54, ",": 1.18, "-": 1.65, ".": 1.18,
"/": 1.41, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.35, "@": 3.39, "A": 2.74, "B": 2.90,
"C": 3.06, "D": 2.98, "E": 2.59, "F": 2.43, "G": 3.21,
"H": 3.06, "I": 1.10, "J": 2.20, "K": 2.82, "L": 2.35,
"M": 3.69, "N": 3.06, "O": 3.22, "P": 2.74, "Q": 3.22,
"R": 2.90, "S": 2.74, "T": 2.43, "U": 3.06, "V": 2.59,
"W": 3.92, "X": 2.59, "Y": 2.74, "Z": 2.59, "[": 1.10,
"\\": 1.41, "]": 1.10, "^": 2.54, "_": 2.12, "`": 0.94,
"a": 2.27, "b": 2.51, "c": 2.27, "d": 2.51, "e": 2.27,
"f": 1.25, "g": 2.43, "h": 2.35, "i": 0.94, "j": 0.94,
"k": 2.20, "l": 0.94, "m": 3.61, "n": 2.35, "o": 2.43,
"p": 2.51, "q": 2.51, "r": 1.41, "s": 2.12, "t": 1.33,
"u": 2.35, "v": 2.12, "w": 3.21, "x": 2.19, "y": 2.12,
"z": 2.03, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue UltraLight": {
"widths": {
" ": 1.18, "!": 0.78, "\"": 1.18, "#": 2.35, "$": 2.35,
"%": 2.90, "&": 2.43, "'": 0.71, "(": 0.94, ")": 0.94,
"*": 1.49, "+": 2.54, ",": 1.18, "-": 1.41, ".": 1.18,
"/": 1.41, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.12, "@": 3.39, "A": 2.43, "B": 2.59,
"C": 2.90, "D": 2.74, "E": 2.27, "F": 2.04, "G": 3.06,
"H": 2.74, "I": 0.54, "J": 1.96, "K": 2.51, "L": 2.04,
"M": 3.30, "N": 2.74, "O": 3.05, "P": 2.43, "Q": 3.05,
"R": 2.59, "S": 2.59, "T": 2.12, "U": 2.67, "V": 2.28,
"W": 3.68, "X": 2.20, "Y": 2.28, "Z": 2.12, "[": 0.94,
"\\": 1.41, "]": 0.94, "^": 2.54, "_": 2.12, "`": 0.55,
"a": 2.04, "b": 2.27, "c": 2.12, "d": 2.27, "e": 2.12,
"f": 0.86, "g": 2.20, "h": 2.12, "i": 0.55, "j": 0.55,
"k": 1.88, "l": 0.55, "m": 3.29, "n": 2.12, "o": 2.20,
"p": 2.27, "q": 2.27, "r": 1.10, "s": 1.96, "t": 1.02,
"u": 2.12, "v": 1.72, "w": 2.90, "x": 1.72, "y": 1.72,
"z": 1.72, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue Italic": {
"widths": {
" ": 1.18, "!": 1.10, "\"": 1.80, "#": 2.35, "$": 2.35,
"%": 3.92, "&": 2.67, "'": 1.18, "(": 1.10, ")": 1.10,
"*": 1.49, "+": 2.54, ",": 1.18, "-": 1.65, ".": 1.18,
"/": 1.41, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.35, "@": 3.39, "A": 2.82, "B": 2.90,
"C": 3.06, "D": 2.98, "E": 2.59, "F": 2.43, "G": 3.21,
"H": 3.06, "I": 1.10, "J": 2.20, "K": 2.82, "L": 2.35,
"M": 3.68, "N": 3.06, "O": 3.21, "P": 2.74, "Q": 3.21,
"R": 2.90, "S": 2.74, "T": 2.43, "U": 3.06, "V": 2.59,
"W": 3.92, "X": 2.59, "Y": 2.59, "Z": 2.59, "[": 1.10,
"\\": 1.41, "]": 1.10, "^": 2.54, "_": 2.12, "`": 0.94,
"a": 2.20, "b": 2.51, "c": 2.27, "d": 2.51, "e": 2.27,
"f": 1.25, "g": 2.43, "h": 2.35, "i": 0.94, "j": 0.94,
"k": 2.04, "l": 0.94, "m": 3.61, "n": 2.35, "o": 2.43,
"p": 2.51, "q": 2.51, "r": 1.41, "s": 2.04, "t": 1.33,
"u": 2.35, "v": 2.04, "w": 3.21, "x": 2.04, "y": 2.04,
"z": 1.88, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue Light": {
"widths": {
" ": 1.18, "!": 1.02, "\"": 1.57, "#": 2.35, "$": 2.35,
"%": 3.76, "&": 2.59, "'": 1.18, "(": 1.02, ")": 1.02,
"*": 1.49, "+": 2.54, ",": 1.18, "-": 1.57, ".": 1.18,
"/": 1.41, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.27, "@": 3.39, "A": 2.67, "B": 2.82,
"C": 2.98, "D": 2.90, "E": 2.51, "F": 2.27, "G": 3.14,
"H": 2.98, "I": 0.94, "J": 2.12, "K": 2.74, "L": 2.27,
"M": 3.48, "N": 2.98, "O": 3.14, "P": 2.67, "Q": 3.14,
"R": 2.82, "S": 2.67, "T": 2.35, "U": 2.90, "V": 2.51,
"W": 3.84, "X": 2.43, "Y": 2.59, "Z": 2.43, "[": 1.02,
"\\": 1.41, "]": 1.02, "^": 2.54, "_": 2.12, "`": 0.78,
"a": 2.20, "b": 2.43, "c": 2.20, "d": 2.43, "e": 2.20,
"f": 1.10, "g": 2.35, "h": 2.27, "i": 0.78, "j": 0.78,
"k": 2.12, "l": 0.78, "m": 3.53, "n": 2.27, "o": 2.35,
"p": 2.43, "q": 2.43, "r": 1.33, "s": 2.04, "t": 1.25,
"u": 2.27, "v": 1.96, "w": 3.14, "x": 2.04, "y": 1.96,
"z": 1.96, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue UltraLight Italic": {
"widths": {
" ": 1.18, "!": 0.78, "\"": 1.18, "#": 2.35, "$": 2.35,
"%": 2.90, "&": 2.43, "'": 0.71, "(": 0.94, ")": 0.94,
"*": 1.49, "+": 2.54, ",": 1.18, "-": 1.41, ".": 1.18,
"/": 1.41, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.12, "@": 3.39, "A": 2.43, "B": 2.59,
"C": 2.90, "D": 2.82, "E": 2.20, "F": 2.04, "G": 3.06,
"H": 2.74, "I": 0.63, "J": 1.96, "K": 2.51, "L": 2.04,
"M": 3.37, "N": 2.82, "O": 3.06, "P": 2.43, "Q": 3.06,
"R": 2.51, "S": 2.59, "T": 2.12, "U": 2.74, "V": 2.35,
"W": 3.76, "X": 2.20, "Y": 2.20, "Z": 2.12, "[": 0.94,
"\\": 1.41, "]": 0.94, "^": 2.54, "_": 2.12, "`": 0.55,
"a": 2.04, "b": 2.27, "c": 2.12, "d": 2.27, "e": 2.12,
"f": 0.86, "g": 2.20, "h": 2.12, "i": 0.55, "j": 0.55,
"k": 1.88, "l": 0.55, "m": 3.29, "n": 2.12, "o": 2.20,
"p": 2.27, "q": 2.27, "r": 1.10, "s": 1.96, "t": 1.02,
"u": 2.12, "v": 1.72, "w": 2.90, "x": 1.72, "y": 1.72,
"z": 1.72, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue Condensed Black": {
"widths": {
" ": 1.10, "!": 1.33, "\"": 2.04, "#": 2.20, "$": 2.20,
"%": 3.29, "&": 2.59, "'": 1.10, "(": 1.33, ")": 1.33,
"*": 1.72, "+": 2.54, ",": 1.10, "-": 1.56, ".": 1.10,
"/": 1.41, "0": 2.20, "1": 2.20, "2": 2.20, "3": 2.20,
"4": 2.20, "5": 2.20, "6": 2.20, "7": 2.20, "8": 2.20,
"9": 2.20, ":": 1.10, ";": 1.10, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.12, "@": 3.39, "A": 2.35, "B": 2.43,
"C": 2.27, "D": 2.43, "E": 2.12, "F": 2.04, "G": 2.35,
"H": 2.43, "I": 1.10, "J": 2.04, "K": 2.35, "L": 1.96,
"M": 3.21, "N": 2.51, "O": 2.35, "P": 2.27, "Q": 2.35,
"R": 2.43, "S": 2.27, "T": 1.96, "U": 2.35, "V": 2.20,
"W": 3.29, "X": 2.27, "Y": 2.20, "Z": 2.04, "[": 1.33,
"\\": 1.41, "]": 1.33, "^": 2.54, "_": 2.12, "`": 1.10,
"a": 2.12, "b": 2.20, "c": 2.04, "d": 2.20, "e": 2.04,
"f": 1.33, "g": 2.20, "h": 2.20, "i": 1.09, "j": 1.09,
"k": 2.12, "l": 1.09, "m": 3.29, "n": 2.20, "o": 2.12,
"p": 2.20, "q": 2.20, "r": 1.49, "s": 1.96, "t": 1.33,
"u": 2.20, "v": 1.96, "w": 3.13, "x": 2.04, "y": 1.96,
"z": 1.88, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 3.79
},
"Helvetica Neue Condensed Bold": {
"widths": {
" ": 1.02, "!": 1.25, "\"": 1.96, "#": 2.03, "$": 2.03,
"%": 3.29, "&": 2.51, "'": 1.10, "(": 1.25, ")": 1.25,
"*": 1.65, "+": 2.54, ",": 1.02, "-": 1.57, ".": 1.02,
"/": 1.41, "0": 2.03, "1": 2.03, "2": 2.03, "3": 2.03,
"4": 2.03, "5": 2.03, "6": 2.03, "7": 2.03, "8": 2.03,
"9": 2.03, ":": 1.02, ";": 1.02, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.04, "@": 3.39, "A": 2.35, "B": 2.35,
"C": 2.27, "D": 2.43, "E": 2.04, "F": 1.96, "G": 2.35,
"H": 2.35, "I": 1.09, "J": 1.96, "K": 2.27, "L": 1.96,
"M": 3.13, "N": 2.43, "O": 2.35, "P": 2.20, "Q": 2.35,
"R": 2.35, "S": 2.20, "T": 2.03, "U": 2.28, "V": 2.20,
"W": 3.22, "X": 2.27, "Y": 2.20, "Z": 2.04, "[": 1.33,
"\\": 1.41, "]": 1.33, "^": 2.54, "_": 2.12, "`": 0.94,
"a": 2.04, "b": 2.12, "c": 1.96, "d": 2.12, "e": 1.96,
"f": 1.25, "g": 2.12, "h": 2.12, "i": 1.02, "j": 1.02,
"k": 2.12, "l": 1.02, "m": 3.21, "n": 2.12, "o": 2.03,
"p": 2.12, "q": 2.12, "r": 1.41, "s": 1.88, "t": 1.25,
"u": 2.12, "v": 1.88, "w": 2.98, "x": 1.96, "y": 1.88,
"z": 1.80, "{": 1.33, "|": 0.94, "}": 1.33, "~": 2.54
},
"height": 3.79
},
"Helvetica Neue Bold Italic": {
"widths": {
" ": 1.18, "!": 1.25, "\"": 2.04, "#": 2.35, "$": 2.35,
"%": 4.08, "&": 2.90, "'": 1.18, "(": 1.25, ")": 1.25,
"*": 1.72, "+": 2.54, ",": 1.18, "-": 1.72, ".": 1.18,
"/": 1.65, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.43, "@": 3.39, "A": 2.90, "B": 3.06,
"C": 3.14, "D": 3.14, "E": 2.82, "F": 2.51, "G": 3.21,
"H": 3.14, "I": 1.25, "J": 2.35, "K": 3.06, "L": 2.43,
"M": 3.84, "N": 3.14, "O": 3.29, "P": 2.82, "Q": 3.29,
"R": 3.06, "S": 2.74, "T": 2.59, "U": 3.14, "V": 2.67,
"W": 4.00, "X": 2.82, "Y": 2.74, "Z": 2.74, "[": 1.41,
"\\": 1.65, "]": 1.41, "^": 2.54, "_": 2.12, "`": 1.10,
"a": 2.43, "b": 2.59, "c": 2.35, "d": 2.59, "e": 2.43,
"f": 1.49, "g": 2.59, "h": 2.59, "i": 1.10, "j": 1.10,
"k": 2.35, "l": 1.10, "m": 3.84, "n": 2.59, "o": 2.51,
"p": 2.59, "q": 2.59, "r": 1.65, "s": 2.20, "t": 1.57,
"u": 2.59, "v": 2.20, "w": 3.45, "x": 2.20, "y": 2.20,
"z": 2.12, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue Light Italic": {
"widths": {
" ": 1.18, "!": 1.18, "\"": 1.57, "#": 2.35, "$": 2.35,
"%": 3.53, "&": 2.59, "'": 1.18, "(": 1.10, ")": 1.10,
"*": 1.49, "+": 2.54, ",": 1.18, "-": 1.57, ".": 1.18,
"/": 1.41, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.27, "@": 3.39, "A": 2.67, "B": 2.82,
"C": 2.98, "D": 2.90, "E": 2.43, "F": 2.27, "G": 3.14,
"H": 2.98, "I": 0.94, "J": 2.12, "K": 2.74, "L": 2.27,
"M": 3.61, "N": 2.98, "O": 3.14, "P": 2.67, "Q": 3.14,
"R": 2.74, "S": 2.67, "T": 2.35, "U": 2.98, "V": 2.51,
"W": 3.84, "X": 2.43, "Y": 2.43, "Z": 2.43, "[": 1.02,
"\\": 1.41, "]": 1.02, "^": 2.54, "_": 2.12, "`": 0.78,
"a": 2.20, "b": 2.43, "c": 2.20, "d": 2.43, "e": 2.20,
"f": 1.10, "g": 2.35, "h": 2.27, "i": 0.78, "j": 0.78,
"k": 1.96, "l": 0.78, "m": 3.53, "n": 2.27, "o": 2.35,
"p": 2.43, "q": 2.43, "r": 1.33, "s": 2.04, "t": 1.25,
"u": 2.27, "v": 1.96, "w": 3.14, "x": 1.96, "y": 1.96,
"z": 1.80, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue Medium": {
"widths": {
" ": 1.18, "!": 1.18, "\"": 1.88, "#": 2.35, "$": 2.35,
"%": 4.23, "&": 2.74, "'": 1.18, "(": 1.18, ")": 1.18,
"*": 1.57, "+": 2.54, ",": 1.18, "-": 1.65, ".": 1.18,
"/": 1.49, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.35, "@": 3.39, "A": 2.82, "B": 2.98,
"C": 3.06, "D": 3.06, "E": 2.67, "F": 2.51, "G": 3.21,
"H": 3.06, "I": 1.18, "J": 2.27, "K": 2.90, "L": 2.43,
"M": 3.76, "N": 3.06, "O": 3.22, "P": 2.82, "Q": 3.22,
"R": 2.98, "S": 2.74, "T": 2.51, "U": 3.06, "V": 2.59,
"W": 4.00, "X": 2.74, "Y": 2.74, "Z": 2.67, "[": 1.25,
"\\": 1.49, "]": 1.25, "^": 2.54, "_": 2.12, "`": 1.02,
"a": 2.35, "b": 2.59, "c": 2.35, "d": 2.59, "e": 2.35,
"f": 1.33, "g": 2.51, "h": 2.43, "i": 1.02, "j": 1.02,
"k": 2.27, "l": 1.02, "m": 3.68, "n": 2.43, "o": 2.51,
"p": 2.59, "q": 2.59, "r": 1.49, "s": 2.20, "t": 1.41,
"u": 2.43, "v": 2.20, "w": 3.29, "x": 2.27, "y": 2.20,
"z": 2.12, "{": 1.25, "|": 0.94, "}": 1.25, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue Thin": {
"widths": {
" ": 1.18, "!": 1.10, "\"": 1.33, "#": 2.35, "$": 2.35,
"%": 3.29, "&": 2.51, "'": 0.86, "(": 1.02, ")": 1.02,
"*": 1.49, "+": 2.54, ",": 1.18, "-": 1.49, ".": 1.18,
"/": 1.41, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.20, "@": 3.39, "A": 2.51, "B": 2.67,
"C": 2.98, "D": 2.82, "E": 2.37, "F": 2.18, "G": 3.14,
"H": 2.84, "I": 0.72, "J": 2.04, "K": 2.60, "L": 2.12,
"M": 3.42, "N": 2.87, "O": 3.14, "P": 2.50, "Q": 3.14,
"R": 2.67, "S": 2.67, "T": 2.20, "U": 2.85, "V": 2.35,
"W": 3.76, "X": 2.35, "Y": 2.43, "Z": 2.27, "[": 1.02,
"\\": 1.41, "]": 1.02, "^": 2.54, "_": 2.12, "`": 0.71,
"a": 2.12, "b": 2.35, "c": 2.20, "d": 2.35, "e": 2.20,
"f": 1.02, "g": 2.27, "h": 2.20, "i": 0.71, "j": 0.71,
"k": 1.96, "l": 0.71, "m": 3.37, "n": 2.20, "o": 2.27,
"p": 2.35, "q": 2.35, "r": 1.18, "s": 2.04, "t": 1.10,
"u": 2.20, "v": 1.88, "w": 2.98, "x": 1.88, "y": 1.88,
"z": 1.80, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue Thin Italic": {
"widths": {
" ": 1.18, "!": 0.86, "\"": 1.33, "#": 2.35, "$": 2.35,
"%": 3.21, "&": 2.51, "'": 0.86, "(": 1.02, ")": 1.02,
"*": 1.49, "+": 2.54, ",": 1.18, "-": 1.49, ".": 1.18,
"/": 1.41, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.20, "@": 3.39, "A": 2.59, "B": 2.67,
"C": 2.98, "D": 2.90, "E": 2.35, "F": 2.20, "G": 3.14,
"H": 2.82, "I": 0.78, "J": 2.04, "K": 2.59, "L": 2.12,
"M": 3.45, "N": 2.90, "O": 3.14, "P": 2.51, "Q": 3.14,
"R": 2.67, "S": 2.67, "T": 2.20, "U": 2.82, "V": 2.43,
"W": 3.84, "X": 2.35, "Y": 2.35, "Z": 2.27, "[": 1.02,
"\\": 1.41, "]": 1.02, "^": 2.54, "_": 2.12, "`": 0.71,
"a": 2.12, "b": 2.35, "c": 2.20, "d": 2.35, "e": 2.20,
"f": 1.02, "g": 2.27, "h": 2.20, "i": 0.71, "j": 0.71,
"k": 1.96, "l": 0.71, "m": 3.37, "n": 2.20, "o": 2.27,
"p": 2.35, "q": 2.35, "r": 1.18, "s": 1.96, "t": 1.10,
"u": 2.20, "v": 1.80, "w": 2.98, "x": 1.80, "y": 1.80,
"z": 1.80, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.54
},
"height": 4.23
},
"Helvetica Neue Medium Italic": {
"widths": {
" ": 1.18, "!": 1.25, "\"": 1.88, "#": 2.35, "$": 2.35,
"%": 4.00, "&": 2.82, "'": 1.18, "(": 1.25, ")": 1.25,
"*": 1.65, "+": 2.54, ",": 1.18, "-": 1.65, ".": 1.18,
"/": 1.49, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.54, "=": 2.54,
">": 2.54, "?": 2.35, "@": 3.39, "A": 2.90, "B": 2.98,
"C": 3.06, "D": 3.06, "E": 2.67, "F": 2.51, "G": 3.21,
"H": 3.06, "I": 1.18, "J": 2.27, "K": 2.90, "L": 2.43,
"M": 3.76, "N": 3.06, "O": 3.21, "P": 2.82, "Q": 3.21,
"R": 2.98, "S": 2.74, "T": 2.51, "U": 3.14, "V": 2.59,
"W": 3.92, "X": 2.74, "Y": 2.67, "Z": 2.67, "[": 1.25,
"\\": 1.49, "]": 1.25, "^": 2.54, "_": 2.12, "`": 1.02,
"a": 2.35, "b": 2.59, "c": 2.35, "d": 2.59, "e": 2.35,
"f": 1.33, "g": 2.51, "h": 2.43, "i": 1.02, "j": 1.02,
"k": 2.20, "l": 1.02, "m": 3.76, "n": 2.43, "o": 2.51,
"p": 2.59, "q": 2.59, "r": 1.57, "s": 2.12, "t": 1.41,
"u": 2.43, "v": 2.12, "w": 3.29, "x": 2.12, "y": 2.12,
"z": 2.04, "{": 1.25, "|": 0.94, "}": 1.25, "~": 2.54
},
"height": 4.23
},
"Helvetica": {
"widths": {
" ": 1.18, "!": 1.18, "\"": 1.49, "#": 2.35, "$": 2.35,
"%": 3.76, "&": 2.82, "'": 0.81, "(": 1.41, ")": 1.41,
"*": 1.65, "+": 2.47, ",": 1.18, "-": 1.41, ".": 1.18,
"/": 1.18, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.44, "=": 2.47,
">": 2.44, "?": 2.38, "@": 4.30, "A": 2.82, "B": 2.84,
"C": 3.03, "D": 3.02, "E": 2.81, "F": 2.59, "G": 3.25,
"H": 3.04, "I": 1.18, "J": 2.12, "K": 2.87, "L": 2.34,
"M": 3.53, "N": 3.04, "O": 3.29, "P": 2.81, "Q": 3.29,
"R": 3.01, "S": 2.76, "T": 2.59, "U": 3.07, "V": 2.82,
"W": 4.00, "X": 2.79, "Y": 2.83, "Z": 2.60, "[": 1.18,
"\\": 1.23, "]": 1.18, "^": 1.99, "_": 2.35, "`": 1.41,
"a": 2.35, "b": 2.36, "c": 2.12, "d": 2.35, "e": 2.34,
"f": 1.18, "g": 2.35, "h": 2.35, "i": 0.94, "j": 0.94,
"k": 2.12, "l": 0.94, "m": 3.53, "n": 2.35, "o": 2.34,
"p": 2.36, "q": 2.35, "r": 1.41, "s": 2.14, "t": 1.18,
"u": 2.33, "v": 2.12, "w": 3.06, "x": 2.12, "y": 2.12,
"z": 2.12, "{": 1.41, "|": 1.10, "}": 1.41, "~": 2.48
},
"height": 3.95
},
"Helvetica Bold": {
"widths": {
" ": 1.18, "!": 1.41, "\"": 2.01, "#": 2.35, "$": 2.35,
"%": 3.76, "&": 3.08, "'": 1.01, "(": 1.41, ")": 1.41,
"*": 1.65, "+": 2.47, ",": 1.18, "-": 1.38, ".": 1.18,
"/": 1.18, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.41, ";": 1.41, "<": 2.45, "=": 2.47,
">": 2.45, "?": 2.59, "@": 4.09, "A": 3.06, "B": 3.04,
"C": 3.03, "D": 3.06, "E": 2.82, "F": 2.60, "G": 3.29,
"H": 3.05, "I": 1.18, "J": 2.31, "K": 3.06, "L": 2.60,
"M": 3.53, "N": 3.05, "O": 3.29, "P": 2.79, "Q": 3.29,
"R": 3.00, "S": 2.85, "T": 2.59, "U": 3.05, "V": 2.82,
"W": 4.00, "X": 2.82, "Y": 2.82, "Z": 2.57, "[": 1.41,
"\\": 1.18, "]": 1.41, "^": 2.47, "_": 2.37, "`": 1.41,
"a": 2.37, "b": 2.60, "c": 2.36, "d": 2.59, "e": 2.46,
"f": 1.41, "g": 2.59, "h": 2.58, "i": 1.18, "j": 1.18,
"k": 2.37, "l": 1.18, "m": 3.77, "n": 2.58, "o": 2.59,
"p": 2.60, "q": 2.59, "r": 1.65, "s": 2.36, "t": 1.41,
"u": 2.58, "v": 2.35, "w": 3.29, "x": 2.35, "y": 2.35,
"z": 2.07, "{": 1.65, "|": 1.19, "}": 1.65, "~": 2.49
},
"height": 3.98
},
"Helvetica Oblique": {
"widths": {
" ": 1.18, "!": 1.18, "\"": 1.50, "#": 2.35, "$": 2.35,
"%": 3.76, "&": 2.82, "'": 0.81, "(": 1.41, ")": 1.41,
"*": 1.65, "+": 2.47, ",": 1.18, "-": 1.41, ".": 1.18,
"/": 1.18, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.47, "=": 2.47,
">": 2.47, "?": 2.35, "@": 4.30, "A": 2.82, "B": 2.82,
"C": 3.06, "D": 3.06, "E": 2.82, "F": 2.59, "G": 3.29,
"H": 3.06, "I": 1.18, "J": 2.12, "K": 2.82, "L": 2.35,
"M": 3.53, "N": 3.06, "O": 3.29, "P": 2.82, "Q": 3.29,
"R": 3.06, "S": 2.82, "T": 2.59, "U": 3.06, "V": 2.82,
"W": 4.00, "X": 2.82, "Y": 2.82, "Z": 2.59, "[": 1.18,
"\\": 1.18, "]": 1.18, "^": 1.99, "_": 2.35, "`": 1.41,
"a": 2.35, "b": 2.35, "c": 2.12, "d": 2.35, "e": 2.35,
"f": 1.18, "g": 2.35, "h": 2.35, "i": 0.94, "j": 0.94,
"k": 2.12, "l": 0.94, "m": 3.53, "n": 2.35, "o": 2.35,
"p": 2.35, "q": 2.35, "r": 1.41, "s": 2.12, "t": 1.18,
"u": 2.35, "v": 2.12, "w": 3.06, "x": 2.12, "y": 2.12,
"z": 2.12, "{": 1.41, "|": 1.10, "}": 1.41, "~": 2.47
},
"height": 3.95
},
"Helvetica Bold Oblique": {
"widths": {
" ": 1.18, "!": 1.41, "\"": 2.01, "#": 2.35, "$": 2.35,
"%": 3.76, "&": 3.06, "'": 1.01, "(": 1.41, ")": 1.41,
"*": 1.65, "+": 2.47, ",": 1.18, "-": 1.41, ".": 1.18,
"/": 1.18, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.41, ";": 1.41, "<": 2.47, "=": 2.47,
">": 2.47, "?": 2.59, "@": 4.13, "A": 3.06, "B": 3.06,
"C": 3.06, "D": 3.06, "E": 2.82, "F": 2.59, "G": 3.29,
"H": 3.06, "I": 1.18, "J": 2.35, "K": 3.06, "L": 2.59,
"M": 3.53, "N": 3.06, "O": 3.29, "P": 2.82, "Q": 3.29,
"R": 3.06, "S": 2.82, "T": 2.59, "U": 3.06, "V": 2.82,
"W": 4.00, "X": 2.82, "Y": 2.82, "Z": 2.59, "[": 1.41,
"\\": 1.18, "]": 1.41, "^": 2.47, "_": 2.35, "`": 1.41,
"a": 2.35, "b": 2.59, "c": 2.35, "d": 2.59, "e": 2.35,
"f": 1.41, "g": 2.59, "h": 2.59, "i": 1.18, "j": 1.18,
"k": 2.35, "l": 1.18, "m": 3.76, "n": 2.59, "o": 2.59,
"p": 2.59, "q": 2.59, "r": 1.65, "s": 2.35, "t": 1.41,
"u": 2.59, "v": 2.35, "w": 3.29, "x": 2.35, "y": 2.35,
"z": 2.12, "{": 1.65, "|": 1.18, "}": 1.65, "~": 2.47
},
"height": 3.98
},
"Helvetica Light": {
"widths": {
" ": 1.18, "!": 1.41, "\"": 1.18, "#": 2.35, "$": 2.35,
"%": 3.76, "&": 2.82, "'": 0.94, "(": 1.41, ")": 1.41,
"*": 1.65, "+": 2.79, ",": 1.18, "-": 1.41, ".": 1.18,
"/": 1.18, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.79, "=": 2.79,
">": 2.79, "?": 2.12, "@": 3.39, "A": 2.82, "B": 2.82,
"C": 3.06, "D": 3.06, "E": 2.59, "F": 2.35, "G": 3.29,
"H": 3.06, "I": 1.18, "J": 2.12, "K": 2.82, "L": 2.35,
"M": 3.53, "N": 3.06, "O": 3.29, "P": 2.59, "Q": 3.29,
"R": 2.82, "S": 2.59, "T": 2.35, "U": 3.06, "V": 2.59,
"W": 3.76, "X": 2.59, "Y": 2.59, "Z": 2.59, "[": 1.41,
"\\": 1.18, "]": 1.41, "^": 2.79, "_": 2.12, "`": 1.41,
"a": 2.35, "b": 2.59, "c": 2.35, "d": 2.59, "e": 2.35,
"f": 1.18, "g": 2.59, "h": 2.35, "i": 0.94, "j": 0.94,
"k": 2.12, "l": 0.94, "m": 3.53, "n": 2.35, "o": 2.35,
"p": 2.59, "q": 2.59, "r": 1.41, "s": 2.12, "t": 1.18,
"u": 2.35, "v": 2.12, "w": 3.06, "x": 2.12, "y": 2.12,
"z": 2.12, "{": 1.41, "|": 0.94, "}": 1.41, "~": 2.79
},
"height": 4.23
},
"Helvetica Light Oblique": {
"widths": {
" ": 1.18, "!": 1.41, "\"": 1.18, "#": 2.35, "$": 2.35,
"%": 3.76, "&": 2.82, "'": 0.94, "(": 1.41, ")": 1.41,
"*": 1.65, "+": 2.79, ",": 1.18, "-": 1.41, ".": 1.18,
"/": 1.18, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.79, "=": 2.79,
">": 2.79, "?": 2.12, "@": 3.39, "A": 2.82, "B": 2.82,
"C": 3.06, "D": 3.06, "E": 2.59, "F": 2.35, "G": 3.29,
"H": 3.06, "I": 1.18, "J": 2.12, "K": 2.82, "L": 2.35,
"M": 3.53, "N": 3.06, "O": 3.29, "P": 2.59, "Q": 3.29,
"R": 2.82, "S": 2.59, "T": 2.35, "U": 3.06, "V": 2.59,
"W": 3.76, "X": 2.59, "Y": 2.59, "Z": 2.59, "[": 1.41,
"\\": 1.18, "]": 1.41, "^": 2.79, "_": 2.12, "`": 1.41,
"a": 2.35, "b": 2.59, "c": 2.35, "d": 2.59, "e": 2.35,
"f": 1.18, "g": 2.59, "h": 2.35, "i": 0.94, "j": 0.94,
"k": 2.12, "l": 0.94, "m": 3.53, "n": 2.35, "o": 2.35,
"p": 2.59, "q": 2.59, "r": 1.41, "s": 2.12, "t": 1.18,
"u": 2.35, "v": 2.12, "w": 3.06, "x": 2.12, "y": 2.12,
"z": 2.12, "{": 1.41, "|": 1.70, "}": 1.41, "~": 2.79
},
"height": 4.63
},
"Arial": {
"widths": {
" ": 1.18, "!": 1.18, "\"": 1.50, "#": 2.35, "$": 2.35,
"%": 3.76, "&": 2.82, "'": 0.81, "(": 1.41, ")": 1.41,
"*": 1.65, "+": 2.47, ",": 1.18, "-": 1.41, ".": 1.18,
"/": 1.18, "0": 2.35, "1": 2.35, "2": 2.35, "3": 2.35,
"4": 2.35, "5": 2.35, "6": 2.35, "7": 2.35, "8": 2.35,
"9": 2.35, ":": 1.18, ";": 1.18, "<": 2.47, "=": 2.47,
">": 2.47, "?": 2.35, "@": 4.30, "A": 2.82, "B": 2.82,
"C": 3.06, "D": 3.06, "E": 2.82, "F": 2.59, "G": 3.29,
"H": 3.06, "I": 1.18, "J": 2.12, "K": 2.82, "L": 2.35,
"M": 3.53, "N": 3.06, "O": 3.29, "P": 2.82, "Q": 3.29,
"R": 3.06, "S": 2.82, "T": 2.59, "U": 3.06, "V": 2.82,
"W": 4.00, "X": 2.82, "Y": 2.82, "Z": 2.59, "[": 1.18,
"\\": 1.18, "]": 1.18, "^": 1.99, "_": 2.35, "`": 1.41,
"a": 2.35, "b": 2.35, "c": 2.12, "d": 2.35, "e": 2.35,
"f": 1.18, "g": 2.35, "h": 2.35, "i": 0.94, "j": 0.94,
"k": 2.12, "l": 0.94, "m": 3.53, "n": 2.35, "o": 2.35,
"p": 2.35, "q": 2.35, "r": 1.41, "s": 2.12, "t": 1.18,
"u": 2.35, "v": 2.12, "w": 3.06, "x": 2.12, "y": 2.12,
"z": 2.12, "{": 1.41, "|": 1.10, "}": 1.41, "~": 2.47
},
"height": 3.98
},
"PT Sans": {
"widths": {
" ": 1.13, "!": 1.29, "\"": 1.42, "#": 2.31, "$": 2.31,
"%": 3.27, "&": 3.45, "'": 0.92, "(": 1.19, ")": 1.19,
"*": 1.49, "+": 2.14, ",": 0.82, "-": 1.52, ".": 0.91,
"/": 1.50, "0": 2.31, "1": 2.31, "2": 2.31, "3": 2.31,
"4": 2.31, "5": 2.31, "6": 2.31, "7": 2.31, "8": 2.31,
"9": 2.31, ":": 0.93, ";": 1.08, "<": 2.14, "=": 2.14,
">": 2.14, "?": 1.85, "@": 4.50, "A": 2.48, "B": 2.47,
"C": 2.42, "D": 2.77, "E": 2.27, "F": 2.19, "G": 2.59,
"H": 2.85, "I": 1.23, "J": 1.23, "K": 2.58, "L": 2.19,
"M": 3.35, "N": 2.85, "O": 2.90, "P": 2.37, "Q": 2.90,
"R": 2.52, "S": 2.25, "T": 2.35, "U": 2.76, "V": 2.40,
"W": 3.50, "X": 2.62, "Y": 2.36, "Z": 2.31, "[": 1.29,
"\\": 1.61, "]": 1.29, "^": 2.12, "_": 1.73, "`": 1.19,
"a": 2.10, "b": 2.29, "c": 1.91, "d": 2.28, "e": 2.15,
"f": 1.35, "g": 2.27, "h": 2.31, "i": 1.13, "j": 1.13,
"k": 2.03, "l": 1.24, "m": 3.44, "n": 2.31, "o": 2.27,
"p": 2.29, "q": 2.27, "r": 1.44, "s": 1.78, "t": 1.44,
"u": 2.28, "v": 2.04, "w": 3.11, "x": 2.18, "y": 1.97,
"z": 1.89, "{": 1.47, "|": 1.01, "}": 1.47, "~": 2.14
},
"height": 3.94
},
"PT Sans Italic": {
"widths": {
" ": 1.13, "!": 1.16, "\"": 1.28, "#": 2.20, "$": 2.20,
"%": 3.12, "&": 3.27, "'": 0.85, "(": 1.13, ")": 1.13,
"*": 1.41, "+": 2.03, ",": 0.79, "-": 1.45, ".": 0.89,
"/": 1.42, "0": 2.20, "1": 2.20, "2": 2.20, "3": 2.20,
"4": 2.20, "5": 2.20, "6": 2.20, "7": 2.20, "8": 2.20,
"9": 2.20, ":": 1.13, ";": 1.16, "<": 2.03, "=": 2.03,
">": 2.03, "?": 1.75, "@": 4.50, "A": 2.36, "B": 2.35,
"C": 2.30, "D": 2.63, "E": 2.16, "F": 2.08, "G": 2.47,
"H": 2.71, "I": 1.17, "J": 1.18, "K": 2.44, "L": 2.08,
"M": 3.19, "N": 2.72, "O": 2.76, "P": 2.25, "Q": 2.76,
"R": 2.40, "S": 2.14, "T": 2.23, "U": 2.62, "V": 2.29,
"W": 3.34, "X": 2.49, "Y": 2.25, "Z": 2.20, "[": 1.23,
"\\": 1.61, "]": 1.24, "^": 2.12, "_": 1.73, "`": 1.01,
"a": 2.06, "b": 2.21, "c": 1.78, "d": 2.15, "e": 1.96,
"f": 1.18, "g": 2.14, "h": 2.24, "i": 1.10, "j": 1.05,
"k": 1.90, "l": 1.14, "m": 3.23, "n": 2.21, "o": 2.11,
"p": 2.15, "q": 2.13, "r": 1.38, "s": 1.69, "t": 1.32,
"u": 2.16, "v": 1.89, "w": 2.90, "x": 2.05, "y": 1.86,
"z": 1.82, "{": 1.38, "|": 1.01, "}": 1.40, "~": 2.03
},
"height": 3.94
},
"PT Sans Narrow Bold": {
"widths": {
" ": 0.87, "!": 1.06, "\"": 1.49, "#": 2.02, "$": 2.02,
"%": 3.05, "&": 2.84, "'": 0.92, "(": 1.18, ")": 1.18,
"*": 1.37, "+": 1.88, ",": 0.83, "-": 1.26, ".": 0.81,
"/": 1.48, "0": 2.02, "1": 2.02, "2": 2.02, "3": 2.02,
"4": 2.02, "5": 2.02, "6": 2.02, "7": 2.02, "8": 2.02,
"9": 2.02, ":": 1.06, ";": 1.06, "<": 1.88, "=": 1.88,
">": 1.88, "?": 1.62, "@": 3.73, "A": 2.12, "B": 2.07,
"C": 1.93, "D": 2.27, "E": 1.82, "F": 1.77, "G": 2.12,
"H": 2.26, "I": 1.01, "J": 1.22, "K": 2.20, "L": 1.79,
"M": 2.81, "N": 2.29, "O": 2.34, "P": 2.02, "Q": 2.34,
"R": 2.13, "S": 1.86, "T": 2.00, "U": 2.18, "V": 2.13,
"W": 3.04, "X": 2.23, "Y": 2.10, "Z": 1.88, "[": 1.17,
"\\": 1.53, "]": 1.16, "^": 1.81, "_": 1.58, "`": 1.23,
"a": 1.75, "b": 1.88, "c": 1.48, "d": 1.88, "e": 1.81,
"f": 1.13, "g": 1.88, "h": 1.90, "i": 0.95, "j": 0.95,
"k": 1.74, "l": 1.03, "m": 2.81, "n": 1.90, "o": 1.88,
"p": 1.89, "q": 1.88, "r": 1.24, "s": 1.48, "t": 1.23,
"u": 1.89, "v": 1.69, "w": 2.52, "x": 1.86, "y": 1.69,
"z": 1.61, "{": 1.32, "|": 0.80, "}": 1.32, "~": 1.88
},
"height": 3.94
},
"PT Sans Narrow": {
"widths": {
" ": 0.90, "!": 1.05, "\"": 1.21, "#": 1.91, "$": 1.91,
"%": 2.70, "&": 2.78, "'": 0.77, "(": 0.99, ")": 0.99,
"*": 1.23, "+": 1.76, ",": 0.69, "-": 1.23, ".": 0.66,
"/": 1.25, "0": 1.91, "1": 1.91, "2": 1.91, "3": 1.91,
"4": 1.91, "5": 1.91, "6": 1.91, "7": 1.91, "8": 1.91,
"9": 1.91, ":": 0.80, ";": 0.91, "<": 1.76, "=": 1.76,
">": 1.76, "?": 1.51, "@": 3.63, "A": 2.00, "B": 1.99,
"C": 1.94, "D": 2.22, "E": 1.82, "F": 1.75, "G": 2.08,
"H": 2.27, "I": 0.99, "J": 1.02, "K": 2.09, "L": 1.76,
"M": 2.70, "N": 2.28, "O": 2.32, "P": 1.91, "Q": 2.32,
"R": 2.03, "S": 1.81, "T": 1.89, "U": 2.21, "V": 1.96,
"W": 2.85, "X": 2.12, "Y": 1.93, "Z": 1.86, "[": 1.05,
"\\": 1.34, "]": 1.05, "^": 1.74, "_": 1.41, "`": 1.08,
"a": 1.69, "b": 1.84, "c": 1.51, "d": 1.83, "e": 1.75,
"f": 1.09, "g": 1.83, "h": 1.86, "i": 0.92, "j": 0.91,
"k": 1.64, "l": 0.99, "m": 2.76, "n": 1.86, "o": 1.83,
"p": 1.84, "q": 1.83, "r": 1.16, "s": 1.43, "t": 1.16,
"u": 1.84, "v": 1.64, "w": 2.50, "x": 1.74, "y": 1.59,
"z": 1.52, "{": 1.19, "|": 0.80, "}": 1.19, "~": 1.76
},
"height": 3.94
},
"PT Sans Caption Bold": {
"widths": {
" ": 1.17, "!": 1.33, "\"": 1.85, "#": 2.50, "$": 2.50,
"%": 3.84, "&": 3.75, "'": 1.17, "(": 1.51, ")": 1.50,
"*": 1.73, "+": 2.41, ",": 1.05, "-": 1.66, ".": 1.02,
"/": 1.88, "0": 2.50, "1": 2.50, "2": 2.50, "3": 2.50,
"4": 2.50, "5": 2.50, "6": 2.50, "7": 2.50, "8": 2.50,
"9": 2.50, ":": 1.24, ";": 1.19, "<": 2.42, "=": 2.42,
">": 2.42, "?": 2.08, "@": 4.86, "A": 2.79, "B": 2.71,
"C": 2.57, "D": 2.97, "E": 2.40, "F": 2.33, "G": 2.80,
"H": 2.99, "I": 1.64, "J": 1.53, "K": 2.84, "L": 2.36,
"M": 3.67, "N": 3.02, "O": 3.08, "P": 2.62, "Q": 3.08,
"R": 2.76, "S": 2.43, "T": 2.61, "U": 2.87, "V": 2.77,
"W": 3.97, "X": 2.90, "Y": 2.73, "Z": 2.47, "[": 1.48,
"\\": 1.95, "]": 1.48, "^": 2.27, "_": 2.04, "`": 1.48,
"a": 2.45, "b": 2.62, "c": 2.12, "d": 2.66, "e": 2.51,
"f": 1.57, "g": 2.62, "h": 2.70, "i": 1.34, "j": 1.34,
"k": 2.39, "l": 1.43, "m": 3.98, "n": 2.70, "o": 2.61,
"p": 2.64, "q": 2.62, "r": 1.72, "s": 2.04, "t": 1.71,
"u": 2.72, "v": 2.31, "w": 3.49, "x": 2.48, "y": 2.29,
"z": 2.23, "{": 1.71, "|": 1.04, "}": 1.71, "~": 2.42
},
"height": 3.99
},
"PT Sans Caption": {
"widths": {
" ": 1.23, "!": 1.40, "\"": 1.59, "#": 2.51, "$": 2.51,
"%": 3.62, "&": 3.77, "'": 1.03, "(": 1.33, ")": 1.32,
"*": 1.64, "+": 2.35, ",": 0.93, "-": 1.67, ".": 1.01,
"/": 1.68, "0": 2.51, "1": 2.51, "2": 2.51, "3": 2.51,
"4": 2.51, "5": 2.51, "6": 2.51, "7": 2.51, "8": 2.51,
"9": 2.51, ":": 1.16, ";": 1.17, "<": 2.35, "=": 2.35,
">": 2.35, "?": 2.03, "@": 4.92, "A": 2.73, "B": 2.71,
"C": 2.64, "D": 3.03, "E": 2.48, "F": 2.39, "G": 2.83,
"H": 3.10, "I": 1.69, "J": 1.38, "K": 2.83, "L": 2.40,
"M": 3.67, "N": 3.11, "O": 3.16, "P": 2.60, "Q": 3.16,
"R": 2.76, "S": 2.46, "T": 2.58, "U": 3.00, "V": 2.66,
"W": 3.87, "X": 2.87, "Y": 2.61, "Z": 2.52, "[": 1.42,
"\\": 1.78, "]": 1.42, "^": 2.35, "_": 1.91, "`": 1.27,
"a": 2.46, "b": 2.66, "c": 2.24, "d": 2.66, "e": 2.53,
"f": 1.54, "g": 2.65, "h": 2.71, "i": 1.34, "j": 1.32,
"k": 2.36, "l": 1.42, "m": 4.01, "n": 2.71, "o": 2.67,
"p": 2.67, "q": 2.65, "r": 1.61, "s": 2.11, "t": 1.71,
"u": 2.73, "v": 2.27, "w": 3.56, "x": 2.51, "y": 2.25,
"z": 2.18, "{": 1.62, "|": 1.09, "}": 1.62, "~": 2.35
},
"height": 4.01
},
"PT Sans Bold Italic": {
"widths": {
" ": 1.07, "!": 1.20, "\"": 1.50, "#": 2.31, "$": 2.31,
"%": 3.40, "&": 3.31, "'": 0.92, "(": 1.31, ")": 1.31,
"*": 1.51, "+": 2.14, ",": 0.91, "-": 1.45, ".": 1.06,
"/": 1.64, "0": 2.31, "1": 2.31, "2": 2.31, "3": 2.31,
"4": 2.31, "5": 2.31, "6": 2.31, "7": 2.31, "8": 2.31,
"9": 2.31, ":": 1.33, ";": 1.30, "<": 2.14, "=": 2.14,
">": 2.14, "?": 1.82, "@": 4.48, "A": 2.46, "B": 2.40,
"C": 2.27, "D": 2.62, "E": 2.13, "F": 2.07, "G": 2.48,
"H": 2.64, "I": 1.18, "J": 1.37, "K": 2.51, "L": 2.10,
"M": 3.25, "N": 2.67, "O": 2.73, "P": 2.33, "Q": 2.73,
"R": 2.47, "S": 2.16, "T": 2.31, "U": 2.55, "V": 2.45,
"W": 3.50, "X": 2.57, "Y": 2.41, "Z": 2.19, "[": 1.33,
"\\": 1.79, "]": 1.32, "^": 2.14, "_": 1.88, "`": 1.01,
"a": 2.13, "b": 2.17, "c": 1.74, "d": 2.15, "e": 1.97,
"f": 1.25, "g": 2.14, "h": 2.23, "i": 1.08, "j": 1.03,
"k": 1.97, "l": 1.15, "m": 3.25, "n": 2.21, "o": 2.10,
"p": 2.14, "q": 2.12, "r": 1.45, "s": 1.68, "t": 1.35,
"u": 2.17, "v": 1.90, "w": 2.87, "x": 2.10, "y": 1.91,
"z": 1.84, "{": 1.51, "|": 0.98, "}": 1.52, "~": 2.14
},
"height": 3.94
},
"PT Sans Bold": {
"widths": {
" ": 1.07, "!": 1.25, "\"": 1.70, "#": 2.40, "$": 2.40,
"%": 3.56, "&": 3.45, "'": 1.07, "(": 1.38, ")": 1.38,
"*": 1.60, "+": 2.23, ",": 0.96, "-": 1.52, ".": 1.04,
"/": 1.73, "0": 2.40, "1": 2.40, "2": 2.40, "3": 2.40,
"4": 2.40, "5": 2.40, "6": 2.40, "7": 2.40, "8": 2.40,
"9": 2.40, ":": 1.14, ";": 1.23, "<": 2.23, "=": 2.23,
">": 2.23, "?": 1.92, "@": 4.48, "A": 2.56, "B": 2.50,
"C": 2.37, "D": 2.74, "E": 2.21, "F": 2.15, "G": 2.58,
"H": 2.76, "I": 1.21, "J": 1.41, "K": 2.62, "L": 2.18,
"M": 3.39, "N": 2.78, "O": 2.84, "P": 2.42, "Q": 2.84,
"R": 2.55, "S": 2.24, "T": 2.40, "U": 2.65, "V": 2.55,
"W": 3.65, "X": 2.68, "Y": 2.51, "Z": 2.28, "[": 1.37,
"\\": 1.79, "]": 1.37, "^": 2.12, "_": 1.88, "`": 1.34,
"a": 2.10, "b": 2.27, "c": 1.83, "d": 2.28, "e": 2.15,
"f": 1.36, "g": 2.27, "h": 2.31, "i": 1.14, "j": 1.13,
"k": 2.08, "l": 1.25, "m": 3.41, "n": 2.31, "o": 2.27,
"p": 2.29, "q": 2.27, "r": 1.49, "s": 1.79, "t": 1.48,
"u": 2.28, "v": 2.02, "w": 3.05, "x": 2.22, "y": 2.02,
"z": 1.94, "{": 1.57, "|": 0.96, "}": 1.57, "~": 2.23
},
"height": 3.94
},
"Source Sans Pro": {
"widths": {
" ": 0.85, "!": 1.22, "\"": 1.80, "#": 2.10, "$": 2.10,
"%": 3.49, "&": 2.58, "'": 1.05, "(": 1.28, ")": 1.28,
"*": 1.77, "+": 2.10, ",": 1.05, "-": 1.32, ".": 1.05,
"/": 1.48, "0": 2.10, "1": 2.10, "2": 2.10, "3": 2.10,
"4": 2.10, "5": 2.10, "6": 2.10, "7": 2.10, "8": 2.10,
"9": 2.10, ":": 1.05, ";": 1.05, "<": 2.10, "=": 2.10,
">": 2.10, "?": 1.80, "@": 3.59, "A": 2.28, "B": 2.47,
"C": 2.40, "D": 2.58, "E": 2.21, "F": 2.07, "G": 2.59,
"H": 2.74, "I": 1.09, "J": 2.01, "K": 2.43, "L": 2.04,
"M": 3.06, "N": 2.72, "O": 2.79, "P": 2.42, "Q": 2.79,
"R": 2.44, "S": 2.24, "T": 2.25, "U": 2.71, "V": 2.16,
"W": 3.31, "X": 2.15, "Y": 1.99, "Z": 2.26, "[": 1.28,
"\\": 1.48, "]": 1.28, "^": 2.10, "_": 2.12, "`": 2.29,
"a": 2.17, "b": 2.35, "c": 1.93, "d": 2.35, "e": 2.11,
"f": 1.24, "g": 2.13, "h": 2.30, "i": 1.04, "j": 1.05,
"k": 2.10, "l": 1.08, "m": 3.51, "n": 2.32, "o": 2.29,
"p": 2.35, "q": 2.33, "r": 1.47, "s": 1.77, "t": 1.43,
"u": 2.32, "v": 1.98, "w": 3.04, "x": 1.89, "y": 1.98,
"z": 1.80, "{": 1.28, "|": 1.02, "}": 1.28, "~": 2.10
},
"height": 4.23
}}
================================================
FILE: deps/mkfile
================================================
# Mkfile for updating the glyphsize table. This is not intended for general use.
# If you really want to use it, you'll probably have to change FONTS to point to
# the font files you want to serialize, then obtain a copy of mk, either from
# plan9port, or from github.com/dcjones/mk. Then just type 'mk'.
all:V: glyphsize.json
FONTS=/System/Library/Fonts/HelveticaNeue.dfont \
/System/Library/Fonts/Helvetica.dfont \
/Library/Fonts/Microsoft/Arial.ttf \
/Library/Fonts/PTSans.ttc \
/Users/dcjones/Library/Fonts/SourceSansPro-Regular.otf
glyphsize.json: glyphsize $FONTS
./glyphsize $FONTS > $target
CFLAGS=-Wall -g -I/usr/local/include/freetype2
glyphsize: glyphsize.c
gcc $CFLAGS -o $target $prereq -lfreetype
clean:V:
rm -f glyphsize
# Uglifyjs outputs a bunch of non-ascii characters that cause problems
# when embedded in an svg file, so use closure-complier.
snap.svg-min.js: /Users/dcjones/src/Snap.svg-0.3.0/dist/snap.svg.js
closure-compiler $prereq > $target
================================================
FILE: deps/snap.svg-min.js
================================================
(function(N){var k=/[\.\/]/,L=/\s*,\s*/,C=function(a,d){return a-d},a,v,y={n:{}},M=function(){for(var a=0,d=this.length;a<d;a++)if("undefined"!=typeof this[a])return this[a]},A=function(){for(var a=this.length;--a;)if("undefined"!=typeof this[a])return this[a]},w=function(k,d){k=String(k);var f=v,n=Array.prototype.slice.call(arguments,2),u=w.listeners(k),p=0,b,q=[],e={},l=[],r=a;l.firstDefined=M;l.lastDefined=A;a=k;for(var s=v=0,x=u.length;s<x;s++)"zIndex"in u[s]&&(q.push(u[s].zIndex),0>u[s].zIndex&&
(e[u[s].zIndex]=u[s]));for(q.sort(C);0>q[p];)if(b=e[q[p++]],l.push(b.apply(d,n)),v)return v=f,l;for(s=0;s<x;s++)if(b=u[s],"zIndex"in b)if(b.zIndex==q[p]){l.push(b.apply(d,n));if(v)break;do if(p++,(b=e[q[p]])&&l.push(b.apply(d,n)),v)break;while(b)}else e[b.zIndex]=b;else if(l.push(b.apply(d,n)),v)break;v=f;a=r;return l};w._events=y;w.listeners=function(a){a=a.split(k);var d=y,f,n,u,p,b,q,e,l=[d],r=[];u=0;for(p=a.length;u<p;u++){e=[];b=0;for(q=l.length;b<q;b++)for(d=l[b].n,f=[d[a[u]],d["*"]],n=2;n--;)if(d=
f[n])e.push(d),r=r.concat(d.f||[]);l=e}return r};w.on=function(a,d){a=String(a);if("function"!=typeof d)return function(){};for(var f=a.split(L),n=0,u=f.length;n<u;n++)(function(a){a=a.split(k);for(var b=y,f,e=0,l=a.length;e<l;e++)b=b.n,b=b.hasOwnProperty(a[e])&&b[a[e]]||(b[a[e]]={n:{}});b.f=b.f||[];e=0;for(l=b.f.length;e<l;e++)if(b.f[e]==d){f=!0;break}!f&&b.f.push(d)})(f[n]);return function(a){+a==+a&&(d.zIndex=+a)}};w.f=function(a){var d=[].slice.call(arguments,1);return function(){w.apply(null,
[a,null].concat(d).concat([].slice.call(arguments,0)))}};w.stop=function(){v=1};w.nt=function(k){return k?(new RegExp("(?:\\.|\\/|^)"+k+"(?:\\.|\\/|$)")).test(a):a};w.nts=function(){return a.split(k)};w.off=w.unbind=function(a,d){if(a){var f=a.split(L);if(1<f.length)for(var n=0,u=f.length;n<u;n++)w.off(f[n],d);else{for(var f=a.split(k),p,b,q,e,l=[y],n=0,u=f.length;n<u;n++)for(e=0;e<l.length;e+=q.length-2){q=[e,1];p=l[e].n;if("*"!=f[n])p[f[n]]&&q.push(p[f[n]]);else for(b in p)p.hasOwnProperty(b)&&
q.push(p[b]);l.splice.apply(l,q)}n=0;for(u=l.length;n<u;n++)for(p=l[n];p.n;){if(d){if(p.f){e=0;for(f=p.f.length;e<f;e++)if(p.f[e]==d){p.f.splice(e,1);break}!p.f.length&&delete p.f}for(b in p.n)if(p.n.hasOwnProperty(b)&&p.n[b].f){q=p.n[b].f;e=0;for(f=q.length;e<f;e++)if(q[e]==d){q.splice(e,1);break}!q.length&&delete p.n[b].f}}else for(b in delete p.f,p.n)p.n.hasOwnProperty(b)&&p.n[b].f&&delete p.n[b].f;p=p.n}}}else w._events=y={n:{}}};w.once=function(a,d){var f=function(){w.unbind(a,f);return d.apply(this,
arguments)};return w.on(a,f)};w.version="0.4.2";w.toString=function(){return"You are running Eve 0.4.2"};"undefined"!=typeof module&&module.exports?module.exports=w:"function"===typeof define&&define.amd?define("eve",[],function(){return w}):N.eve=w})(this);
(function(N,k){"function"===typeof define&&define.amd?define("Snap.svg",["eve"],function(L){return k(N,L)}):k(N,N.eve)})(this,function(N,k){var L=function(a){var k={},y=N.requestAnimationFrame||N.webkitRequestAnimationFrame||N.mozRequestAnimationFrame||N.oRequestAnimationFrame||N.msRequestAnimationFrame||function(a){setTimeout(a,16)},M=Array.isArray||function(a){return a instanceof Array||"[object Array]"==Object.prototype.toString.call(a)},A=0,w="M"+(+new Date).toString(36),z=function(a){if(null==
a)return this.s;var b=this.s-a;this.b+=this.dur*b;this.B+=this.dur*b;this.s=a},d=function(a){if(null==a)return this.spd;this.spd=a},f=function(a){if(null==a)return this.dur;this.s=this.s*a/this.dur;this.dur=a},n=function(){delete k[this.id];this.update();a("mina.stop."+this.id,this)},u=function(){this.pdif||(delete k[this.id],this.update(),this.pdif=this.get()-this.b)},p=function(){this.pdif&&(this.b=this.get()-this.pdif,delete this.pdif,k[this.id]=this)},b=function(){var a;if(M(this.start)){a=[];
for(var b=0,e=this.start.length;b<e;b++)a[b]=+this.start[b]+(this.end[b]-this.start[b])*this.easing(this.s)}else a=+this.start+(this.end-this.start)*this.easing(this.s);this.set(a)},q=function(){var l=0,b;for(b in k)if(k.hasOwnProperty(b)){var e=k[b],f=e.get();l++;e.s=(f-e.b)/(e.dur/e.spd);1<=e.s&&(delete k[b],e.s=1,l--,function(b){setTimeout(function(){a("mina.finish."+b.id,b)})}(e));e.update()}l&&y(q)},e=function(a,r,s,x,G,h,J){a={id:w+(A++).toString(36),start:a,end:r,b:s,s:0,dur:x-s,spd:1,get:G,
set:h,easing:J||e.linear,status:z,speed:d,duration:f,stop:n,pause:u,resume:p,update:b};k[a.id]=a;r=0;for(var K in k)if(k.hasOwnProperty(K)&&(r++,2==r))break;1==r&&y(q);return a};e.time=Date.now||function(){return+new Date};e.getById=function(a){return k[a]||null};e.linear=function(a){return a};e.easeout=function(a){return Math.pow(a,1.7)};e.easein=function(a){return Math.pow(a,0.48)};e.easeinout=function(a){if(1==a)return 1;if(0==a)return 0;var b=0.48-a/1.04,e=Math.sqrt(0.1734+b*b);a=e-b;a=Math.pow(Math.abs(a),
1/3)*(0>a?-1:1);b=-e-b;b=Math.pow(Math.abs(b),1/3)*(0>b?-1:1);a=a+b+0.5;return 3*(1-a)*a*a+a*a*a};e.backin=function(a){return 1==a?1:a*a*(2.70158*a-1.70158)};e.backout=function(a){if(0==a)return 0;a-=1;return a*a*(2.70158*a+1.70158)+1};e.elastic=function(a){return a==!!a?a:Math.pow(2,-10*a)*Math.sin(2*(a-0.075)*Math.PI/0.3)+1};e.bounce=function(a){a<1/2.75?a*=7.5625*a:a<2/2.75?(a-=1.5/2.75,a=7.5625*a*a+0.75):a<2.5/2.75?(a-=2.25/2.75,a=7.5625*a*a+0.9375):(a-=2.625/2.75,a=7.5625*a*a+0.984375);return a};
return N.mina=e}("undefined"==typeof k?function(){}:k),C=function(){function a(c,t){if(c){if(c.tagName)return x(c);if(y(c,"array")&&a.set)return a.set.apply(a,c);if(c instanceof e)return c;if(null==t)return c=G.doc.querySelector(c),x(c)}return new s(null==c?"100%":c,null==t?"100%":t)}function v(c,a){if(a){"#text"==c&&(c=G.doc.createTextNode(a.text||""));"string"==typeof c&&(c=v(c));if("string"==typeof a)return"xlink:"==a.substring(0,6)?c.getAttributeNS(m,a.substring(6)):"xml:"==a.substring(0,4)?c.getAttributeNS(la,
a.substring(4)):c.getAttribute(a);for(var da in a)if(a[h](da)){var b=J(a[da]);b?"xlink:"==da.substring(0,6)?c.setAttributeNS(m,da.substring(6),b):"xml:"==da.substring(0,4)?c.setAttributeNS(la,da.substring(4),b):c.setAttribute(da,b):c.removeAttribute(da)}}else c=G.doc.createElementNS(la,c);return c}function y(c,a){a=J.prototype.toLowerCase.call(a);return"finite"==a?isFinite(c):"array"==a&&(c instanceof Array||Array.isArray&&Array.isArray(c))?!0:"null"==a&&null===c||a==typeof c&&null!==c||"object"==
a&&c===Object(c)||$.call(c).slice(8,-1).toLowerCase()==a}function M(c){if("function"==typeof c||Object(c)!==c)return c;var a=new c.constructor,b;for(b in c)c[h](b)&&(a[b]=M(c[b]));return a}function A(c,a,b){function m(){var e=Array.prototype.slice.call(arguments,0),f=e.join("\u2400"),d=m.cache=m.cache||{},l=m.count=m.count||[];if(d[h](f)){a:for(var e=l,l=f,B=0,H=e.length;B<H;B++)if(e[B]===l){e.push(e.splice(B,1)[0]);break a}return b?b(d[f]):d[f]}1E3<=l.length&&delete d[l.shift()];l.push(f);d[f]=c.apply(a,
e);return b?b(d[f]):d[f]}return m}function w(c,a,b,m,e,f){return null==e?(c-=b,a-=m,c||a?(180*I.atan2(-a,-c)/C+540)%360:0):w(c,a,e,f)-w(b,m,e,f)}function z(c){return c%360*C/180}function d(c){var a=[];c=c.replace(/(?:^|\s)(\w+)\(([^)]+)\)/g,function(c,b,m){m=m.split(/\s*,\s*|\s+/);"rotate"==b&&1==m.length&&m.push(0,0);"scale"==b&&(2<m.length?m=m.slice(0,2):2==m.length&&m.push(0,0),1==m.length&&m.push(m[0],0,0));"skewX"==b?a.push(["m",1,0,I.tan(z(m[0])),1,0,0]):"skewY"==b?a.push(["m",1,I.tan(z(m[0])),
0,1,0,0]):a.push([b.charAt(0)].concat(m));return c});return a}function f(c,t){var b=O(c),m=new a.Matrix;if(b)for(var e=0,f=b.length;e<f;e++){var h=b[e],d=h.length,B=J(h[0]).toLowerCase(),H=h[0]!=B,l=H?m.invert():0,E;"t"==B&&2==d?m.translate(h[1],0):"t"==B&&3==d?H?(d=l.x(0,0),B=l.y(0,0),H=l.x(h[1],h[2]),l=l.y(h[1],h[2]),m.translate(H-d,l-B)):m.translate(h[1],h[2]):"r"==B?2==d?(E=E||t,m.rotate(h[1],E.x+E.width/2,E.y+E.height/2)):4==d&&(H?(H=l.x(h[2],h[3]),l=l.y(h[2],h[3]),m.rotate(h[1],H,l)):m.rotate(h[1],
h[2],h[3])):"s"==B?2==d||3==d?(E=E||t,m.scale(h[1],h[d-1],E.x+E.width/2,E.y+E.height/2)):4==d?H?(H=l.x(h[2],h[3]),l=l.y(h[2],h[3]),m.scale(h[1],h[1],H,l)):m.scale(h[1],h[1],h[2],h[3]):5==d&&(H?(H=l.x(h[3],h[4]),l=l.y(h[3],h[4]),m.scale(h[1],h[2],H,l)):m.scale(h[1],h[2],h[3],h[4])):"m"==B&&7==d&&m.add(h[1],h[2],h[3],h[4],h[5],h[6])}return m}function n(c,t){if(null==t){var m=!0;t="linearGradient"==c.type||"radialGradient"==c.type?c.node.getAttribute("gradientTransform"):"pattern"==c.type?c.node.getAttribute("patternTransform"):
c.node.getAttribute("transform");if(!t)return new a.Matrix;t=d(t)}else t=a._.rgTransform.test(t)?J(t).replace(/\.{3}|\u2026/g,c._.transform||aa):d(t),y(t,"array")&&(t=a.path?a.path.toString.call(t):J(t)),c._.transform=t;var b=f(t,c.getBBox(1));if(m)return b;c.matrix=b}function u(c){c=c.node.ownerSVGElement&&x(c.node.ownerSVGElement)||c.node.parentNode&&x(c.node.parentNode)||a.select("svg")||a(0,0);var t=c.select("defs"),t=null==t?!1:t.node;t||(t=r("defs",c.node).node);return t}function p(c){return c.node.ownerSVGElement&&
x(c.node.ownerSVGElement)||a.select("svg")}function b(c,a,m){function b(c){if(null==c)return aa;if(c==+c)return c;v(B,{width:c});try{return B.getBBox().width}catch(a){return 0}}function h(c){if(null==c)return aa;if(c==+c)return c;v(B,{height:c});try{return B.getBBox().height}catch(a){return 0}}function e(b,B){null==a?d[b]=B(c.attr(b)||0):b==a&&(d=B(null==m?c.attr(b)||0:m))}var f=p(c).node,d={},B=f.querySelector(".svg---mgr");B||(B=v("rect"),v(B,{x:-9E9,y:-9E9,width:10,height:10,"class":"svg---mgr",
fill:"none"}),f.appendChild(B));switch(c.type){case "rect":e("rx",b),e("ry",h);case "image":e("width",b),e("height",h);case "text":e("x",b);e("y",h);break;case "circle":e("cx",b);e("cy",h);e("r",b);break;case "ellipse":e("cx",b);e("cy",h);e("rx",b);e("ry",h);break;case "line":e("x1",b);e("x2",b);e("y1",h);e("y2",h);break;case "marker":e("refX",b);e("markerWidth",b);e("refY",h);e("markerHeight",h);break;case "radialGradient":e("fx",b);e("fy",h);break;case "tspan":e("dx",b);e("dy",h);break;default:e(a,
b)}f.removeChild(B);return d}function q(c){y(c,"array")||(c=Array.prototype.slice.call(arguments,0));for(var a=0,b=0,m=this.node;this[a];)delete this[a++];for(a=0;a<c.length;a++)"set"==c[a].type?c[a].forEach(function(c){m.appendChild(c.node)}):m.appendChild(c[a].node);for(var h=m.childNodes,a=0;a<h.length;a++)this[b++]=x(h[a]);return this}function e(c){if(c.snap in E)return E[c.snap];var a=this.id=V(),b;try{b=c.ownerSVGElement}catch(m){}this.node=c;b&&(this.paper=new s(b));this.type=c.tagName;this.anims=
{};this._={transform:[]};c.snap=a;E[a]=this;"g"==this.type&&(this.add=q);if(this.type in{g:1,mask:1,pattern:1})for(var e in s.prototype)s.prototype[h](e)&&(this[e]=s.prototype[e])}function l(c){this.node=c}function r(c,a){var b=v(c);a.appendChild(b);return x(b)}function s(c,a){var b,m,f,d=s.prototype;if(c&&"svg"==c.tagName){if(c.snap in E)return E[c.snap];var l=c.ownerDocument;b=new e(c);m=c.getElementsByTagName("desc")[0];f=c.getElementsByTagName("defs")[0];m||(m=v("desc"),m.appendChild(l.createTextNode("Created with Snap")),
b.node.appendChild(m));f||(f=v("defs"),b.node.appendChild(f));b.defs=f;for(var ca in d)d[h](ca)&&(b[ca]=d[ca]);b.paper=b.root=b}else b=r("svg",G.doc.body),v(b.node,{height:a,version:1.1,width:c,xmlns:la});return b}function x(c){return!c||c instanceof e||c instanceof l?c:c.tagName&&"svg"==c.tagName.toLowerCase()?new s(c):c.tagName&&"object"==c.tagName.toLowerCase()&&"image/svg+xml"==c.type?new s(c.contentDocument.getElementsByTagName("svg")[0]):new e(c)}a.version="0.3.0";a.toString=function(){return"Snap v"+
this.version};a._={};var G={win:N,doc:N.document};a._.glob=G;var h="hasOwnProperty",J=String,K=parseFloat,U=parseInt,I=Math,P=I.max,Q=I.min,Y=I.abs,C=I.PI,aa="",$=Object.prototype.toString,F=/^\s*((#[a-f\d]{6})|(#[a-f\d]{3})|rgba?\(\s*([\d\.]+%?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+%?(?:\s*,\s*[\d\.]+%?)?)\s*\)|hsba?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\)|hsla?\(\s*([\d\.]+(?:deg|\xb0|%)?\s*,\s*[\d\.]+%?\s*,\s*[\d\.]+(?:%?\s*,\s*[\d\.]+)?%?)\s*\))\s*$/i;a._.separator=
RegExp("[,\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]+");var S=RegExp("[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*"),X={hs:1,rg:1},W=RegExp("([a-z])[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)",
"ig"),ma=RegExp("([rstm])[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029,]*((-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*)+)","ig"),Z=RegExp("(-?\\d*\\.?\\d*(?:e[\\-+]?\\d+)?)[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*,?[\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*",
"ig"),na=0,ba="S"+(+new Date).toString(36),V=function(){return ba+(na++).toString(36)},m="http://www.w3.org/1999/xlink",la="http://www.w3.org/2000/svg",E={},ca=a.url=function(c){return"url('#"+c+"')"};a._.$=v;a._.id=V;a.format=function(){var c=/\{([^\}]+)\}/g,a=/(?:(?:^|\.)(.+?)(?=\[|\.|$|\()|\[('|")(.+?)\2\])(\(\))?/g,b=function(c,b,m){var h=m;b.replace(a,function(c,a,b,m,t){a=a||m;h&&(a in h&&(h=h[a]),"function"==typeof h&&t&&(h=h()))});return h=(null==h||h==m?c:h)+""};return function(a,m){return J(a).replace(c,
function(c,a){return b(c,a,m)})}}();a._.clone=M;a._.cacher=A;a.rad=z;a.deg=function(c){return 180*c/C%360};a.angle=w;a.is=y;a.snapTo=function(c,a,b){b=y(b,"finite")?b:10;if(y(c,"array"))for(var m=c.length;m--;){if(Y(c[m]-a)<=b)return c[m]}else{c=+c;m=a%c;if(m<b)return a-m;if(m>c-b)return a-m+c}return a};a.getRGB=A(function(c){if(!c||(c=J(c)).indexOf("-")+1)return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:ka};if("none"==c)return{r:-1,g:-1,b:-1,hex:"none",toString:ka};!X[h](c.toLowerCase().substring(0,
2))&&"#"!=c.charAt()&&(c=T(c));if(!c)return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:ka};var b,m,e,f,d;if(c=c.match(F)){c[2]&&(e=U(c[2].substring(5),16),m=U(c[2].substring(3,5),16),b=U(c[2].substring(1,3),16));c[3]&&(e=U((d=c[3].charAt(3))+d,16),m=U((d=c[3].charAt(2))+d,16),b=U((d=c[3].charAt(1))+d,16));c[4]&&(d=c[4].split(S),b=K(d[0]),"%"==d[0].slice(-1)&&(b*=2.55),m=K(d[1]),"%"==d[1].slice(-1)&&(m*=2.55),e=K(d[2]),"%"==d[2].slice(-1)&&(e*=2.55),"rgba"==c[1].toLowerCase().slice(0,4)&&(f=K(d[3])),
d[3]&&"%"==d[3].slice(-1)&&(f/=100));if(c[5])return d=c[5].split(S),b=K(d[0]),"%"==d[0].slice(-1)&&(b/=100),m=K(d[1]),"%"==d[1].slice(-1)&&(m/=100),e=K(d[2]),"%"==d[2].slice(-1)&&(e/=100),"deg"!=d[0].slice(-3)&&"\u00b0"!=d[0].slice(-1)||(b/=360),"hsba"==c[1].toLowerCase().slice(0,4)&&(f=K(d[3])),d[3]&&"%"==d[3].slice(-1)&&(f/=100),a.hsb2rgb(b,m,e,f);if(c[6])return d=c[6].split(S),b=K(d[0]),"%"==d[0].slice(-1)&&(b/=100),m=K(d[1]),"%"==d[1].slice(-1)&&(m/=100),e=K(d[2]),"%"==d[2].slice(-1)&&(e/=100),
"deg"!=d[0].slice(-3)&&"\u00b0"!=d[0].slice(-1)||(b/=360),"hsla"==c[1].toLowerCase().slice(0,4)&&(f=K(d[3])),d[3]&&"%"==d[3].slice(-1)&&(f/=100),a.hsl2rgb(b,m,e,f);b=Q(I.round(b),255);m=Q(I.round(m),255);e=Q(I.round(e),255);f=Q(P(f,0),1);c={r:b,g:m,b:e,toString:ka};c.hex="#"+(16777216|e|m<<8|b<<16).toString(16).slice(1);c.opacity=y(f,"finite")?f:1;return c}return{r:-1,g:-1,b:-1,hex:"none",error:1,toString:ka}},a);a.hsb=A(function(c,b,m){return a.hsb2rgb(c,b,m).hex});a.hsl=A(function(c,b,m){return a.hsl2rgb(c,
b,m).hex});a.rgb=A(function(c,a,b,m){if(y(m,"finite")){var e=I.round;return"rgba("+[e(c),e(a),e(b),+m.toFixed(2)]+")"}return"#"+(16777216|b|a<<8|c<<16).toString(16).slice(1)});var T=function(c){var a=G.doc.getElementsByTagName("head")[0]||G.doc.getElementsByTagName("svg")[0];T=A(function(c){if("red"==c.toLowerCase())return"rgb(255, 0, 0)";a.style.color="rgb(255, 0, 0)";a.style.color=c;c=G.doc.defaultView.getComputedStyle(a,aa).getPropertyValue("color");return"rgb(255, 0, 0)"==c?null:c});return T(c)},
qa=function(){return"hsb("+[this.h,this.s,this.b]+")"},ra=function(){return"hsl("+[this.h,this.s,this.l]+")"},ka=function(){return 1==this.opacity||null==this.opacity?this.hex:"rgba("+[this.r,this.g,this.b,this.opacity]+")"},D=function(c,b,m){null==b&&y(c,"object")&&"r"in c&&"g"in c&&"b"in c&&(m=c.b,b=c.g,c=c.r);null==b&&y(c,string)&&(m=a.getRGB(c),c=m.r,b=m.g,m=m.b);if(1<c||1<b||1<m)c/=255,b/=255,m/=255;return[c,b,m]},oa=function(c,b,m,e){c=I.round(255*c);b=I.round(255*b);m=I.round(255*m);c={r:c,
g:b,b:m,opacity:y(e,"finite")?e:1,hex:a.rgb(c,b,m),toString:ka};y(e,"finite")&&(c.opacity=e);return c};a.color=function(c){var b;y(c,"object")&&"h"in c&&"s"in c&&"b"in c?(b=a.hsb2rgb(c),c.r=b.r,c.g=b.g,c.b=b.b,c.opacity=1,c.hex=b.hex):y(c,"object")&&"h"in c&&"s"in c&&"l"in c?(b=a.hsl2rgb(c),c.r=b.r,c.g=b.g,c.b=b.b,c.opacity=1,c.hex=b.hex):(y(c,"string")&&(c=a.getRGB(c)),y(c,"object")&&"r"in c&&"g"in c&&"b"in c&&!("error"in c)?(b=a.rgb2hsl(c),c.h=b.h,c.s=b.s,c.l=b.l,b=a.rgb2hsb(c),c.v=b.b):(c={hex:"none"},
c.r=c.g=c.b=c.h=c.s=c.v=c.l=-1,c.error=1));c.toString=ka;return c};a.hsb2rgb=function(c,a,b,m){y(c,"object")&&"h"in c&&"s"in c&&"b"in c&&(b=c.b,a=c.s,c=c.h,m=c.o);var e,h,d;c=360*c%360/60;d=b*a;a=d*(1-Y(c%2-1));b=e=h=b-d;c=~~c;b+=[d,a,0,0,a,d][c];e+=[a,d,d,a,0,0][c];h+=[0,0,a,d,d,a][c];return oa(b,e,h,m)};a.hsl2rgb=function(c,a,b,m){y(c,"object")&&"h"in c&&"s"in c&&"l"in c&&(b=c.l,a=c.s,c=c.h);if(1<c||1<a||1<b)c/=360,a/=100,b/=100;var e,h,d;c=360*c%360/60;d=2*a*(0.5>b?b:1-b);a=d*(1-Y(c%2-1));b=e=
h=b-d/2;c=~~c;b+=[d,a,0,0,a,d][c];e+=[a,d,d,a,0,0][c];h+=[0,0,a,d,d,a][c];return oa(b,e,h,m)};a.rgb2hsb=function(c,a,b){b=D(c,a,b);c=b[0];a=b[1];b=b[2];var m,e;m=P(c,a,b);e=m-Q(c,a,b);c=((0==e?0:m==c?(a-b)/e:m==a?(b-c)/e+2:(c-a)/e+4)+360)%6*60/360;return{h:c,s:0==e?0:e/m,b:m,toString:qa}};a.rgb2hsl=function(c,a,b){b=D(c,a,b);c=b[0];a=b[1];b=b[2];var m,e,h;m=P(c,a,b);e=Q(c,a,b);h=m-e;c=((0==h?0:m==c?(a-b)/h:m==a?(b-c)/h+2:(c-a)/h+4)+360)%6*60/360;m=(m+e)/2;return{h:c,s:0==h?0:0.5>m?h/(2*m):h/(2-2*
m),l:m,toString:ra}};a.parsePathString=function(c){if(!c)return null;var b=a.path(c);if(b.arr)return a.path.clone(b.arr);var m={a:7,c:6,o:2,h:1,l:2,m:2,r:4,q:4,s:4,t:2,v:1,u:3,z:0},e=[];y(c,"array")&&y(c[0],"array")&&(e=a.path.clone(c));e.length||J(c).replace(W,function(c,a,b){var h=[];c=a.toLowerCase();b.replace(Z,function(c,a){a&&h.push(+a)});"m"==c&&2<h.length&&(e.push([a].concat(h.splice(0,2))),c="l",a="m"==a?"l":"L");"o"==c&&1==h.length&&e.push([a,h[0]]);if("r"==c)e.push([a].concat(h));else for(;h.length>=
m[c]&&(e.push([a].concat(h.splice(0,m[c]))),m[c]););});e.toString=a.path.toString;b.arr=a.path.clone(e);return e};var O=a.parseTransformString=function(c){if(!c)return null;var b=[];y(c,"array")&&y(c[0],"array")&&(b=a.path.clone(c));b.length||J(c).replace(ma,function(c,a,m){var e=[];a.toLowerCase();m.replace(Z,function(c,a){a&&e.push(+a)});b.push([a].concat(e))});b.toString=a.path.toString;return b};a._.svgTransform2string=d;a._.rgTransform=RegExp("^[a-z][\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029]*-?\\.?\\d",
"i");a._.transform2matrix=f;a._unit2px=b;a._.getSomeDefs=u;a._.getSomeSVG=p;a.select=function(c){return x(G.doc.querySelector(c))};a.selectAll=function(c){c=G.doc.querySelectorAll(c);for(var b=(a.set||Array)(),m=0;m<c.length;m++)b.push(x(c[m]));return b};setInterval(function(){for(var c in E)if(E[h](c)){var a=E[c],b=a.node;("svg"!=a.type&&!b.ownerSVGElement||"svg"==a.type&&(!b.parentNode||"ownerSVGElement"in b.parentNode&&!b.ownerSVGElement))&&delete E[c]}},1E4);(function(c){function m(c){function a(c,
b){var m=v(c.node,b);(m=(m=m&&m.match(d))&&m[2])&&"#"==m.charAt()&&(m=m.substring(1))&&(f[m]=(f[m]||[]).concat(function(a){var m={};m[b]=ca(a);v(c.node,m)}))}function b(c){var a=v(c.node,"xlink:href");a&&"#"==a.charAt()&&(a=a.substring(1))&&(f[a]=(f[a]||[]).concat(function(a){c.attr("xlink:href","#"+a)}))}var e=c.selectAll("*"),h,d=/^\s*url\(("|'|)(.*)\1\)\s*$/;c=[];for(var f={},l=0,E=e.length;l<E;l++){h=e[l];a(h,"fill");a(h,"stroke");a(h,"filter");a(h,"mask");a(h,"clip-path");b(h);var t=v(h.node,
"id");t&&(v(h.node,{id:h.id}),c.push({old:t,id:h.id}))}l=0;for(E=c.length;l<E;l++)if(e=f[c[l].old])for(h=0,t=e.length;h<t;h++)e[h](c[l].id)}function e(c,a,b){return function(m){m=m.slice(c,a);1==m.length&&(m=m[0]);return b?b(m):m}}function d(c){return function(){var a=c?"<"+this.type:"",b=this.node.attributes,m=this.node.childNodes;if(c)for(var e=0,h=b.length;e<h;e++)a+=" "+b[e].name+'="'+b[e].value.replace(/"/g,'\\"')+'"';if(m.length){c&&(a+=">");e=0;for(h=m.length;e<h;e++)3==m[e].nodeType?a+=m[e].nodeValue:
1==m[e].nodeType&&(a+=x(m[e]).toString());c&&(a+="</"+this.type+">")}else c&&(a+="/>");return a}}c.attr=function(c,a){if(!c)return this;if(y(c,"string"))if(1<arguments.length){var b={};b[c]=a;c=b}else return k("snap.util.getattr."+c,this).firstDefined();for(var m in c)c[h](m)&&k("snap.util.attr."+m,this,c[m]);return this};c.getBBox=function(c){if(!a.Matrix||!a.path)return this.node.getBBox();var b=this,m=new a.Matrix;if(b.removed)return a._.box();for(;"use"==b.type;)if(c||(m=m.add(b.transform().localMatrix.translate(b.attr("x")||
0,b.attr("y")||0))),b.original)b=b.original;else var e=b.attr("xlink:href"),b=b.original=b.node.ownerDocument.getElementById(e.substring(e.indexOf("#")+1));var e=b._,h=a.path.get[b.type]||a.path.get.deflt;try{if(c)return e.bboxwt=h?a.path.getBBox(b.realPath=h(b)):a._.box(b.node.getBBox()),a._.box(e.bboxwt);b.realPath=h(b);b.matrix=b.transform().localMatrix;e.bbox=a.path.getBBox(a.path.map(b.realPath,m.add(b.matrix)));return a._.box(e.bbox)}catch(d){return a._.box()}};var f=function(){return this.string};
c.transform=function(c){var b=this._;if(null==c){var m=this;c=new a.Matrix(this.node.getCTM());for(var e=n(this),h=[e],d=new a.Matrix,l=e.toTransformString(),b=J(e)==J(this.matrix)?J(b.transform):l;"svg"!=m.type&&(m=m.parent());)h.push(n(m));for(m=h.length;m--;)d.add(h[m]);return{string:b,globalMatrix:c,totalMatrix:d,localMatrix:e,diffMatrix:c.clone().add(e.invert()),global:c.toTransformString(),total:d.toTransformString(),local:l,toString:f}}c instanceof a.Matrix?this.matrix=c:n(this,c);this.node&&
("linearGradient"==this.type||"radialGradient"==this.type?v(this.node,{gradientTransform:this.matrix}):"pattern"==this.type?v(this.node,{patternTransform:this.matrix}):v(this.node,{transform:this.matrix}));return this};c.parent=function(){return x(this.node.parentNode)};c.append=c.add=function(c){if(c){if("set"==c.type){var a=this;c.forEach(function(c){a.add(c)});return this}c=x(c);this.node.appendChild(c.node);c.paper=this.paper}return this};c.appendTo=function(c){c&&(c=x(c),c.append(this));return this};
c.prepend=function(c){if(c){if("set"==c.type){var a=this,b;c.forEach(function(c){b?b.after(c):a.prepend(c);b=c});return this}c=x(c);var m=c.parent();this.node.insertBefore(c.node,this.node.firstChild);this.add&&this.add();c.paper=this.paper;this.parent()&&this.parent().add();m&&m.add()}return this};c.prependTo=function(c){c=x(c);c.prepend(this);return this};c.before=function(c){if("set"==c.type){var a=this;c.forEach(function(c){var b=c.parent();a.node.parentNode.insertBefore(c.node,a.node);b&&b.add()});
this.parent().add();return this}c=x(c);var b=c.parent();this.node.parentNode.insertBefore(c.node,this.node);this.parent()&&this.parent().add();b&&b.add();c.paper=this.paper;return this};c.after=function(c){c=x(c);var a=c.parent();this.node.nextSibling?this.node.parentNode.insertBefore(c.node,this.node.nextSibling):this.node.parentNode.appendChild(c.node);this.parent()&&this.parent().add();a&&a.add();c.paper=this.paper;return this};c.insertBefore=function(c){c=x(c);var a=this.parent();c.node.parentNode.insertBefore(this.node,
c.node);this.paper=c.paper;a&&a.add();c.parent()&&c.parent().add();return this};c.insertAfter=function(c){c=x(c);var a=this.parent();c.node.parentNode.insertBefore(this.node,c.node.nextSibling);this.paper=c.paper;a&&a.add();c.parent()&&c.parent().add();return this};c.remove=function(){var c=this.parent();this.node.parentNode&&this.node.parentNode.removeChild(this.node);delete this.paper;this.removed=!0;c&&c.add();return this};c.select=function(c){return x(this.node.querySelector(c))};c.selectAll=
function(c){c=this.node.querySelectorAll(c);for(var b=(a.set||Array)(),m=0;m<c.length;m++)b.push(x(c[m]));return b};c.asPX=function(c,a){null==a&&(a=this.attr(c));return+b(this,c,a)};c.use=function(){var c,a=this.node.id;a||(a=this.id,v(this.node,{id:a}));c="linearGradient"==this.type||"radialGradient"==this.type||"pattern"==this.type?r(this.type,this.node.parentNode):r("use",this.node.parentNode);v(c.node,{"xlink:href":"#"+a});c.original=this;return c};var l=/\S+/g;c.addClass=function(c){var a=(c||
"").match(l)||[];c=this.node;var b=c.className.baseVal,m=b.match(l)||[],e,h,d;if(a.length){for(e=0;d=a[e++];)h=m.indexOf(d),~h||m.push(d);a=m.join(" ");b!=a&&(c.className.baseVal=a)}return this};c.removeClass=function(c){var a=(c||"").match(l)||[];c=this.node;var b=c.className.baseVal,m=b.match(l)||[],e,h;if(m.length){for(e=0;h=a[e++];)h=m.indexOf(h),~h&&m.splice(h,1);a=m.join(" ");b!=a&&(c.className.baseVal=a)}return this};c.hasClass=function(c){return!!~(this.node.className.baseVal.match(l)||[]).indexOf(c)};
c.toggleClass=function(c,a){if(null!=a)return a?this.addClass(c):this.removeClass(c);var b=(c||"").match(l)||[],m=this.node,e=m.className.baseVal,h=e.match(l)||[],d,f,E;for(d=0;E=b[d++];)f=h.indexOf(E),~f?h.splice(f,1):h.push(E);b=h.join(" ");e!=b&&(m.className.baseVal=b);return this};c.clone=function(){var c=x(this.node.cloneNode(!0));v(c.node,"id")&&v(c.node,{id:c.id});m(c);c.insertAfter(this);return c};c.toDefs=function(){u(this).appendChild(this.node);return this};c.pattern=c.toPattern=function(c,
a,b,m){var e=r("pattern",u(this));null==c&&(c=this.getBBox());y(c,"object")&&"x"in c&&(a=c.y,b=c.width,m=c.height,c=c.x);v(e.node,{x:c,y:a,width:b,height:m,patternUnits:"userSpaceOnUse",id:e.id,viewBox:[c,a,b,m].join(" ")});e.node.appendChild(this.node);return e};c.marker=function(c,a,b,m,e,h){var d=r("marker",u(this));null==c&&(c=this.getBBox());y(c,"object")&&"x"in c&&(a=c.y,b=c.width,m=c.height,e=c.refX||c.cx,h=c.refY||c.cy,c=c.x);v(d.node,{viewBox:[c,a,b,m].join(" "),markerWidth:b,markerHeight:m,
orient:"auto",refX:e||0,refY:h||0,id:d.id});d.node.appendChild(this.node);return d};var E=function(c,a,b,m){"function"!=typeof b||b.length||(m=b,b=L.linear);this.attr=c;this.dur=a;b&&(this.easing=b);m&&(this.callback=m)};a._.Animation=E;a.animation=function(c,a,b,m){return new E(c,a,b,m)};c.inAnim=function(){var c=[],a;for(a in this.anims)this.anims[h](a)&&function(a){c.push({anim:new E(a._attrs,a.dur,a.easing,a._callback),mina:a,curStatus:a.status(),status:function(c){return a.status(c)},stop:function(){a.stop()}})}(this.anims[a]);
return c};a.animate=function(c,a,b,m,e,h){"function"!=typeof e||e.length||(h=e,e=L.linear);var d=L.time();c=L(c,a,d,d+m,L.time,b,e);h&&k.once("mina.finish."+c.id,h);return c};c.stop=function(){for(var c=this.inAnim(),a=0,b=c.length;a<b;a++)c[a].stop();return this};c.animate=function(c,a,b,m){"function"!=typeof b||b.length||(m=b,b=L.linear);c instanceof E&&(m=c.callback,b=c.easing,a=b.dur,c=c.attr);var d=[],f=[],l={},t,ca,n,T=this,q;for(q in c)if(c[h](q)){T.equal?(n=T.equal(q,J(c[q])),t=n.from,ca=
n.to,n=n.f):(t=+T.attr(q),ca=+c[q]);var la=y(t,"array")?t.length:1;l[q]=e(d.length,d.length+la,n);d=d.concat(t);f=f.concat(ca)}t=L.time();var p=L(d,f,t,t+a,L.time,function(c){var a={},b;for(b in l)l[h](b)&&(a[b]=l[b](c));T.attr(a)},b);T.anims[p.id]=p;p._attrs=c;p._callback=m;k("snap.animcreated."+T.id,p);k.once("mina.finish."+p.id,function(){delete T.anims[p.id];m&&m.call(T)});k.once("mina.stop."+p.id,function(){delete T.anims[p.id]});return T};var T={};c.data=function(c,b){var m=T[this.id]=T[this.id]||
{};if(0==arguments.length)return k("snap.data.get."+this.id,this,m,null),m;if(1==arguments.length){if(a.is(c,"object")){for(var e in c)c[h](e)&&this.data(e,c[e]);return this}k("snap.data.get."+this.id,this,m[c],c);return m[c]}m[c]=b;k("snap.data.set."+this.id,this,b,c);return this};c.removeData=function(c){null==c?T[this.id]={}:T[this.id]&&delete T[this.id][c];return this};c.outerSVG=c.toString=d(1);c.innerSVG=d()})(e.prototype);a.parse=function(c){var a=G.doc.createDocumentFragment(),b=!0,m=G.doc.createElement("div");
c=J(c);c.match(/^\s*<\s*svg(?:\s|>)/)||(c="<svg>"+c+"</svg>",b=!1);m.innerHTML=c;if(c=m.getElementsByTagName("svg")[0])if(b)a=c;else for(;c.firstChild;)a.appendChild(c.firstChild);m.innerHTML=aa;return new l(a)};l.prototype.select=e.prototype.select;l.prototype.selectAll=e.prototype.selectAll;a.fragment=function(){for(var c=Array.prototype.slice.call(arguments,0),b=G.doc.createDocumentFragment(),m=0,e=c.length;m<e;m++){var h=c[m];h.node&&h.node.nodeType&&b.appendChild(h.node);h.nodeType&&b.appendChild(h);
"string"==typeof h&&b.appendChild(a.parse(h).node)}return new l(b)};a._.make=r;a._.wrap=x;s.prototype.el=function(c,a){var b=r(c,this.node);a&&b.attr(a);return b};k.on("snap.util.getattr",function(){var c=k.nt(),c=c.substring(c.lastIndexOf(".")+1),a=c.replace(/[A-Z]/g,function(c){return"-"+c.toLowerCase()});return pa[h](a)?this.node.ownerDocument.defaultView.getComputedStyle(this.node,null).getPropertyValue(a):v(this.node,c)});var pa={"alignment-baseline":0,"baseline-shift":0,clip:0,"clip-path":0,
"clip-rule":0,color:0,"color-interpolation":0,"color-interpolation-filters":0,"color-profile":0,"color-rendering":0,cursor:0,direction:0,display:0,"dominant-baseline":0,"enable-background":0,fill:0,"fill-opacity":0,"fill-rule":0,filter:0,"flood-color":0,"flood-opacity":0,font:0,"font-family":0,"font-size":0,"font-size-adjust":0,"font-stretch":0,"font-style":0,"font-variant":0,"font-weight":0,"glyph-orientation-horizontal":0,"glyph-orientation-vertical":0,"image-rendering":0,kerning:0,"letter-spacing":0,
"lighting-color":0,marker:0,"marker-end":0,"marker-mid":0,"marker-start":0,mask:0,opacity:0,overflow:0,"pointer-events":0,"shape-rendering":0,"stop-color":0,"stop-opacity":0,stroke:0,"stroke-dasharray":0,"stroke-dashoffset":0,"stroke-linecap":0,"stroke-linejoin":0,"stroke-miterlimit":0,"stroke-opacity":0,"stroke-width":0,"text-anchor":0,"text-decoration":0,"text-rendering":0,"unicode-bidi":0,visibility:0,"word-spacing":0,"writing-mode":0};k.on("snap.util.attr",function(c){var a=k.nt(),b={},a=a.substring(a.lastIndexOf(".")+
1);b[a]=c;var m=a.replace(/-(\w)/gi,function(c,a){return a.toUpperCase()}),a=a.replace(/[A-Z]/g,function(c){return"-"+c.toLowerCase()});pa[h](a)?this.node.style[m]=null==c?aa:c:v(this.node,b)});a.ajax=function(c,a,b,m){var e=new XMLHttpRequest,h=V();if(e){if(y(a,"function"))m=b,b=a,a=null;else if(y(a,"object")){var d=[],f;for(f in a)a.hasOwnProperty(f)&&d.push(encodeURIComponent(f)+"="+encodeURIComponent(a[f]));a=d.join("&")}e.open(a?"POST":"GET",c,!0);a&&(e.setRequestHeader("X-Requested-With","XMLHttpRequest"),
e.setRequestHeader("Content-type","application/x-www-form-urlencoded"));b&&(k.once("snap.ajax."+h+".0",b),k.once("snap.ajax."+h+".200",b),k.once("snap.ajax."+h+".304",b));e.onreadystatechange=function(){4==e.readyState&&k("snap.ajax."+h+"."+e.status,m,e)};if(4==e.readyState)return e;e.send(a);return e}};a.load=function(c,b,m){a.ajax(c,function(c){c=a.parse(c.responseText);m?b.call(m,c):b(c)})};a.getElementByPoint=function(c,a){var b,m,e=G.doc.elementFromPoint(c,a);if(G.win.opera&&"svg"==e.tagName){b=
e;m=b.getBoundingClientRect();b=b.ownerDocument;var h=b.body,d=b.documentElement;b=m.top+(g.win.pageYOffset||d.scrollTop||h.scrollTop)-(d.clientTop||h.clientTop||0);m=m.left+(g.win.pageXOffset||d.scrollLeft||h.scrollLeft)-(d.clientLeft||h.clientLeft||0);h=e.createSVGRect();h.x=c-m;h.y=a-b;h.width=h.height=1;b=e.getIntersectionList(h,null);b.length&&(e=b[b.length-1])}return e?x(e):null};a.plugin=function(c){c(a,e,s,G,l)};return G.win.Snap=a}();C.plugin(function(a,k,y,M,A){function w(a,d,f,b,q,e){null==
d&&"[object SVGMatrix]"==z.call(a)?(this.a=a.a,this.b=a.b,this.c=a.c,this.d=a.d,this.e=a.e,this.f=a.f):null!=a?(this.a=+a,this.b=+d,this.c=+f,this.d=+b,this.e=+q,this.f=+e):(this.a=1,this.c=this.b=0,this.d=1,this.f=this.e=0)}var z=Object.prototype.toString,d=String,f=Math;(function(n){function k(a){return a[0]*a[0]+a[1]*a[1]}function p(a){var d=f.sqrt(k(a));a[0]&&(a[0]/=d);a[1]&&(a[1]/=d)}n.add=function(a,d,e,f,n,p){var k=[[],[],[]],u=[[this.a,this.c,this.e],[this.b,this.d,this.f],[0,0,1]];d=[[a,
e,n],[d,f,p],[0,0,1]];a&&a instanceof w&&(d=[[a.a,a.c,a.e],[a.b,a.d,a.f],[0,0,1]]);for(a=0;3>a;a++)for(e=0;3>e;e++){for(f=n=0;3>f;f++)n+=u[a][f]*d[f][e];k[a][e]=n}this.a=k[0][0];this.b=k[1][0];this.c=k[0][1];this.d=k[1][1];this.e=k[0][2];this.f=k[1][2];return this};n.invert=function(){var a=this.a*this.d-this.b*this.c;return new w(this.d/a,-this.b/a,-this.c/a,this.a/a,(this.c*this.f-this.d*this.e)/a,(this.b*this.e-this.a*this.f)/a)};n.clone=function(){return new w(this.a,this.b,this.c,this.d,this.e,
this.f)};n.translate=function(a,d){return this.add(1,0,0,1,a,d)};n.scale=function(a,d,e,f){null==d&&(d=a);(e||f)&&this.add(1,0,0,1,e,f);this.add(a,0,0,d,0,0);(e||f)&&this.add(1,0,0,1,-e,-f);return this};n.rotate=function(b,d,e){b=a.rad(b);d=d||0;e=e||0;var l=+f.cos(b).toFixed(9);b=+f.sin(b).toFixed(9);this.add(l,b,-b,l,d,e);return this.add(1,0,0,1,-d,-e)};n.x=function(a,d){return a*this.a+d*this.c+this.e};n.y=function(a,d){return a*this.b+d*this.d+this.f};n.get=function(a){return+this[d.fromCharCode(97+
a)].toFixed(4)};n.toString=function(){return"matrix("+[this.get(0),this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)].join()+")"};n.offset=function(){return[this.e.toFixed(4),this.f.toFixed(4)]};n.determinant=function(){return this.a*this.d-this.b*this.c};n.split=function(){var b={};b.dx=this.e;b.dy=this.f;var d=[[this.a,this.c],[this.b,this.d]];b.scalex=f.sqrt(k(d[0]));p(d[0]);b.shear=d[0][0]*d[1][0]+d[0][1]*d[1][1];d[1]=[d[1][0]-d[0][0]*b.shear,d[1][1]-d[0][1]*b.shear];b.scaley=f.sqrt(k(d[1]));
p(d[1]);b.shear/=b.scaley;0>this.determinant()&&(b.scalex=-b.scalex);var e=-d[0][1],d=d[1][1];0>d?(b.rotate=a.deg(f.acos(d)),0>e&&(b.rotate=360-b.rotate)):b.rotate=a.deg(f.asin(e));b.isSimple=!+b.shear.toFixed(9)&&(b.scalex.toFixed(9)==b.scaley.toFixed(9)||!b.rotate);b.isSuperSimple=!+b.shear.toFixed(9)&&b.scalex.toFixed(9)==b.scaley.toFixed(9)&&!b.rotate;b.noRotation=!+b.shear.toFixed(9)&&!b.rotate;return b};n.toTransformString=function(a){a=a||this.split();if(+a.shear.toFixed(9))return"m"+[this.get(0),
this.get(1),this.get(2),this.get(3),this.get(4),this.get(5)];a.scalex=+a.scalex.toFixed(4);a.scaley=+a.scaley.toFixed(4);a.rotate=+a.rotate.toFixed(4);return(a.dx||a.dy?"t"+[+a.dx.toFixed(4),+a.dy.toFixed(4)]:"")+(1!=a.scalex||1!=a.scaley?"s"+[a.scalex,a.scaley,0,0]:"")+(a.rotate?"r"+[+a.rotate.toFixed(4),0,0]:"")}})(w.prototype);a.Matrix=w;a.matrix=function(a,d,f,b,k,e){return new w(a,d,f,b,k,e)}});C.plugin(function(a,v,y,M,A){function w(h){return function(d){k.stop();d instanceof A&&1==d.node.childNodes.length&&
("radialGradient"==d.node.firstChild.tagName||"linearGradient"==d.node.firstChild.tagName||"pattern"==d.node.firstChild.tagName)&&(d=d.node.firstChild,b(this).appendChild(d),d=u(d));if(d instanceof v)if("radialGradient"==d.type||"linearGradient"==d.type||"pattern"==d.type){d.node.id||e(d.node,{id:d.id});var f=l(d.node.id)}else f=d.attr(h);else f=a.color(d),f.error?(f=a(b(this).ownerSVGElement).gradient(d))?(f.node.id||e(f.node,{id:f.id}),f=l(f.node.id)):f=d:f=r(f);d={};d[h]=f;e(this.node,d);this.node.style[h]=
x}}function z(a){k.stop();a==+a&&(a+="px");this.node.style.fontSize=a}function d(a){var b=[];a=a.childNodes;for(var e=0,f=a.length;e<f;e++){var l=a[e];3==l.nodeType&&b.push(l.nodeValue);"tspan"==l.tagName&&(1==l.childNodes.length&&3==l.firstChild.nodeType?b.push(l.firstChild.nodeValue):b.push(d(l)))}return b}function f(){k.stop();return this.node.style.fontSize}var n=a._.make,u=a._.wrap,p=a.is,b=a._.getSomeDefs,q=/^url\(#?([^)]+)\)$/,e=a._.$,l=a.url,r=String,s=a._.separator,x="";k.on("snap.util.attr.mask",
function(a){if(a instanceof v||a instanceof A){k.stop();a instanceof A&&1==a.node.childNodes.length&&(a=a.node.firstChild,b(this).appendChild(a),a=u(a));if("mask"==a.type)var d=a;else d=n("mask",b(this)),d.node.appendChild(a.node);!d.node.id&&e(d.node,{id:d.id});e(this.node,{mask:l(d.id)})}});(function(a){k.on("snap.util.attr.clip",a);k.on("snap.util.attr.clip-path",a);k.on("snap.util.attr.clipPath",a)})(function(a){if(a instanceof v||a instanceof A){k.stop();if("clipPath"==a.type)var d=a;else d=
n("clipPath",b(this)),d.node.appendChild(a.node),!d.node.id&&e(d.node,{id:d.id});e(this.node,{"clip-path":l(d.id)})}});k.on("snap.util.attr.fill",w("fill"));k.on("snap.util.attr.stroke",w("stroke"));var G=/^([lr])(?:\(([^)]*)\))?(.*)$/i;k.on("snap.util.grad.parse",function(a){a=r(a);var b=a.match(G);if(!b)return null;a=b[1];var e=b[2],b=b[3],e=e.split(/\s*,\s*/).map(function(a){return+a==a?+a:a});1==e.length&&0==e[0]&&(e=[]);b=b.split("-");b=b.map(function(a){a=a.split(":");var b={color:a[0]};a[1]&&
(b.offset=parseFloat(a[1]));return b});return{type:a,params:e,stops:b}});k.on("snap.util.attr.d",function(b){k.stop();p(b,"array")&&p(b[0],"array")&&(b=a.path.toString.call(b));b=r(b);b.match(/[ruo]/i)&&(b=a.path.toAbsolute(b));e(this.node,{d:b})})(-1);k.on("snap.util.attr.#text",function(a){k.stop();a=r(a);for(a=M.doc.createTextNode(a);this.node.firstChild;)this.node.removeChild(this.node.firstChild);this.node.appendChild(a)})(-1);k.on("snap.util.attr.path",function(a){k.stop();this.attr({d:a})})(-1);
k.on("snap.util.attr.class",function(a){k.stop();this.node.className.baseVal=a})(-1);k.on("snap.util.attr.viewBox",function(a){a=p(a,"object")&&"x"in a?[a.x,a.y,a.width,a.height].join(" "):p(a,"array")?a.join(" "):a;e(this.node,{viewBox:a});k.stop()})(-1);k.on("snap.util.attr.transform",function(a){this.transform(a);k.stop()})(-1);k.on("snap.util.attr.r",function(a){"rect"==this.type&&(k.stop(),e(this.node,{rx:a,ry:a}))})(-1);k.on("snap.util.attr.textpath",function(a){k.stop();if("text"==this.type){var d,
f;if(!a&&this.textPath){for(a=this.textPath;a.node.firstChild;)this.node.appendChild(a.node.firstChild);a.remove();delete this.textPath}else if(p(a,"string")?(d=b(this),a=u(d.parentNode).path(a),d.appendChild(a.node),d=a.id,a.attr({id:d})):(a=u(a),a instanceof v&&(d=a.attr("id"),d||(d=a.id,a.attr({id:d})))),d)if(a=this.textPath,f=this.node,a)a.attr({"xlink:href":"#"+d});else{for(a=e("textPath",{"xlink:href":"#"+d});f.firstChild;)a.appendChild(f.firstChild);f.appendChild(a);this.textPath=u(a)}}})(-1);
k.on("snap.util.attr.text",function(a){if("text"==this.type){for(var b=this.node,d=function(a){var b=e("tspan");if(p(a,"array"))for(var f=0;f<a.length;f++)b.appendChild(d(a[f]));else b.appendChild(M.doc.createTextNode(a));b.normalize&&b.normalize();return b};b.firstChild;)b.removeChild(b.firstChild);for(a=d(a);a.firstChild;)b.appendChild(a.firstChild)}k.stop()})(-1);k.on("snap.util.attr.fontSize",z)(-1);k.on("snap.util.attr.font-size",z)(-1);k.on("snap.util.getattr.transform",function(){k.stop();
return this.transform()})(-1);k.on("snap.util.getattr.textpath",function(){k.stop();return this.textPath})(-1);(function(){function b(d){return function(){k.stop();var b=M.doc.defaultView.getComputedStyle(this.node,null).getPropertyValue("marker-"+d);return"none"==b?b:a(M.doc.getElementById(b.match(q)[1]))}}function d(a){return function(b){k.stop();var d="marker"+a.charAt(0).toUpperCase()+a.substring(1);if(""==b||!b)this.node.style[d]="none";else if("marker"==b.type){var f=b.node.id;f||e(b.node,{id:b.id});
this.node.style[d]=l(f)}}}k.on("snap.util.getattr.marker-end",b("end"))(-1);k.on("snap.util.getattr.markerEnd",b("end"))(-1);k.on("snap.util.getattr.marker-start",b("start"))(-1);k.on("snap.util.getattr.markerStart",b("start"))(-1);k.on("snap.util.getattr.marker-mid",b("mid"))(-1);k.on("snap.util.getattr.markerMid",b("mid"))(-1);k.on("snap.util.attr.marker-end",d("end"))(-1);k.on("snap.util.attr.markerEnd",d("end"))(-1);k.on("snap.util.attr.marker-start",d("start"))(-1);k.on("snap.util.attr.markerStart",
d("start"))(-1);k.on("snap.util.attr.marker-mid",d("mid"))(-1);k.on("snap.util.attr.markerMid",d("mid"))(-1)})();k.on("snap.util.getattr.r",function(){if("rect"==this.type&&e(this.node,"rx")==e(this.node,"ry"))return k.stop(),e(this.node,"rx")})(-1);k.on("snap.util.getattr.text",function(){if("text"==this.type||"tspan"==this.type){k.stop();var a=d(this.node);return 1==a.length?a[0]:a}})(-1);k.on("snap.util.getattr.#text",function(){return this.node.textContent})(-1);k.on("snap.util.getattr.viewBox",
function(){k.stop();var b=e(this.node,"viewBox");if(b)return b=b.split(s),a._.box(+b[0],+b[1],+b[2],+b[3])})(-1);k.on("snap.util.getattr.points",function(){var a=e(this.node,"points");k.stop();if(a)return a.split(s)})(-1);k.on("snap.util.getattr.path",function(){var a=e(this.node,"d");k.stop();return a})(-1);k.on("snap.util.getattr.class",function(){return this.node.className.baseVal})(-1);k.on("snap.util.getattr.fontSize",f)(-1);k.on("snap.util.getattr.font-size",f)(-1)});C.plugin(function(a,v,y,
M,A){function w(a){return a}function z(a){return function(b){return+b.toFixed(3)+a}}var d={"+":function(a,b){return a+b},"-":function(a,b){return a-b},"/":function(a,b){return a/b},"*":function(a,b){return a*b}},f=String,n=/[a-z]+$/i,u=/^\s*([+\-\/*])\s*=\s*([\d.eE+\-]+)\s*([^\d\s]+)?\s*$/;k.on("snap.util.attr",function(a){if(a=f(a).match(u)){var b=k.nt(),b=b.substring(b.lastIndexOf(".")+1),q=this.attr(b),e={};k.stop();var l=a[3]||"",r=q.match(n),s=d[a[1]];r&&r==l?a=s(parseFloat(q),+a[2]):(q=this.asPX(b),
a=s(this.asPX(b),this.asPX(b,a[2]+l)));isNaN(q)||isNaN(a)||(e[b]=a,this.attr(e))}})(-10);k.on("snap.util.equal",function(a,b){var q=f(this.attr(a)||""),e=f(b).match(u);if(e){k.stop();var l=e[3]||"",r=q.match(n),s=d[e[1]];if(r&&r==l)return{from:parseFloat(q),to:s(parseFloat(q),+e[2]),f:z(r)};q=this.asPX(a);return{from:q,to:s(q,this.asPX(a,e[2]+l)),f:w}}})(-10)});C.plugin(function(a,v,y,M,A){var w=y.prototype,z=a.is;w.rect=function(a,d,k,p,b,q){var e;null==q&&(q=b);z(a,"object")&&"[object Object]"==
a?e=a:null!=a&&(e={x:a,y:d,width:k,height:p},null!=b&&(e.rx=b,e.ry=q));return this.el("rect",e)};w.circle=function(a,d,k){var p;z(a,"object")&&"[object Object]"==a?p=a:null!=a&&(p={cx:a,cy:d,r:k});return this.el("circle",p)};var d=function(){function a(){this.parentNode.removeChild(this)}return function(d,k){var p=M.doc.createElement("img"),b=M.doc.body;p.style.cssText="position:absolute;left:-9999em;top:-9999em";p.onload=function(){k.call(p);p.onload=p.onerror=null;b.removeChild(p)};p.onerror=a;
b.appendChild(p);p.src=d}}();w.image=function(f,n,k,p,b){var q=this.el("image");if(z(f,"object")&&"src"in f)q.attr(f);else if(null!=f){var e={"xlink:href":f,preserveAspectRatio:"none"};null!=n&&null!=k&&(e.x=n,e.y=k);null!=p&&null!=b?(e.width=p,e.height=b):d(f,function(){a._.$(q.node,{width:this.offsetWidth,height:this.offsetHeight})});a._.$(q.node,e)}return q};w.ellipse=function(a,d,k,p){var b;z(a,"object")&&"[object Object]"==a?b=a:null!=a&&(b={cx:a,cy:d,rx:k,ry:p});return this.el("ellipse",b)};
w.path=function(a){var d;z(a,"object")&&!z(a,"array")?d=a:a&&(d={d:a});return this.el("path",d)};w.group=w.g=function(a){var d=this.el("g");1==arguments.length&&a&&!a.type?d.attr(a):arguments.length&&d.add(Array.prototype.slice.call(arguments,0));return d};w.svg=function(a,d,k,p,b,q,e,l){var r={};z(a,"object")&&null==d?r=a:(null!=a&&(r.x=a),null!=d&&(r.y=d),null!=k&&(r.width=k),null!=p&&(r.height=p),null!=b&&null!=q&&null!=e&&null!=l&&(r.viewBox=[b,q,e,l]));return this.el("svg",r)};w.mask=function(a){var d=
this.el("mask");1==arguments.length&&a&&!a.type?d.attr(a):arguments.length&&d.add(Array.prototype.slice.call(arguments,0));return d};w.ptrn=function(a,d,k,p,b,q,e,l){if(z(a,"object"))var r=a;else arguments.length?(r={},null!=a&&(r.x=a),null!=d&&(r.y=d),null!=k&&(r.width=k),null!=p&&(r.height=p),null!=b&&null!=q&&null!=e&&null!=l&&(r.viewBox=[b,q,e,l])):r={patternUnits:"userSpaceOnUse"};return this.el("pattern",r)};w.use=function(a){return null!=a?(make("use",this.node),a instanceof v&&(a.attr("id")||
a.attr({id:ID()}),a=a.attr("id")),this.el("use",{"xlink:href":a})):v.prototype.use.call(this)};w.text=function(a,d,k){var p={};z(a,"object")?p=a:null!=a&&(p={x:a,y:d,text:k||""});return this.el("text",p)};w.line=function(a,d,k,p){var b={};z(a,"object")?b=a:null!=a&&(b={x1:a,x2:k,y1:d,y2:p});return this.el("line",b)};w.polyline=function(a){1<arguments.length&&(a=Array.prototype.slice.call(arguments,0));var d={};z(a,"object")&&!z(a,"array")?d=a:null!=a&&(d={points:a});return this.el("polyline",d)};
w.polygon=function(a){1<arguments.length&&(a=Array.prototype.slice.call(arguments,0));var d={};z(a,"object")&&!z(a,"array")?d=a:null!=a&&(d={points:a});return this.el("polygon",d)};(function(){function d(){return this.selectAll("stop")}function n(b,d){var f=e("stop"),k={offset:+d+"%"};b=a.color(b);k["stop-color"]=b.hex;1>b.opacity&&(k["stop-opacity"]=b.opacity);e(f,k);this.node.appendChild(f);return this}function u(){if("linearGradient"==this.type){var b=e(this.node,"x1")||0,d=e(this.node,"x2")||
1,f=e(this.node,"y1")||0,k=e(this.node,"y2")||0;return a._.box(b,f,math.abs(d-b),math.abs(k-f))}b=this.node.r||0;return a._.box((this.node.cx||0.5)-b,(this.node.cy||0.5)-b,2*b,2*b)}function p(a,d){function f(a,b){for(var d=(b-u)/(a-w),e=w;e<a;e++)h[e].offset=+(+u+d*(e-w)).toFixed(2);w=a;u=b}var n=k("snap.util.grad.parse",null,d).firstDefined(),p;if(!n)return null;n.params.unshift(a);p="l"==n.type.toLowerCase()?b.apply(0,n.params):q.apply(0,n.params);n.type!=n.type.toLowerCase()&&e(p.node,{gradientUnits:"userSpaceOnUse"});
var h=n.stops,n=h.length,u=0,w=0;n--;for(var v=0;v<n;v++)"offset"in h[v]&&f(v,h[v].offset);h[n].offset=h[n].offset||100;f(n,h[n].offset);for(v=0;v<=n;v++){var y=h[v];p.addStop(y.color,y.offset)}return p}function b(b,k,p,q,w){b=a._.make("linearGradient",b);b.stops=d;b.addStop=n;b.getBBox=u;null!=k&&e(b.node,{x1:k,y1:p,x2:q,y2:w});return b}function q(b,k,p,q,w,h){b=a._.make("radialGradient",b);b.stops=d;b.addStop=n;b.getBBox=u;null!=k&&e(b.node,{cx:k,cy:p,r:q});null!=w&&null!=h&&e(b.node,{fx:w,fy:h});
return b}var e=a._.$;w.gradient=function(a){return p(this.defs,a)};w.gradientLinear=function(a,d,e,f){return b(this.defs,a,d,e,f)};w.gradientRadial=function(a,b,d,e,f){return q(this.defs,a,b,d,e,f)};w.toString=function(){var b=this.node.ownerDocument,d=b.createDocumentFragment(),b=b.createElement("div"),e=this.node.cloneNode(!0);d.appendChild(b);b.appendChild(e);a._.$(e,{xmlns:"http://www.w3.org/2000/svg"});b=b.innerHTML;d.removeChild(d.firstChild);return b};w.clear=function(){for(var a=this.node.firstChild,
b;a;)b=a.nextSibling,"defs"!=a.tagName?a.parentNode.removeChild(a):w.clear.call({node:a}),a=b}})()});C.plugin(function(a,k,y,M){function A(a){var b=A.ps=A.ps||{};b[a]?b[a].sleep=100:b[a]={sleep:100};setTimeout(function(){for(var d in b)b[L](d)&&d!=a&&(b[d].sleep--,!b[d].sleep&&delete b[d])});return b[a]}function w(a,b,d,e){null==a&&(a=b=d=e=0);null==b&&(b=a.y,d=a.width,e=a.height,a=a.x);return{x:a,y:b,width:d,w:d,height:e,h:e,x2:a+d,y2:b+e,cx:a+d/2,cy:b+e/2,r1:F.min(d,e)/2,r2:F.max(d,e)/2,r0:F.sqrt(d*
d+e*e)/2,path:s(a,b,d,e),vb:[a,b,d,e].join(" ")}}function z(){return this.join(",").replace(N,"$1")}function d(a){a=C(a);a.toString=z;return a}function f(a,b,d,h,f,k,l,n,p){if(null==p)return e(a,b,d,h,f,k,l,n);if(0>p||e(a,b,d,h,f,k,l,n)<p)p=void 0;else{var q=0.5,O=1-q,s;for(s=e(a,b,d,h,f,k,l,n,O);0.01<Z(s-p);)q/=2,O+=(s<p?1:-1)*q,s=e(a,b,d,h,f,k,l,n,O);p=O}return u(a,b,d,h,f,k,l,n,p)}function n(b,d){function e(a){return+(+a).toFixed(3)}return a._.cacher(function(a,h,l){a instanceof k&&(a=a.attr("d"));
a=I(a);for(var n,p,D,q,O="",s={},c=0,t=0,r=a.length;t<r;t++){D=a[t];if("M"==D[0])n=+D[1],p=+D[2];else{q=f(n,p,D[1],D[2],D[3],D[4],D[5],D[6]);if(c+q>h){if(d&&!s.start){n=f(n,p,D[1],D[2],D[3],D[4],D[5],D[6],h-c);O+=["C"+e(n.start.x),e(n.start.y),e(n.m.x),e(n.m.y),e(n.x),e(n.y)];if(l)return O;s.start=O;O=["M"+e(n.x),e(n.y)+"C"+e(n.n.x),e(n.n.y),e(n.end.x),e(n.end.y),e(D[5]),e(D[6])].join();c+=q;n=+D[5];p=+D[6];continue}if(!b&&!d)return n=f(n,p,D[1],D[2],D[3],D[4],D[5],D[6],h-c)}c+=q;n=+D[5];p=+D[6]}O+=
D.shift()+D}s.end=O;return n=b?c:d?s:u(n,p,D[0],D[1],D[2],D[3],D[4],D[5],1)},null,a._.clone)}function u(a,b,d,e,h,f,k,l,n){var p=1-n,q=ma(p,3),s=ma(p,2),c=n*n,t=c*n,r=q*a+3*s*n*d+3*p*n*n*h+t*k,q=q*b+3*s*n*e+3*p*n*n*f+t*l,s=a+2*n*(d-a)+c*(h-2*d+a),t=b+2*n*(e-b)+c*(f-2*e+b),x=d+2*n*(h-d)+c*(k-2*h+d),c=e+2*n*(f-e)+c*(l-2*f+e);a=p*a+n*d;b=p*b+n*e;h=p*h+n*k;f=p*f+n*l;l=90-180*F.atan2(s-x,t-c)/S;return{x:r,y:q,m:{x:s,y:t},n:{x:x,y:c},start:{x:a,y:b},end:{x:h,y:f},alpha:l}}function p(b,d,e,h,f,n,k,l){a.is(b,
"array")||(b=[b,d,e,h,f,n,k,l]);b=U.apply(null,b);return w(b.min.x,b.min.y,b.max.x-b.min.x,b.max.y-b.min.y)}function b(a,b,d){return b>=a.x&&b<=a.x+a.width&&d>=a.y&&d<=a.y+a.height}function q(a,d){a=w(a);d=w(d);return b(d,a.x,a.y)||b(d,a.x2,a.y)||b(d,a.x,a.y2)||b(d,a.x2,a.y2)||b(a,d.x,d.y)||b(a,d.x2,d.y)||b(a,d.x,d.y2)||b(a,d.x2,d.y2)||(a.x<d.x2&&a.x>d.x||d.x<a.x2&&d.x>a.x)&&(a.y<d.y2&&a.y>d.y||d.y<a.y2&&d.y>a.y)}function e(a,b,d,e,h,f,n,k,l){null==l&&(l=1);l=(1<l?1:0>l?0:l)/2;for(var p=[-0.1252,
0.1252,-0.3678,0.3678,-0.5873,0.5873,-0.7699,0.7699,-0.9041,0.9041,-0.9816,0.9816],q=[0.2491,0.2491,0.2335,0.2335,0.2032,0.2032,0.1601,0.1601,0.1069,0.1069,0.0472,0.0472],s=0,c=0;12>c;c++)var t=l*p[c]+l,r=t*(t*(-3*a+9*d-9*h+3*n)+6*a-12*d+6*h)-3*a+3*d,t=t*(t*(-3*b+9*e-9*f+3*k)+6*b-12*e+6*f)-3*b+3*e,s=s+q[c]*F.sqrt(r*r+t*t);return l*s}function l(a,b,d){a=I(a);b=I(b);for(var h,f,l,n,k,s,r,O,x,c,t=d?0:[],w=0,v=a.length;w<v;w++)if(x=a[w],"M"==x[0])h=k=x[1],f=s=x[2];else{"C"==x[0]?(x=[h,f].concat(x.slice(1)),
h=x[6],f=x[7]):(x=[h,f,h,f,k,s,k,s],h=k,f=s);for(var G=0,y=b.length;G<y;G++)if(c=b[G],"M"==c[0])l=r=c[1],n=O=c[2];else{"C"==c[0]?(c=[l,n].concat(c.slice(1)),l=c[6],n=c[7]):(c=[l,n,l,n,r,O,r,O],l=r,n=O);var z;var K=x,B=c;z=d;var H=p(K),J=p(B);if(q(H,J)){for(var H=e.apply(0,K),J=e.apply(0,B),H=~~(H/8),J=~~(J/8),U=[],A=[],F={},M=z?0:[],P=0;P<H+1;P++){var C=u.apply(0,K.concat(P/H));U.push({x:C.x,y:C.y,t:P/H})}for(P=0;P<J+1;P++)C=u.apply(0,B.concat(P/J)),A.push({x:C.x,y:C.y,t:P/J});for(P=0;P<H;P++)for(K=
0;K<J;K++){var Q=U[P],L=U[P+1],B=A[K],C=A[K+1],N=0.001>Z(L.x-Q.x)?"y":"x",S=0.001>Z(C.x-B.x)?"y":"x",R;R=Q.x;var Y=Q.y,V=L.x,ea=L.y,fa=B.x,ga=B.y,ha=C.x,ia=C.y;if(W(R,V)<X(fa,ha)||X(R,V)>W(fa,ha)||W(Y,ea)<X(ga,ia)||X(Y,ea)>W(ga,ia))R=void 0;else{var $=(R*ea-Y*V)*(fa-ha)-(R-V)*(fa*ia-ga*ha),aa=(R*ea-Y*V)*(ga-ia)-(Y-ea)*(fa*ia-ga*ha),ja=(R-V)*(ga-ia)-(Y-ea)*(fa-ha);if(ja){var $=$/ja,aa=aa/ja,ja=+$.toFixed(2),ba=+aa.toFixed(2);R=ja<+X(R,V).toFixed(2)||ja>+W(R,V).toFixed(2)||ja<+X(fa,ha).toFixed(2)||
ja>+W(fa,ha).toFixed(2)||ba<+X(Y,ea).toFixed(2)||ba>+W(Y,ea).toFixed(2)||ba<+X(ga,ia).toFixed(2)||ba>+W(ga,ia).toFixed(2)?void 0:{x:$,y:aa}}else R=void 0}R&&F[R.x.toFixed(4)]!=R.y.toFixed(4)&&(F[R.x.toFixed(4)]=R.y.toFixed(4),Q=Q.t+Z((R[N]-Q[N])/(L[N]-Q[N]))*(L.t-Q.t),B=B.t+Z((R[S]-B[S])/(C[S]-B[S]))*(C.t-B.t),0<=Q&&1>=Q&&0<=B&&1>=B&&(z?M++:M.push({x:R.x,y:R.y,t1:Q,t2:B})))}z=M}else z=z?0:[];if(d)t+=z;else{H=0;for(J=z.length;H<J;H++)z[H].segment1=w,z[H].segment2=G,z[H].bez1=x,z[H].bez2=c;t=t.concat(z)}}}return t}
function r(a){var b=A(a);if(b.bbox)return C(b.bbox);if(!a)return w();a=I(a);for(var d=0,e=0,h=[],f=[],l,n=0,k=a.length;n<k;n++)l=a[n],"M"==l[0]?(d=l[1],e=l[2],h.push(d),f.push(e)):(d=U(d,e,l[1],l[2],l[3],l[4],l[5],l[6]),h=h.concat(d.min.x,d.max.x),f=f.concat(d.min.y,d.max.y),d=l[5],e=l[6]);a=X.apply(0,h);l=X.apply(0,f);h=W.apply(0,h);f=W.apply(0,f);f=w(a,l,h-a,f-l);b.bbox=C(f);return f}function s(a,b,d,e,h){if(h)return[["M",+a+ +h,b],["l",d-2*h,0],["a",h,h,0,0,1,h,h],["l",0,e-2*h],["a",h,h,0,0,1,
-h,h],["l",2*h-d,0],["a",h,h,0,0,1,-h,-h],["l",0,2*h-e],["a",h,h,0,0,1,h,-h],["z"]];a=[["M",a,b],["l",d,0],["l",0,e],["l",-d,0],["z"]];a.toString=z;return a}function x(a,b,d,e,h){null==h&&null==e&&(e=d);a=+a;b=+b;d=+d;e=+e;if(null!=h){var f=Math.PI/180,l=a+d*Math.cos(-e*f);a+=d*Math.cos(-h*f);var n=b+d*Math.sin(-e*f);b+=d*Math.sin(-h*f);d=[["M",l,n],["A",d,d,0,+(180<h-e),0,a,b]]}else d=[["M",a,b],["m",0,-e],["a",d,e,0,1,1,0,2*e],["a",d,e,0,1,1,0,-2*e],["z"]];d.toString=z;return d}function G(b){var e=
A(b);if(e.abs)return d(e.abs);Q(b,"array")&&Q(b&&b[0],"array")||(b=a.parsePathString(b));if(!b||!b.length)return[["M",0,0]];var h=[],f=0,l=0,n=0,k=0,p=0;"M"==b[0][0]&&(f=+b[0][1],l=+b[0][2],n=f,k=l,p++,h[0]=["M",f,l]);for(var q=3==b.length&&"M"==b[0][0]&&"R"==b[1][0].toUpperCase()&&"Z"==b[2][0].toUpperCase(),s,r,w=p,c=b.length;w<c;w++){h.push(s=[]);r=b[w];p=r[0];if(p!=p.toUpperCase())switch(s[0]=p.toUpperCase(),s[0]){case "A":s[1]=r[1];s[2]=r[2];s[3]=r[3];s[4]=r[4];s[5]=r[5];s[6]=+r[6]+f;s[7]=+r[7]+
l;break;case "V":s[1]=+r[1]+l;break;case "H":s[1]=+r[1]+f;break;case "R":for(var t=[f,l].concat(r.slice(1)),u=2,v=t.length;u<v;u++)t[u]=+t[u]+f,t[++u]=+t[u]+l;h.pop();h=h.concat(P(t,q));break;case "O":h.pop();t=x(f,l,r[1],r[2]);t.push(t[0]);h=h.concat(t);break;case "U":h.pop();h=h.concat(x(f,l,r[1],r[2],r[3]));s=["U"].concat(h[h.length-1].slice(-2));break;case "M":n=+r[1]+f,k=+r[2]+l;default:for(u=1,v=r.length;u<v;u++)s[u]=+r[u]+(u%2?f:l)}else if("R"==p)t=[f,l].concat(r.slice(1)),h.pop(),h=h.concat(P(t,
q)),s=["R"].concat(r.slice(-2));else if("O"==p)h.pop(),t=x(f,l,r[1],r[2]),t.push(t[0]),h=h.concat(t);else if("U"==p)h.pop(),h=h.concat(x(f,l,r[1],r[2],r[3])),s=["U"].concat(h[h.length-1].slice(-2));else for(t=0,u=r.length;t<u;t++)s[t]=r[t];p=p.toUpperCase();if("O"!=p)switch(s[0]){case "Z":f=+n;l=+k;break;case "H":f=s[1];break;case "V":l=s[1];break;case "M":n=s[s.length-2],k=s[s.length-1];default:f=s[s.length-2],l=s[s.length-1]}}h.toString=z;e.abs=d(h);return h}function h(a,b,d,e){return[a,b,d,e,d,
e]}function J(a,b,d,e,h,f){var l=1/3,n=2/3;return[l*a+n*d,l*b+n*e,l*h+n*d,l*f+n*e,h,f]}function K(b,d,e,h,f,l,n,k,p,s){var r=120*S/180,q=S/180*(+f||0),c=[],t,x=a._.cacher(function(a,b,c){var d=a*F.cos(c)-b*F.sin(c);a=a*F.sin(c)+b*F.cos(c);return{x:d,y:a}});if(s)v=s[0],t=s[1],l=s[2],u=s[3];else{t=x(b,d,-q);b=t.x;d=t.y;t=x(k,p,-q);k=t.x;p=t.y;F.cos(S/180*f);F.sin(S/180*f);t=(b-k)/2;v=(d-p)/2;u=t*t/(e*e)+v*v/(h*h);1<u&&(u=F.sqrt(u),e*=u,h*=u);var u=e*e,w=h*h,u=(l==n?-1:1)*F.sqrt(Z((u*w-u*v*v-w*t*t)/
(u*v*v+w*t*t)));l=u*e*v/h+(b+k)/2;var u=u*-h*t/e+(d+p)/2,v=F.asin(((d-u)/h).toFixed(9));t=F.asin(((p-u)/h).toFixed(9));v=b<l?S-v:v;t=k<l?S-t:t;0>v&&(v=2*S+v);0>t&&(t=2*S+t);n&&v>t&&(v-=2*S);!n&&t>v&&(t-=2*S)}if(Z(t-v)>r){var c=t,w=k,G=p;t=v+r*(n&&t>v?1:-1);k=l+e*F.cos(t);p=u+h*F.sin(t);c=K(k,p,e,h,f,0,n,w,G,[t,c,l,u])}l=t-v;f=F.cos(v);r=F.sin(v);n=F.cos(t);t=F.sin(t);l=F.tan(l/4);e=4/3*e*l;l*=4/3*h;h=[b,d];b=[b+e*r,d-l*f];d=[k+e*t,p-l*n];k=[k,p];b[0]=2*h[0]-b[0];b[1]=2*h[1]-b[1];if(s)return[b,d,k].concat(c);
c=[b,d,k].concat(c).join().split(",");s=[];k=0;for(p=c.length;k<p;k++)s[k]=k%2?x(c[k-1],c[k],q).y:x(c[k],c[k+1],q).x;return s}function U(a,b,d,e,h,f,l,k){for(var n=[],p=[[],[]],s,r,c,t,q=0;2>q;++q)0==q?(r=6*a-12*d+6*h,s=-3*a+9*d-9*h+3*l,c=3*d-3*a):(r=6*b-12*e+6*f,s=-3*b+9*e-9*f+3*k,c=3*e-3*b),1E-12>Z(s)?1E-12>Z(r)||(s=-c/r,0<s&&1>s&&n.push(s)):(t=r*r-4*c*s,c=F.sqrt(t),0>t||(t=(-r+c)/(2*s),0<t&&1>t&&n.push(t),s=(-r-c)/(2*s),0<s&&1>s&&n.push(s)));for(r=q=n.length;q--;)s=n[q],c=1-s,p[0][q]=c*c*c*a+3*
c*c*s*d+3*c*s*s*h+s*s*s*l,p[1][q]=c*c*c*b+3*c*c*s*e+3*c*s*s*f+s*s*s*k;p[0][r]=a;p[1][r]=b;p[0][r+1]=l;p[1][r+1]=k;p[0].length=p[1].length=r+2;return{min:{x:X.apply(0,p[0]),y:X.apply(0,p[1])},max:{x:W.apply(0,p[0]),y:W.apply(0,p[1])}}}function I(a,b){var e=!b&&A(a);if(!b&&e.curve)return d(e.curve);var f=G(a),l=b&&G(b),n={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},k={x:0,y:0,bx:0,by:0,X:0,Y:0,qx:null,qy:null},p=function(a,b,c){if(!a)return["C",b.x,b.y,b.x,b.y,b.x,b.y];a[0]in{T:1,Q:1}||(b.qx=b.qy=null);
switch(a[0]){case "M":b.X=a[1];b.Y=a[2];break;case "A":a=["C"].concat(K.apply(0,[b.x,b.y].concat(a.slice(1))));break;case "S":"C"==c||"S"==c?(c=2*b.x-b.bx,b=2*b.y-b.by):(c=b.x,b=b.y);a=["C",c,b].concat(a.slice(1));break;case "T":"Q"==c||"T"==c?(b.qx=2*b.x-b.qx,b.qy=2*b.y-b.qy):(b.qx=b.x,b.qy=b.y);a=["C"].concat(J(b.x,b.y,b.qx,b.qy,a[1],a[2]));break;case "Q":b.qx=a[1];b.qy=a[2];a=["C"].concat(J(b.x,b.y,a[1],a[2],a[3],a[4]));break;case "L":a=["C"].concat(h(b.x,b.y,a[1],a[2]));break;case "H":a=["C"].concat(h(b.x,
b.y,a[1],b.y));break;case "V":a=["C"].concat(h(b.x,b.y,b.x,a[1]));break;case "Z":a=["C"].concat(h(b.x,b.y,b.X,b.Y))}return a},s=function(a,b){if(7<a[b].length){a[b].shift();for(var c=a[b];c.length;)q[b]="A",l&&(u[b]="A"),a.splice(b++,0,["C"].concat(c.splice(0,6)));a.splice(b,1);v=W(f.length,l&&l.length||0)}},r=function(a,b,c,d,e){a&&b&&"M"==a[e][0]&&"M"!=b[e][0]&&(b.splice(e,0,["M",d.x,d.y]),c.bx=0,c.by=0,c.x=a[e][1],c.y=a[e][2],v=W(f.length,l&&l.length||0))},q=[],u=[],c="",t="",x=0,v=W(f.length,
l&&l.length||0);for(;x<v;x++){f[x]&&(c=f[x][0]);"C"!=c&&(q[x]=c,x&&(t=q[x-1]));f[x]=p(f[x],n,t);"A"!=q[x]&&"C"==c&&(q[x]="C");s(f,x);l&&(l[x]&&(c=l[x][0]),"C"!=c&&(u[x]=c,x&&(t=u[x-1])),l[x]=p(l[x],k,t),"A"!=u[x]&&"C"==c&&(u[x]="C"),s(l,x));r(f,l,n,k,x);r(l,f,k,n,x);var w=f[x],z=l&&l[x],y=w.length,U=l&&z.length;n.x=w[y-2];n.y=w[y-1];n.bx=$(w[y-4])||n.x;n.by=$(w[y-3])||n.y;k.bx=l&&($(z[U-4])||k.x);k.by=l&&($(z[U-3])||k.y);k.x=l&&z[U-2];k.y=l&&z[U-1]}l||(e.curve=d(f));return l?[f,l]:f}function P(a,
b){for(var d=[],e=0,h=a.length;h-2*!b>e;e+=2){var f=[{x:+a[e-2],y:+a[e-1]},{x:+a[e],y:+a[e+1]},{x:+a[e+2],y:+a[e+3]},{x:+a[e+4],y:+a[e+5]}];b?e?h-4==e?f[3]={x:+a[0],y:+a[1]}:h-2==e&&(f[2]={x:+a[0],y:+a[1]},f[3]={x:+a[2],y:+a[3]}):f[0]={x:+a[h-2],y:+a[h-1]}:h-4==e?f[3]=f[2]:e||(f[0]={x:+a[e],y:+a[e+1]});d.push(["C",(-f[0].x+6*f[1].x+f[2].x)/6,(-f[0].y+6*f[1].y+f[2].y)/6,(f[1].x+6*f[2].x-f[3].x)/6,(f[1].y+6*f[2].y-f[3].y)/6,f[2].x,f[2].y])}return d}y=k.prototype;var Q=a.is,C=a._.clone,L="hasOwnProperty",
N=/,?([a-z]),?/gi,$=parseFloat,F=Math,S=F.PI,X=F.min,W=F.max,ma=F.pow,Z=F.abs;M=n(1);var na=n(),ba=n(0,1),V=a._unit2px;a.path=A;a.path.getTotalLength=M;a.path.getPointAtLength=na;a.path.getSubpath=function(a,b,d){if(1E-6>this.getTotalLength(a)-d)return ba(a,b).end;a=ba(a,d,1);return b?ba(a,b).end:a};y.getTotalLength=function(){if(this.node.getTotalLength)return this.node.getTotalLength()};y.getPointAtLength=function(a){return na(this.attr("d"),a)};y.getSubpath=function(b,d){return a.path.getSubpath(this.attr("d"),
b,d)};a._.box=w;a.path.findDotsAtSegment=u;a.path.bezierBBox=p;a.path.isPointInsideBBox=b;a.path.isBBoxIntersect=q;a.path.intersection=function(a,b){return l(a,b)};a.path.intersectionNumber=function(a,b){return l(a,b,1)};a.path.isPointInside=function(a,d,e){var h=r(a);return b(h,d,e)&&1==l(a,[["M",d,e],["H",h.x2+10]],1)%2};a.path.getBBox=r;a.path.get={path:function(a){return a.attr("path")},circle:function(a){a=V(a);return x(a.cx,a.cy,a.r)},ellipse:function(a){a=V(a);return x(a.cx||0,a.cy||0,a.rx,
a.ry)},rect:function(a){a=V(a);return s(a.x||0,a.y||0,a.width,a.height,a.rx,a.ry)},image:function(a){a=V(a);return s(a.x||0,a.y||0,a.width,a.height)},line:function(a){return"M"+[a.attr("x1")||0,a.attr("y1")||0,a.attr("x2"),a.attr("y2")]},polyline:function(a){return"M"+a.attr("points")},polygon:function(a){return"M"+a.attr("points")+"z"},deflt:function(a){a=a.node.getBBox();return s(a.x,a.y,a.width,a.height)}};a.path.toRelative=function(b){var e=A(b),h=String.prototype.toLowerCase;if(e.rel)return d(e.rel);
a.is(b,"array")&&a.is(b&&b[0],"array")||(b=a.parsePathString(b));var f=[],l=0,n=0,k=0,p=0,s=0;"M"==b[0][0]&&(l=b[0][1],n=b[0][2],k=l,p=n,s++,f.push(["M",l,n]));for(var r=b.length;s<r;s++){var q=f[s]=[],x=b[s];if(x[0]!=h.call(x[0]))switch(q[0]=h.call(x[0]),q[0]){case "a":q[1]=x[1];q[2]=x[2];q[3]=x[3];q[4]=x[4];q[5]=x[5];q[6]=+(x[6]-l).toFixed(3);q[7]=+(x[7]-n).toFixed(3);break;case "v":q[1]=+(x[1]-n).toFixed(3);break;case "m":k=x[1],p=x[2];default:for(var c=1,t=x.length;c<t;c++)q[c]=+(x[c]-(c%2?l:
n)).toFixed(3)}else for(f[s]=[],"m"==x[0]&&(k=x[1]+l,p=x[2]+n),q=0,c=x.length;q<c;q++)f[s][q]=x[q];x=f[s].length;switch(f[s][0]){case "z":l=k;n=p;break;case "h":l+=+f[s][x-1];break;case "v":n+=+f[s][x-1];break;default:l+=+f[s][x-2],n+=+f[s][x-1]}}f.toString=z;e.rel=d(f);return f};a.path.toAbsolute=G;a.path.toCubic=I;a.path.map=function(a,b){if(!b)return a;var d,e,h,f,l,n,k;a=I(a);h=0;for(l=a.length;h<l;h++)for(k=a[h],f=1,n=k.length;f<n;f+=2)d=b.x(k[f],k[f+1]),e=b.y(k[f],k[f+1]),k[f]=d,k[f+1]=e;return a};
a.path.toString=z;a.path.clone=d});C.plugin(function(a,v,y,C){var A=Math.max,w=Math.min,z=function(a){this.items=[];this.bindings={};this.length=0;this.type="set";if(a)for(var f=0,n=a.length;f<n;f++)a[f]&&(this[this.items.length]=this.items[this.items.length]=a[f],this.length++)};v=z.prototype;v.push=function(){for(var a,f,n=0,k=arguments.length;n<k;n++)if(a=arguments[n])f=this.items.length,this[f]=this.items[f]=a,this.length++;return this};v.pop=function(){this.length&&delete this[this.length--];
return this.items.pop()};v.forEach=function(a,f){for(var n=0,k=this.items.length;n<k&&!1!==a.call(f,this.items[n],n);n++);return this};v.animate=function(d,f,n,u){"function"!=typeof n||n.length||(u=n,n=L.linear);d instanceof a._.Animation&&(u=d.callback,n=d.easing,f=n.dur,d=d.attr);var p=arguments;if(a.is(d,"array")&&a.is(p[p.length-1],"array"))var b=!0;var q,e=function(){q?this.b=q:q=this.b},l=0,r=u&&function(){l++==this.length&&u.call(this)};return this.forEach(function(a,l){k.once("snap.animcreated."+
a.id,e);b?p[l]&&a.animate.apply(a,p[l]):a.animate(d,f,n,r)})};v.remove=function(){for(;this.length;)this.pop().remove();return this};v.bind=function(a,f,k){var u={};if("function"==typeof f)this.bindings[a]=f;else{var p=k||a;this.bindings[a]=function(a){u[p]=a;f.attr(u)}}return this};v.attr=function(a){var f={},k;for(k in a)if(this.bindings[k])this.bindings[k](a[k]);else f[k]=a[k];a=0;for(k=this.items.length;a<k;a++)this.items[a].attr(f);return this};v.clear=function(){for(;this.length;)this.pop()};
v.splice=function(a,f,k){a=0>a?A(this.length+a,0):a;f=A(0,w(this.length-a,f));var u=[],p=[],b=[],q;for(q=2;q<arguments.length;q++)b.push(arguments[q]);for(q=0;q<f;q++)p.push(this[a+q]);for(;q<this.length-a;q++)u.push(this[a+q]);var e=b.length;for(q=0;q<e+u.length;q++)this.items[a+q]=this[a+q]=q<e?b[q]:u[q-e];for(q=this.items.length=this.length-=f-e;this[q];)delete this[q++];return new z(p)};v.exclude=function(a){for(var f=0,k=this.length;f<k;f++)if(this[f]==a)return this.splice(f,1),!0;return!1};
v.insertAfter=function(a){for(var f=this.items.length;f--;)this.items[f].insertAfter(a);return this};v.getBBox=function(){for(var a=[],f=[],k=[],u=[],p=this.items.length;p--;)if(!this.items[p].removed){var b=this.items[p].getBBox();a.push(b.x);f.push(b.y);k.push(b.x+b.width);u.push(b.y+b.height)}a=w.apply(0,a);f=w.apply(0,f);k=A.apply(0,k);u=A.apply(0,u);return{x:a,y:f,x2:k,y2:u,width:k-a,height:u-f,cx:a+(k-a)/2,cy:f+(u-f)/2}};v.clone=function(a){a=new z;for(var f=0,k=this.items.length;f<k;f++)a.push(this.items[f].clone());
return a};v.toString=function(){return"Snap\u2018s set"};v.type="set";a.set=function(){var a=new z;arguments.length&&a.push.apply(a,Array.prototype.slice.call(arguments,0));return a}});C.plugin(function(a,v,y,C){function A(a){var b=a[0];switch(b.toLowerCase()){case "t":return[b,0,0];case "m":return[b,1,0,0,1,0,0];case "r":return 4==a.length?[b,0,a[2],a[3]]:[b,0];case "s":return 5==a.length?[b,1,1,a[3],a[4]]:3==a.length?[b,1,1]:[b,1]}}function w(b,d,f){d=q(d).replace(/\.{3}|\u2026/g,b);b=a.parseTransformString(b)||
[];d=a.parseTransformString(d)||[];for(var k=Math.max(b.length,d.length),p=[],v=[],h=0,w,z,y,I;h<k;h++){y=b[h]||A(d[h]);I=d[h]||A(y);if(y[0]!=I[0]||"r"==y[0].toLowerCase()&&(y[2]!=I[2]||y[3]!=I[3])||"s"==y[0].toLowerCase()&&(y[3]!=I[3]||y[4]!=I[4])){b=a._.transform2matrix(b,f());d=a._.transform2matrix(d,f());p=[["m",b.a,b.b,b.c,b.d,b.e,b.f]];v=[["m",d.a,d.b,d.c,d.d,d.e,d.f]];break}p[h]=[];v[h]=[];w=0;for(z=Math.max(y.length,I.length);w<z;w++)w in y&&(p[h][w]=y[w]),w in I&&(v[h][w]=I[w])}return{from:u(p),
to:u(v),f:n(p)}}function z(a){return a}function d(a){return function(b){return+b.toFixed(3)+a}}function f(b){return a.rgb(b[0],b[1],b[2])}function n(a){var b=0,d,f,k,n,h,p,q=[];d=0;for(f=a.length;d<f;d++){h="[";p=['"'+a[d][0]+'"'];k=1;for(n=a[d].length;k<n;k++)p[k]="val["+b++ +"]";h+=p+"]";q[d]=h}return Function("val","return Snap.path.toString.call(["+q+"])")}function u(a){for(var b=[],d=0,f=a.length;d<f;d++)for(var k=1,n=a[d].length;k<n;k++)b.push(a[d][k]);return b}var p={},b=/[a-z]+$/i,q=String;
p.stroke=p.fill="colour";v.prototype.equal=function(a,b){return k("snap.util.equal",this,a,b).firstDefined()};k.on("snap.util.equal",function(e,k){var r,s;r=q(this.attr(e)||"");var x=this;if(r==+r&&k==+k)return{from:+r,to:+k,f:z};if("colour"==p[e])return r=a.color(r),s=a.color(k),{from:[r.r,r.g,r.b,r.opacity],to:[s.r,s.g,s.b,s.opacity],f:f};if("transform"==e||"gradientTransform"==e||"patternTransform"==e)return k instanceof a.Matrix&&(k=k.toTransformString()),a._.rgTransform.test(k)||(k=a._.svgTransform2string(k)),
w(r,k,function(){return x.getBBox(1)});if("d"==e||"path"==e)return r=a.path.toCubic(r,k),{from:u(r[0]),to:u(r[1]),f:n(r[0])};if("points"==e)return r=q(r).split(a._.separator),s=q(k).split(a._.separator),{from:r,to:s,f:function(a){return a}};aUnit=r.match(b);s=q(k).match(b);return aUnit&&aUnit==s?{from:parseFloat(r),to:parseFloat(k),f:d(aUnit)}:{from:this.asPX(e),to:this.asPX(e,k),f:z}})});C.plugin(function(a,v,y,C){var A=v.prototype,w="createTouch"in C.doc;v="click dblclick mousedown mousemove mouseout mouseover mouseup touchstart touchmove touchend touchcancel".split(" ");
var z={mousedown:"touchstart",mousemove:"touchmove",mouseup:"touchend"},d=function(a,b){var d="y"==a?"scrollTop":"scrollLeft",e=b&&b.node?b.node.ownerDocument:C.doc;return e[d in e.documentElement?"documentElement":"body"][d]},f=function(){this.returnValue=!1},n=function(){return this.originalEvent.preventDefault()},u=function(){this.cancelBubble=!0},p=function(){return this.originalEvent.stopPropagation()},b=function(){if(C.doc.addEventListener)return function(a,b,e,f){var k=w&&z[b]?z[b]:b,l=function(k){var l=
d("y",f),q=d("x",f);if(w&&z.hasOwnProperty(b))for(var r=0,u=k.targetTouches&&k.targetTouches.length;r<u;r++)if(k.targetTouches[r].target==a||a.contains(k.targetTouches[r].target)){u=k;k=k.targetTouches[r];k.originalEvent=u;k.preventDefault=n;k.stopPropagation=p;break}return e.call(f,k,k.clientX+q,k.clientY+l)};b!==k&&a.addEventListener(b,l,!1);a.addEventListener(k,l,!1);return function(){b!==k&&a.removeEventListener(b,l,!1);a.removeEventListener(k,l,!1);return!0}};if(C.doc.attachEvent)return function(a,
b,e,h){var k=function(a){a=a||h.node.ownerDocument.window.event;var b=d("y",h),k=d("x",h),k=a.clientX+k,b=a.clientY+b;a.preventDefault=a.preventDefault||f;a.stopPropagation=a.stopPropagation||u;return e.call(h,a,k,b)};a.attachEvent("on"+b,k);return function(){a.detachEvent("on"+b,k);return!0}}}(),q=[],e=function(a){for(var b=a.clientX,e=a.clientY,f=d("y"),l=d("x"),n,p=q.length;p--;){n=q[p];if(w)for(var r=a.touches&&a.touches.length,u;r--;){if(u=a.touches[r],u.identifier==n.el._drag.id||n.el.node.contains(u.target)){b=
u.clientX;e=u.clientY;(a.originalEvent?a.originalEvent:a).preventDefault();break}}else a.preventDefault();b+=l;e+=f;k("snap.drag.move."+n.el.id,n.move_scope||n.el,b-n.el._drag.x,e-n.el._drag.y,b,e,a)}},l=function(b){a.unmousemove(e).unmouseup(l);for(var d=q.length,f;d--;)f=q[d],f.el._drag={},k("snap.drag.end."+f.el.id,f.end_scope||f.start_scope||f.move_scope||f.el,b);q=[]};for(y=v.length;y--;)(function(d){a[d]=A[d]=function(e,f){a.is(e,"function")&&(this.events=this.events||[],this.events.push({name:d,
f:e,unbind:b(this.node||document,d,e,f||this)}));return this};a["un"+d]=A["un"+d]=function(a){for(var b=this.events||[],e=b.length;e--;)if(b[e].name==d&&(b[e].f==a||!a)){b[e].unbind();b.splice(e,1);!b.length&&delete this.events;break}return this}})(v[y]);A.hover=function(a,b,d,e){return this.mouseover(a,d).mouseout(b,e||d)};A.unhover=function(a,b){return this.unmouseover(a).unmouseout(b)};var r=[];A.drag=function(b,d,f,h,n,p){function u(r,v,w){(r.originalEvent||r).preventDefault();this._drag.x=v;
this._drag.y=w;this._drag.id=r.identifier;!q.length&&a.mousemove(e).mouseup(l);q.push({el:this,move_scope:h,start_scope:n,end_scope:p});d&&k.on("snap.drag.start."+this.id,d);b&&k.on("snap.drag.move."+this.id,b);f&&k.on("snap.drag.end."+this.id,f);k("snap.drag.start."+this.id,n||h||this,v,w,r)}if(!arguments.length){var v;return this.drag(function(a,b){this.attr({transform:v+(v?"T":"t")+[a,b]})},function(){v=this.transform().local})}this._drag={};r.push({el:this,start:u});this.mousedown(u);return this};
A.undrag=function(){for(var b=r.length;b--;)r[b].el==this&&(this.unmousedown(r[b].start),r.splice(b,1),k.unbind("snap.drag.*."+this.id));!r.length&&a.unmousemove(e).unmouseup(l);return this}});C.plugin(function(a,v,y,C){y=y.prototype;var A=/^\s*url\((.+)\)/,w=String,z=a._.$;a.filter={};y.filter=function(d){var f=this;"svg"!=f.type&&(f=f.paper);d=a.parse(w(d));var k=a._.id(),u=z("filter");z(u,{id:k,filterUnits:"userSpaceOnUse"});u.appendChild(d.node);f.defs.appendChild(u);return new v(u)};k.on("snap.util.getattr.filter",
function(){k.stop();var d=z(this.node,"filter");if(d)return(d=w(d).match(A))&&a.select(d[1])});k.on("snap.util.attr.filter",function(d){if(d instanceof v&&"filter"==d.type){k.stop();var f=d.node.id;f||(z(d.node,{id:d.id}),f=d.id);z(this.node,{filter:a.url(f)})}d&&"none"!=d||(k.stop(),this.node.removeAttribute("filter"))});a.filter.blur=function(d,f){null==d&&(d=2);return a.format('<feGaussianBlur stdDeviation="{def}"/>',{def:null==f?d:[d,f]})};a.filter.blur.toString=function(){return this()};a.filter.shadow=
function(d,f,k,u,p){"string"==typeof k&&(p=u=k,k=4);"string"!=typeof u&&(p=u,u="#000");null==k&&(k=4);null==p&&(p=1);null==d&&(d=0,f=2);null==f&&(f=d);u=a.color(u||"#000");return a.format('<feGaussianBlur in="SourceAlpha" stdDeviation="{blur}"/><feOffset dx="{dx}" dy="{dy}" result="offsetblur"/><feFlood flood-color="{color}"/><feComposite in2="offsetblur" operator="in"/><feComponentTransfer><feFuncA type="linear" slope="{opacity}"/></feComponentTransfer><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>',
{color:u,dx:d,dy:f,blur:k,opacity:p})};a.filter.shadow.toString=function(){return this()};a.filter.grayscale=function(d){null==d&&(d=1);return a.format('<feColorMatrix type="matrix" values="{a} {b} {c} 0 0 {d} {e} {f} 0 0 {g} {b} {h} 0 0 0 0 0 1 0"/>',{a:0.2126+0.7874*(1-d),b:0.7152-0.7152*(1-d),c:0.0722-0.0722*(1-d),d:0.2126-0.2126*(1-d),e:0.7152+0.2848*(1-d),f:0.0722-0.0722*(1-d),g:0.2126-0.2126*(1-d),h:0.0722+0.9278*(1-d)})};a.filter.grayscale.toString=function(){return this()};a.filter.sepia=
function(d){null==d&&(d=1);return a.format('<feColorMatrix type="matrix" values="{a} {b} {c} 0 0 {d} {e} {f} 0 0 {g} {h} {i} 0 0 0 0 0 1 0"/>',{a:0.393+0.607*(1-d),b:0.769-0.769*(1-d),c:0.189-0.189*(1-d),d:0.349-0.349*(1-d),e:0.686+0.314*(1-d),f:0.168-0.168*(1-d),g:0.272-0.272*(1-d),h:0.534-0.534*(1-d),i:0.131+0.869*(1-d)})};a.filter.sepia.toString=function(){return this()};a.filter.saturate=function(d){null==d&&(d=1);return a.format('<feColorMatrix type="saturate" values="{amount}"/>',{amount:1-
d})};a.filter.saturate.toString=function(){return this()};a.filter.hueRotate=function(d){return a.format('<feColorMatrix type="hueRotate" values="{angle}"/>',{angle:d||0})};a.filter.hueRotate.toString=function(){return this()};a.filter.invert=function(d){null==d&&(d=1);return a.format('<feComponentTransfer><feFuncR type="table" tableValues="{amount} {amount2}"/><feFuncG type="table" tableValues="{amount} {amount2}"/><feFuncB type="table" tableValues="{amount} {amount2}"/></feComponentTransfer>',{amount:d,
amount2:1-d})};a.filter.invert.toString=function(){return this()};a.filter.brightness=function(d){null==d&&(d=1);return a.format('<feComponentTransfer><feFuncR type="linear" slope="{amount}"/><feFuncG type="linear" slope="{amount}"/><feFuncB type="linear" slope="{amount}"/></feComponentTransfer>',{amount:d})};a.filter.brightness.toString=function(){return this()};a.filter.contrast=function(d){null==d&&(d=1);return a.format('<feComponentTransfer><feFuncR type="linear" slope="{amount}" intercept="{amount2}"/><feFuncG type="linear" slope="{amount}" intercept="{amount2}"/><feFuncB type="linear" slope="{amount}" intercept="{amount2}"/></feComponentTransfer>',
{amount:d,amount2:0.5-d/2})};a.filter.contrast.toString=function(){return this()}});return C});
================================================
FILE: docs/Project.toml
================================================
[deps]
Cairo = "159f3aea-2a34-519c-b102-8c37f9878175"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
Compose = "a81c6b42-2e10-5240-aca2-a61377ecd94b"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Fontconfig = "186bb1d3-e1f7-5a2c-a377-96d770f13627"
Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
================================================
FILE: docs/make.jl
================================================
using Documenter, Compose
import Cairo
struct SVGJSWritable{T}
x :: T
end
Base.show(io::IO, m::MIME"text/html", x::SVGJSWritable) = show(io, m, x.x)
makedocs(
modules = [Compose],
clean = false,
sitename = "Compose.jl",
pages = Any[
"Home" => "index.md",
"Tutorial" => "tutorial.md",
"Gallery" => Any[
"Forms" => "gallery/forms.md",
"Properties"=> "gallery/properties.md",
"Transformations"=> "gallery/transforms.md",
],
"Library" => "library.md"
]
)
deploydocs(
repo = "github.com/GiovineItalia/Compose.jl.git",
)
================================================
FILE: docs/src/gallery/forms.md
================================================
```@meta
Author = ["Mattriks"]
```
# [Forms](@id forms_gallery)
## [`arc`](@ref)
```@example
using Compose
set_default_graphic_size(8cm,4cm)
colv = ["red","orange","green","blue", "purple"]
a = range(-π/4, stop=7π/4, length=6)+ 0.2*randn(6)
a[6] = a[1]
img1 = compose(context(),
(context(), arc([0.5], [0.5], [0.3], [4.5π/4,π/4] , [7.5π/4,3π/4], [true,false]),
stroke("black"), fill(["red","white"])) )
img2 = compose(context(),
(context(), arc([0.5], [0.5], [0.3], a[1:5], a[2:6]),
stroke(colv), fill("transparent"), linewidth(2mm)) )
hstack(img1, img2)
```
## [`bezigon`](@ref)
```@example
using Colors, Compose
set_default_graphic_size(14cm,10cm)
petal = [[(0.4, 0.4), (0.4, 0.2), (0.5, 0.0)], [(0.6, 0.2), (0.6, 0.4), (0.5, 0.5)]]
petalf(θ::Float64) = (context(rotation=Rotation(θ, 0.5,0.5)),
bezigon((0.5, 0.5), petal), fill(LCHuvA(70.,50., 360*θ/2π, 0.4)))
theta = range(π/20, 2π, step=2π/10).-π
img = compose(context(), petalf.(theta)...)
```
## [`bitmap`](@ref)
```@example
using Main: SVGJSWritable #hide
using Compose
set_default_graphic_size(14cm,4cm)
rawimg = read(joinpath(@__DIR__,"..","assets/smiley.png"));
X = 0.9*rand(10,2)
img = compose(context(),
(context(), rectangle(), fill("transparent"), stroke("orange")),
(context(), bitmap(["image/png"], [rawimg], X[:,1], X[:,2], [0.1], [0.1]))
)
SVGJSWritable(ans) #hide
```
## [`circle`](@ref)
```@example
using Colors, Compose
set_default_graphic_size(14cm,4cm)
colv = HSVA.([0:30:179;], 1, 1, 0.5)
img = compose(context(units=UnitBox(0,0,40,8)),
(context(), circle([5.0:6:35;], [4], [4]), fill(colv), stroke("black"))
)
```
## [`curve`](@ref)
```@example
using Colors, Compose
set_default_graphic_size(14cm, 4cm)
epoint(x) = [(x,y) for y in rand(10)]
cpoint(t=0) = [(t+x,y) for (x,y) in zip(rand(10), 0.5*rand(10))]
colv = range(colorant"blue",stop=colorant"orange", length=10)
img = compose(context(units=UnitBox(0,0,2,1)),
(context(), curve([(0.5,1.0)], cpoint(), cpoint(), epoint(0.5)), stroke(colv)),
(context(), curve([(1.5,1.0)], cpoint(1), cpoint(1), epoint(1.5)), stroke(colv))
)
```
## [`ellipse`](@ref)
```@example
using Colors, Compose
set_default_graphic_size(14cm, 4cm)
colv1 = HSVA.([0:30:179;], 1, 1, 0.5)
r = 2*[1:6;]/24
colv2 = HSVA.([0:15:179;], 1, 1, 0.3)
θ = collect(range(0, stop=1.9π, length=10))
rl = 0.5*rand(10)
rw = 0.3*rand(10)
rot = Rotation.(θ, 1.5, 0.5)
ellipsef(i::Int) = ellipse(1.5, 0.5, rl[i], rw[i])
img = compose(context(units=UnitBox(0,0,2,1)),
(context(), ellipse(r,[0.5],r,reverse(r)), stroke("black"), fill(colv1)),
[(context(rotation=rot[i]), ellipsef(i), fill(colv2[i]), stroke("black")) for i in 1:10]...
)
```
## [`line`](@ref)
```@example
using Compose
set_default_graphic_size(10cm, 10cm)
θ = collect(range(0, stop=2π, length=60))
point_array = [[(0,0.75), (x,y)] for (x,y) in zip(cos.(θ), sin.(θ))]
img = compose(context(),
(context(), rectangle(), fill("salmon"), fillopacity(0.3)),
(context(0.12, 0.12, 0.76, 0.76, units=UnitBox(-1,-1,2,2)),
line(point_array), stroke("gold"), linewidth(1mm))
)
```
## [`ngon`](@ref), [`star`](@ref), [`xgon`](@ref)
```@example
using Compose
set_default_graphic_size(14cm, 5cm)
rainbow = ["orange","green","indigo",
"darkviolet","indigo","blue","green","yellow","orange","red"]
properties = [fillopacity(0.5), fill(rainbow), stroke("black")]
npoints = [7,5,3,2,3,4,5,6,7,8]
X = range(0.06, stop=0.94, length=10)
radii = 0.035*[-ones(3); ones(7)]
p = compose(context(),
(context(), ngon(X, [0.16], radii, npoints),
star(X, [0.5], radii, npoints),
xgon(X, [0.84], radii, npoints), properties...))
```
## [`polygon`](@ref)
```@example
using Statistics, Compose
set_default_graphic_size(10cm,10cm)
X = randn(50,2)
X = 0.3*(X .- mean(X,dims=1))./std(X,dims=1)
hp = hypot.(X[:,1],X[:,2])
i = hp .> Statistics.quantile(hp, 0.82)
Z = X[i,:]
θ = atan.(Z[:,1], Z[:,2])
ord = sortperm(θ)
polypoints = [(x,y) for (x,y) in zip(Z[ord,1],Z[ord,2])]
img = compose(context(units=UnitBox(-1,-1, 2,2)),
(context(), line([(-1,-1), (-1,1), (1,1)]), stroke("black")),
(context(), circle(0,0,0.02), fill("red")),
(context(), circle(X[:,1],X[:,2],[0.02]), fill("transparent"),stroke("deepskyblue")),
(context(), polygon(polypoints), fill("red"), fillopacity(0.1))
)
```
## [`rectangle`](@ref)
```@example
using Colors, Compose
set_default_graphic_size(14cm,4cm)
colv = HSVA.([0:15:179;], 1, 1, 0.3)
X = 0.9*rand(10,2)
rl = 0.3*rand(10).+0.03
rw = 0.3*rand(10).+0.03
img = compose(context(),
(context(), rectangle(), fill("transparent"), stroke("orange")),
(context(), rectangle(X[:,1], X[:,2], rl, rw), fill(colv), stroke("black"))
)
```
## [`sector`](@ref)
```@example
using Compose
set_default_graphic_size(14cm, 4cm)
colv = ["red","orange","green","blue", "purple"]
a = range(-π/4, stop=7π/4, length=6)+ 0.2*randn(6)
a[6] = a[1]
sectorobj = sector([0.5], [0.5], [0.3], a[1:5], a[2:6])
img1 = compose(context(),
(context(), sectorobj, fill(colv)) )
img2 = compose(context(),
(context(), sectorobj, stroke("white"), fill(colv), linewidth(1.4mm)) )
img3 = compose(context(),
(context(), sectorobj, stroke(colv), fill("transparent"), linewidth(1.4mm)) )
hstack(img1, img2, img3)
```
## [`text`](@ref)
```@example
using Colors, Compose
set_default_graphic_size(10cm,10cm)
labels=rand(string.(names(Base)[280:end]), 30)
θ = collect(range(0, stop=58π/30, length=30))
X = 1 .+ 0.7*[cos.(θ) sin.(θ)]
colv = range(colorant"blue",stop=colorant"orange", length=30)
rot = Rotation.(θ, X[:,1], X[:,2])
img = compose(context(units=UnitBox(0,0,2,2)),
(context(), text(1, 1, "Julia", hcenter, vcenter), stroke("red"), fontsize(30pt)),
(context(), text(X[:,1], X[:,2], labels, [hcenter], [vcenter], rot), stroke(colv))
)
```
```@example
using Compose
set_default_graphic_size(10cm,8cm)
# This graphic illustrates text alignment
txt = [x*"\n"*y for x in ["hleft", "hcenter","hright"],
y in ["vtop","vcenter","vbottom"] ]
x = repeat(0.1w.*[1,5,9], outer=3)
y = repeat(0.1h.*[1,5,9], inner=3)
xp = repeat([hleft,hcenter,hright], outer=3)
yp = repeat([vtop,vcenter,vbottom], inner=3)
img = compose(context(),
(context(), circle(x, y, [0.01]), fill("red")),
text(x, y, txt, xp, yp), fontsize(14pt)
)
```
================================================
FILE: docs/src/gallery/properties.md
================================================
```@meta
Author = ["Mattriks"]
```
# [Properties](@id properties_gallery)
## [`arrow`](@ref)
```@example
using Compose
set_default_graphic_size(14cm,5cm)
θ, r = 2π*rand(3), 0.1.+0.08*rand(3)
c, s = r.*cos.(θ), r.*sin.(θ)
point_array = [[(0.5,0.5), 0.5.+(x,y)] for (x,y) in zip(c,s) ]
img = compose(context(), arrow(), stroke("black"), fill(nothing),
(context(), arc(0.18, 0.5, 0.08, -π/4, 1π)),
(context(), line(point_array), stroke(["red","green","deepskyblue"])),
(context(), curve((0.7,0.5), (0.8,-0.5), (0.8,1.5), (0.9,0.5)))
)
```
## [`clip`](@ref)
```@example
using Colors, Compose
set_default_graphic_size(14cm,7cm)
X = rand(10,2)
colv = HSVA.(range(0,stop=180,length=10), 1, 1, 0.5)
img = compose(context(units=UnitBox(0,0,2,1)), stroke("black"),
(context(), rectangle(), fill(nothing)),
(context(), ngon([0.5,1.5],[0.5], [0.4], [10]), fill(nothing), stroke("lightgray")),
(context(), xgon(X[:,1],X[:,2],[0.2],[4]), fill(colv)),
(context(), xgon(X[:,1].+1,X[:,2],[0.2],[4]), fill(colv),
clip(points(ngon(1.5,0.5, 0.4, 10))) )
)
```
## [`fill`](@ref), [`fillopacity`](@ref)
```@example
using Compose
set_default_graphic_size(14cm,4cm)
img = compose(context(),
(context(), circle(0.5, 0.5, 0.08), fillopacity(0.3), fill("orange")),
(context(), circle([0.1, 0.26], [0.5], [0.1]), fillopacity(0.3), fill("blue")),
(context(), circle([0.42, 0.58], [0.5], [0.1]), fillopacity(0.3), fill(["yellow","green"])),
(context(), circle([0.74, 0.90], [0.5], [0.1]), fillopacity([0.5,0.3]), fill(["yellow","red"]) )
)
```
================================================
FILE: docs/src/gallery/transforms.md
================================================
```@meta
Author = ["Mattriks"]
```
# [Transformations](@id transforms_gallery)
## [`Mirror`](@ref)
```@example
using Compose
set_default_graphic_size(15cm,5cm)
f_points = [(.1, .1), (.9, .1), (.9, .2), (.2, .2), (.2, .4), (.6, .4), (.6, .5),
(.2, .5), (.2, .9), (.1, .9), (.1, .1)]
f_points = (x->0.4.*x.+0.1).(f_points)
fpoly(ϕ::Float64) = (context(rotation=Rotation(ϕ,0.3,0.46)), polygon(f_points))
imgfa(θ, ϕ=0.0, x=0.5,y=0.5) = compose(context(),
fill("salmon"), fillopacity(1.0), fpoly(ϕ),
(context(rotation=Rotation(θ,x,y)), line([(x-0.5,y),(x+0.5,y)]), circle(x,y, 0.02)),
(context(mirror=Mirror(θ, x, y)), fpoly(ϕ))
)
Fmir = hstack(imgfa(-π/4), imgfa(-π/2.2), imgfa(π/4, 1π))
img = compose(context(), rectangle(), fill(nothing), stroke("black"), Fmir)
```
## [`Rotation`](@ref)
```@example
using Compose
set_default_graphic_size(15cm,5cm)
# This example also illustrates nested contexts
f_points = [(.1, .1), (.9, .1), (.9, .2), (.2, .2), (.2, .4),
(.6, .4), (.6, .5), (.2, .5), (.2, .9), (.1, .9), (.1, .1)]
rect(c::String) = (context(), rectangle(), stroke(c))
circ(c::String, s::Float64=0.4) = (context(), circle([x],[y],[0.03,s]), stroke(c))
fpoly(c::String) = (context(), polygon(f_points), fill(c), fillopacity(1.0))
contextC(θ::Float64) = (context(0.5,0.5,1.5,1.5, units=UnitBox(0,0,1,1),
rotation=Rotation(θ,x,y)), fpoly("steelblue"), circ("orange"))
imgf(θ::Float64) = compose(context(),
(context(0.15, 0.15, 0.7, 0.7, units=UnitBox(0,0,2,2)), rect("red"),
contextC(θ)) # context C in context B in context A
)
x, y, θ = 0.5, 0.25, π/3
Frot = hstack(imgf(-θ), imgf(0.), imgf(θ))
img = compose(context(), rectangle(), fill(nothing), stroke("black"), Frot)
```
## [`Shear`](@ref)
```@example
using Compose
set_default_graphic_size(15cm, 5cm)
f_points = [(.1, .1), (.9, .1), (.9, .2), (.2, .2), (.2, .4), (.6, .4),
(.6, .5), (.2, .5), (.2, .9), (.1, .9), (.1, .1)]
f_points = (x->0.5.*x.+0.3).(f_points)
ctxl(θ, x, y) = (context(rotation=Rotation(θ, x, y)), circle(x,y, 0.01),
line([(x-0.5,y),(x+0.5,y)]))
fpoly(c::String) = (context(), polygon(f_points), fill(c) )
ctxf(θ, ϕ, s, x, y,c) = (context(rotation=Rotation(-θ, x, y),
shear=Shear(s, ϕ, x, y)), fpoly(c))
x, y, θ = 0.5, 0.5, -π/6
img1 = compose(context(), stroke("black"), ctxl(θ,x,y), ctxf(0,0,0,x,y, "yellow"),
(context(), arc(x,y,0.3,π+θ,π-0.15), arrow()) )
img2 = compose(context(), stroke("black"), ctxl(0,x,y),
ctxf(θ,0,1.8,x,y,"transparent"), ctxf(θ,0,0,x,y,"yellow"),
text(0.5, 0.1, "x' = x+y*shear", hcenter, vcenter) )
img3 = compose(context(), stroke("black"),
ctxl(θ, x, y), ctxf(0,θ,1.8,x,y,"yellow") )
hstack(img1, img2, img3)
```
================================================
FILE: docs/src/index.md
================================================
```@meta
Author = ["Daniel C. Jones", "Gio Borje", "Tamas Nagy"]
```
# Compose
Compose is a declarative vector graphics system written in Julia. It's designed
to simplify the creation of complex graphics and serves as the basis of the
[Gadfly](https://github.com/GiovineItalia/Gadfly.jl) data visualization package.
## Package features
- Renders publication quality graphics to SVG, PNG, Postscript, PDF and PGF
- Intuitive and consistent interface
- Works with [Jupyter](http://jupyter.org/) notebooks via [IJulia](https://github.com/JuliaLang/IJulia.jl) out of the box
## Installation
The latest release of **Compose** can be installed from the Julia REPL prompt with
```julia
julia> Pkg.add("Compose")
```
This installs the package and any missing dependencies. From there, the
simplest of graphics can be rendered to your default internet browser with
```julia
julia> using Compose
julia> compose(context(), circle(), fill("gold"))
```
Now that you have it installed, check out the [Tutorial](@ref) and the [Forms](@ref forms_gallery) gallery.
## Influences
Compose is intended as a futuristic version of the R library
[grid](http://www.stat.auckland.ac.nz/~paul/grid/grid.html), and so takes a few
ideas from grid. The Compose canvas is roughly equivalent to a viewport in grid,
for example. Compose was also inspired by the admirable Haskell library
[Diagrams](http://projects.haskell.org/diagrams/).
================================================
FILE: docs/src/library.md
================================================
```@autodocs
Modules = [Compose]
```
================================================
FILE: docs/src/tutorial.md
================================================
```@meta
Author = ["Daniel C. Jones", "Gio Borje", "Tamas Nagy"]
```
# Tutorial
## Compose is declarative
In a declarative graphics system, a figure is built without specifying the
precise sequence of drawing commands but by arranging shapes and attaching
properties. This makes it easy to break a complex graphic into manageable parts
and then figure out how to combine the parts.
## Everything is a tree
Graphics in Compose are defined using a tree structure. It's not unlike SVG in
this regard, but has simpler semantics. There are three important types that
make up the nodes of the tree:
* `Context`: An internal node.
* `Form`: A leaf node that defines some geometry, like a line or a polygon.
* `Property`: A leaf node that modifies how its parent's subtree is drawn,
like fill color, font family, or line width.
The all-important function in Compose, is called, not surprisingly, `compose`.
Calling `compose(a, b)` will return a new tree rooted at `a` and with `b`
attached as a child.
That's enough to start drawing some simple shapes.
```@setup 1
using Compose
set_default_graphic_size(4cm, 4cm)
set_default_jsmode(:exclude)
```
```@example 1
using Compose
composition = compose(compose(context(), rectangle()), fill("tomato"))
draw(SVG("tomato.svg", 4cm, 4cm), composition)
nothing # hide
```

The last line renders the composition to specificied backend, here the SVG
backend. This can also be written like
`composition |> SVG("tomato.svg", 4cm, 4cm)`.
Alternatively, if multiple compositions of the same size are to be
generated, this can be abbreviated even further to
```
set_default_graphic_size(4cm, 4cm)
composition |> SVG("tomato.svg")
composition2 |> SVG("celery.svg")
composition3 |> SVG("rutabaga.svg") # etc...
```
## The compose function accepts S-expressions
In the first example, we had to call `compose` twice just to draw a lousy red
square. Fortunately `compose` has a few tricks up its sleeve. As everyone from
lisp hackers and [phylogeneticists](http://en.wikipedia.org/wiki/Newick_format)
knows, trees can be defined most tersely using S-expressions. We can rewrite our
first example like:
```julia
# equivalent to compose(compose(context(), rectangle()), fill("tomato")))
compose(context(), rectangle(), fill("tomato"))
```
Furthermore, more complex trees can be formed by grouping subtrees with
parenthesis or brackets.
```@example 1
composition = compose(context(),
(context(), circle(), fill("bisque")),
(context(), rectangle(), fill("tomato")))
composition |> SVG("tomato_bisque.svg")
nothing # hide
```

## Trees can be visualized with introspect
A useful function for visualizing the graphic that you've constructed is
`introspect`. It takes a `Context` defining a graphic and returns a new graphic
with a schematic of the tree.
```@example 2
using Compose # hide
set_default_graphic_size(6cm, 6cm) # hide
tomato_bisque =
compose(context(),
(context(), circle(), fill("bisque")),
(context(), rectangle(), fill("tomato")))
introspect(tomato_bisque)
```
This is a little cryptic, but you can use this limited edition decoder ring:
```@example 2
using Compose, Colors, Measures
set_default_graphic_size(6cm, 4cm)
figsize = 6mm
t = table(3, 2, 1:3, 2:2, y_prop=[1.0, 1.0, 1.0])
t[1,1] = [compose(context(minwidth=figsize + 2mm, minheight=figsize),
circle(0.5, 0.5, figsize/2), fill(LCHab(92, 10, 77)))]
t[2,1] = [compose(context(minwidth=figsize + 2mm, minheight=figsize),
rectangle(0.5cx - figsize/2, 0.5cy - figsize/2, figsize, figsize),
fill(LCHab(68, 74, 192)))]
t[3,1] = [compose(context(minwidth=figsize + 2mm, minheight=figsize),
polygon([(0.5cx - figsize/2, 0.5cy - figsize/2),
(0.5cx + figsize/2, 0.5cy - figsize/2),
(0.5cx, 0.5cy + figsize/2)]),
fill(LCHab(68, 74, 29)))]
t[1,2] = [compose(context(), text(0, 0.5, "Context", hleft, vcenter))]
t[2,2] = [compose(context(), text(0, 0.5, "Form", hleft, vcenter))]
t[3,2] = [compose(context(), text(0, 0.5, "Property", hleft, vcenter))]
compose(context(), t, fill(LCHab(92, 10, 77)), fontsize(10pt))
```
## Contexts specify a coordinate system for their children
In addition to forming internal nodes to group `Form` and `Property` children, a
`Context` can define a coordinate system using the `context(x0, y0, width, height)`
form. Here we'll reposition some circles by composing them with contexts using
different coordinate systems.
```@setup 3
using Compose
set_default_graphic_size(4cm, 4cm)
```
```@example 3
composition = compose(context(), fill("tomato"),
(context(0.0, 0.0, 0.5, 0.5), circle()),
(context(0.5, 0.5, 0.5, 0.5), circle()))
composition |> SVG("tomatos.svg")
nothing # hide
```

The context's box (i.e. `(x0, y0, width, height)`) is given in terms of its
parent's coordinate system and defaults to `(0, 0, 1, 1)`. All the children of a
context will use coordinates relative to that box.
This is an easy mechanism to translate the coordinates of a subtree in the
graphic, but coordinates can be scaled and shifted as well by passing a
`UnitBox` to the `units` attribute.
```@example 3
composition = compose(context(),
(context(units=UnitBox(0, 0, 1000, 1000)),
polygon([(0, 1000), (500, 1000), (500, 0)]),
fill("tomato")),
(context(),
polygon([(1, 1), (0.5, 1), (0.5, 0)]),
fill("bisque")))
composition |> SVG("tomato_bisque_triangle.svg")
nothing # hide
```

## Measures can be a combination of absolute and relative units
Complex visualizations often are defined using a combination of relative and
absolute units. Compose makes these easy. In fact there are four sorts of units
used in Compose:
* **Context (position) units**: If no unit is explicitly attached to a position, it is
assumed to be in “context units”, which are relative to the parent Context's
box and coordinate system. (Constants: `cx`, `cy`)
* **Context (relative position) units**: The radius of a form can be expressed in size units
with respect to the context units (Constants: `sx`, `sy`). If no unit is explicitly attached to
a size (e.g. radius) unit, it is assumed to be wrt the context `x` units. More info below.
* **Width/Height units**: Sometimes you'll want place geometry in relative
coordinates, but bypassing the parent context's coordinate system.
Width/height work so that `(0w, 0h)` is always the top-left corner of the
context, and `(1w, 1h)` is always the bottom-right. (Constants: `w`, `h`)
* **Absolute units**: Absolute units are inches, centimeters, points, etc.
(Constants: `inch`, `cm`, `mm`, `pt`)
Any linear combination of these types of units is allowed. For example, `1w - 10mm` is a well formed expression, giving the width of the parent canvas minus ten millimeters. An example of the difference between
context position units (`cx`, `cy`) and size units (`sx`, `sy`), is when the coordinate system (defined by `UnitBox`) does not start at `(0,0)`, then the size `0sx` (or `0sy`) will always equal `0mm`, but the position `(0cx, 0cy)` will be dependent on the coordinates (and may refer to a point outside the context's `UnitBox`).
## Forms and Properties can be vectorized
Often one needs to produce many copies of a similar shape. Most of the forms an
properties have a scalar and vector forms to simplify this sort of mass
production.
We'll use `circle` as an example, which has two constructors:
```julia
circle(x=0.5w, y=0.5h, r=0.5w)
circle(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
```
The first of these creates only circle centered at `(x, y)` with radius `r`. The
second form can succinctly create many circles (using the [Colors](https://github.com/JuliaLang/Colors.jl) package to specify the `LHCab` colorspace):
```@setup 4
using Compose, Colors
set_default_graphic_size(4cm, 4cm)
```
```@example 4
composition = compose(context(),
circle([0.25, 0.5, 0.75], [0.25, 0.5, 0.75], [0.1, 0.1, 0.1]),
fill(LCHab(92, 10, 77)))
composition |> SVG("circles.svg")
nothing # hide
```

The arrays in passed to `xs`, `ys`, and `rs` need not be the same length.
Shorter arrays will be cycled. This let's us shorten this last example by only
specifying the radius just once.
```@example 4
composition = compose(context(),
circle([0.25, 0.5, 0.75], [0.25, 0.5, 0.75], [0.1]),
fill(LCHab(92, 10, 77)))
composition |> SVG("cycled_circles.svg")
nothing # hide
```

The `fill` is a property can also be vectorized here to quickly assign different
colors to each circle.
```@example 4
circles_fill_vectorized = compose(context(),
circle([0.25, 0.5, 0.75], [0.25, 0.5, 0.75], [0.1]),
fill([LCHab(92, 10, 77), LCHab(68, 74, 192), LCHab(78, 84, 29)]))
circles_fill_vectorized |> SVG("circles_fill_vectorized.svg")
nothing # hide
```

If vector properties are used with vector forms, they must be of equal length.
## Compose can produce arbitrary directed graphs
Though we've so far explained `compose` as producing trees, there's nothing
stopping one from producing an arbitrary directed graph. This can be quite
useful in some cases.
In this example, only one triangle object is ever initialized, despite many
triangles being drawn, which is possible because the graph produced by
`siepinski` is not a tree. The triangle polygon has many parent nodes than
“re-contextualize” that triangle by repositioning it.
```@example 5
using Compose, Colors # hide
set_default_graphic_size(8cm, 8*(sqrt(3)/2)*cm) # hide
function sierpinski(n)
if n == 0
compose(context(), polygon([(1,1), (0,1), (1/2, 0)]))
else
t = sierpinski(n - 1)
compose(context(),
(context(1/4, 0, 1/2, 1/2), t),
(context( 0, 1/2, 1/2, 1/2), t),
(context(1/2, 1/2, 1/2, 1/2), t))
end
end
composition = compose(sierpinski(6), fill(LCHab(92, 10, 77)))
composition |> SVG("sierpinski.svg", 8cm, 8*(sqrt(3)/2)*cm)
nothing # hide
```

There are no safeguards to check for cycles. You can produce a graph with a
cycle and Compose will run in an infinite loop trying to draw it. In most
applications, this isn't a concern.
## Fancier compositions
There are fancier forms of the `compose` function, in particular, variadic
`compose`, which is roughly defined as:
```julia
compose(a, b, cs...) = compose(compose(a, b), cs...)
```
Compose over tuples or arrays:
```julia
compose((as...)) = compose(as...)
```
In effect, this lets one write a complex series of compose operations as an
S-expression. For example:
```julia
compose(a, b, ((c, d), (e, f), g))
```
Since all we are doing is building trees, this syntax tends to be pretty
convenient.
## [Forms](@ref forms_gallery)
These are basic constructors for the in-built forms - see the [Forms gallery](@ref forms_gallery) for examples.
* `polygon(points)`
* `rectangle(x0, y0, width, height)`
* `circle(x, y, r)`
* `ellipse(x, y, x_radius, y_radius)`
* `text(x, y, value)`
* `line(points)`
* `curve(anchor0, ctrl0, ctrl1, anchor1)`
* `bitmap(mime, data, x0, y0, width, height)`
* `arc(x, y, r, angle1, angle2, sector)`
* `sector(x, y, r, angle1, angle2)`
* `bezigon(anchor0, sides)`
## [Properties](@ref properties_gallery)
Properties include `arrow`, `fill`, `fillopacity`, etc. See the [Properties gallery](@ref properties_gallery) for examples.
For colors, Compose supports the colors available in [Colors.jl](https://github.com/JuliaGraphics/Colors.jl), which includes many [color spaces](http://juliagraphics.github.io/Colors.jl/stable/), hex strings, and [named colors](http://juliagraphics.github.io/Colors.jl/stable/namedcolors/).
## Text
Symbols can be used in text strings by inserting [HTML
codes](http://www.ascii.cl/htmlcodes.htm). More general formatting for the SVG
backend is [documented here](https://www.w3.org/TR/SVG/text.html),
whereas the Cairo backend uses a [Pango markup
language](https://developer.gnome.org/pango/unstable/PangoMarkupFormat.html).
```@example 6
using Compose # hide
cents_ina_dollar = compose(context(), text(0.5, 0.5,"100¢ in a $"))
cents_ina_dollar |> SVG("dollar.svg",5cm,1cm)
nothing # hide
```

Use the `font` and `fontsize` properties to change the appearance of type:
```@example 7
using Compose # hide
compose(context(),
(context(), text(0.2,0.5,"big"), fontsize(18pt)),
(context(), text(0.4,0.5,"small"), fontsize(6pt)),
(context(), text(0.6,0.5,"bold"), font("Helvetica-Bold")),
(context(), text(0.8,0.5,"oblique"), font("Helvetica-Oblique"))) |>
SVG("font_fontsize.svg",15cm,1cm)
nothing # hide
```

================================================
FILE: src/Compose.jl
================================================
module Compose
using Colors
using IterTools
using DataStructures
using Measures
using Requires
using Dates
using Printf
using Base.Iterators
using Statistics
import JSON
import Base: length, isempty, getindex, setindex!,
display, show, convert, zero, isless, max, fill, size, copy,
min, max, abs, +, -, *, /, ==
import Measures: resolve, w, h
export compose, compose!, Context, UnitBox, AbsoluteBoundingBox,
Rotation, Mirror, Shear,
ParentDrawContext, context, ctxpromise, table, set_units!, minwidth, minheight,
text_extents, max_text_extents, polygon, ngon, star, xgon, bezigon,
line, rectangle, circle, arc, sector, ellipse, text, curve, bitmap,
stroke, fill, strokedash, strokelinecap, arrow, strokelinejoin,
linewidth, visible, fillopacity, strokeopacity, clip, points,
font, fontsize, svgid, svgclass, svgattribute, jsinclude, jscall, Measure,
inch, mm, cm, pt, px, cx, cy, sx, sy, w, h, hleft, hcenter, hright, vtop, vcenter,
vbottom, SVG, SVGJS, PGF, PNG, PS, PDF, draw, pad, pad_inner, pad_outer,
hstack, vstack, gridstack, LineCapButt, LineCapSquare, LineCapRound,
CAIROSURFACE, introspect, set_default_graphic_size, set_default_jsmode,
boundingbox, Patchable
abstract type Backend end
"""
Some backends can more efficiently draw forms by batching. If so, they
shuld define a similar method that returns true.
"""
canbatch(::Backend) = false
# Allow users to supply strings without deprecation warnings
parse_colorant(c::Colorant) = c
parse_colorant(str::AbstractString) = parse(Colorant, str)
parse_colorant(c::Union{Tuple,Vector}) = [parse_colorant(x) for x in c]
parse_colorant(c...) = parse_colorant(c)
@deprecate parse_colorant_vec(c...) parse_colorant(c)
include("misc.jl")
include("measure.jl")
include("list.jl")
# Every graphic in Compose consists of a tree.
abstract type ComposeNode end
# Used to mark null child pointers
struct NullNode <: ComposeNode end
nullnode = NullNode()
include("form.jl")
include("property.jl")
include("container.jl")
include("batch.jl")
include("table.jl")
include("stack.jl")
# How large to draw graphics when not explicitly drawing to a backend
default_graphic_width = sqrt(2)*10*cm
default_graphic_height = 10cm
function set_default_graphic_size(width::MeasureOrNumber,
height::MeasureOrNumber)
global default_graphic_width
global default_graphic_height
default_graphic_width = x_measure(width)
default_graphic_height = y_measure(height)
nothing
end
default_graphic_format = :html
function set_default_graphic_format(fmt::Symbol)
fmt in [:html, :png, :svg, :pdf, :ps, :pgf] || error("$(fmt) is not a supported plot format")
global default_graphic_format
default_graphic_format = fmt
nothing
end
# Default means to include javascript dependencies in the SVGJS backend.
default_jsmode = :embed
function set_default_jsmode(mode::Symbol)
global default_jsmode
if mode in [:none, :exclude, :embed, :linkabs, :linkrel]
default_jsmode = mode
else
error("$(mode) is not a valid jsmode")
end
nothing
end
function default_mime()
if default_graphic_format == :png
"image/png"
elseif default_graphic_format == :svg
"image/svg+xml"
elseif default_graphic_format == :html
"text/html"
elseif default_graphic_format == :ps
"application/postscript"
elseif default_graphic_format == :pdf
"application/pdf"
elseif default_graphic_format == :pgf
"application/x-tex"
else
""
end
end
# Default property values
default_font_family = "Helvetica Neue,Helvetica,Arial,sans"
default_font_size = 11pt
default_line_width = 0.3mm
default_stroke_color = nothing
default_fill_color = colorant"black"
# If Cairo is not available, throw an error when trying to save with a Cairo backend
missing_cairo_error(backend::String, invocation::String=backend) =
"""
The Cairo and Fontconfig packages are necessary for saving as $backend.
Add them with the package manager if necessary, then run `import Cairo,
Fontconfig` before invoking `$invocation`.
"""
missing_cairo_error(m::MIME) =
missing_cairo_error(string(m), "show(::IO, ::MIME\"$m\", ::Context)")
for backend in [:PNG, :PS, :PDF]
docstr = missing_cairo_error(string(backend))
@eval @doc $docstr $backend(args...; kwargs...) = error(missing_cairo_error(string($backend)))
end
CairoMIME = Union{MIME"image/png", MIME"application/ps", MIME"application/pdf"}
show(io::IO, m::CairoMIME, ctx::Context) = error(missing_cairo_error(m))
include("svg.jl")
include("pgf_backend.jl")
# If available, pango and fontconfig are used to compute text extents and match
# fonts. Otherwise a simplistic pure-julia fallback is used.
include("fontfallback.jl")
const pango_cairo_ctx = Ref{Ptr}(C_NULL)
const pango_cairo_fm = Ref{Ptr}(C_NULL)
const pangolayout = Ref{Any}(nothing)
function link_fontconfig()
@debug "Loading Fontconfig backend into Compose.jl"
pango_cairo_ctx[] = C_NULL
ccall((:g_type_init, libgobject), Cvoid, ())
pango_cairo_fm[] = ccall((:pango_cairo_font_map_new, libpangocairo),
Ptr{Cvoid}, ())
pango_cairo_ctx[] = ccall((:pango_font_map_create_context, libpango),
Ptr{Cvoid}, (Ptr{Cvoid},), pango_cairo_fm[])
pangolayout[] = PangoLayout()
end
function link_cairo()
@debug "Loading Cairo backend into Compose.jl"
include(joinpath(@__DIR__,"cairo_backends.jl"))
include(joinpath(@__DIR__,"immerse_backend.jl"))
end
function __init__()
@require Cairo="159f3aea-2a34-519c-b102-8c37f9878175" link_cairo()
@require Fontconfig="186bb1d3-e1f7-5a2c-a377-96d770f13627" begin
include("pango.jl")
link_fontconfig()
end
end
show(io::IO, m::MIME"text/html", ctx::Context) =
draw(SVGJS(io, default_graphic_width, default_graphic_height, false,
jsmode=default_jsmode), ctx)
show(io::IO, m::MIME"image/svg+xml", ctx::Context) =
draw(SVG(io, default_graphic_width, default_graphic_height, false), ctx)
function pad_outer(c::Context,
left_padding::MeasureOrNumber,
right_padding::MeasureOrNumber,
top_padding::MeasureOrNumber,
bottom_padding::MeasureOrNumber)
left_padding = size_measure(left_padding)
right_padding = size_measure(right_padding)
top_padding = size_measure(top_padding)
bottom_padding = size_measure(bottom_padding)
root = context(c.box.x0[1], c.box.x0[1],
c.box.a[1] + left_padding + right_padding,
c.box.a[2] + top_padding + bottom_padding,
minwidth=c.minwidth,
minheight=c.minheight)
c = copy(c)
c.box = BoundingBox(left_padding, top_padding,
1w - left_padding - right_padding,
1h - top_padding - bottom_padding)
return compose!(root, c)
end
pad_outer(c::Context, padding::MeasureOrNumber) =
pad_outer(c, padding, padding, padding, padding)
pad_outer(cs::Vector{Context},
left_padding::MeasureOrNumber,
right_padding::MeasureOrNumber,
top_padding::MeasureOrNumber,
bottom_padding::MeasureOrNumber) =
map(c -> pad_outer(c, left_padding, right_padding, top_padding, bottom_padding), cs)
pad_outer(cs::Vector{Context}, padding::MeasureOrNumber) =
pad_outer(cs, padding, padding, padding, padding)
function pad_inner(c::Context,
left_padding::MeasureOrNumber,
right_padding::MeasureOrNumber,
top_padding::MeasureOrNumber,
bottom_padding::MeasureOrNumber)
left_padding = size_measure(left_padding)
right_padding = size_measure(right_padding)
top_padding = size_measure(top_padding)
bottom_padding = size_measure(bottom_padding)
root = context(c.box.x0[1], c.box.x0[2],
c.box.a[1], c.box.a[2],
minwidth=c.minwidth,
minheight=c.minheight)
c = copy(c)
c.box = BoundingBox(left_padding, top_padding,
1w - left_padding - right_padding,
1h - top_padding - bottom_padding)
return compose!(root, c)
end
pad_inner(c::Context, padding::MeasureOrNumber) =
pad_inner(c, padding, padding, padding, padding)
pad_inner(cs::Vector{Context},
left_padding::MeasureOrNumber,
right_padding::MeasureOrNumber,
top_padding::MeasureOrNumber,
bottom_padding::MeasureOrNumber) =
map(c -> pad_inner(c, left_padding, right_padding, top_padding, bottom_padding), cs)
pad_inner(cs::Vector{Context}, padding::MeasureOrNumber) =
pad_inner(cs, padding, padding, padding, padding)
function gridstack(cs::Matrix{Context})
m, n = size(cs)
t = Table(m, n, 1:m, 1:n, x_prop=ones(n), y_prop=ones(m))
for i in 1:m, j in 1:n
t[i, j] = [cs[i, j]]
end
return compose!(context(), t)
end
const pad = pad_outer
end # module Compose
================================================
FILE: src/abandoned.jl
================================================
# Path Primitives
# From form.jl:
# Path
# ----
# An implementation of the SVG path mini-language.
abstract type PathOp end
struct MoveAbsPathOp <: PathOp
to::Vec
end
function assert_pathop_tokens_len(op_type, tokens, i, needed)
provided = length(tokens) - i + 1
provided < needed &&
error("In path $(op_type) requires $(needed) argumens but only $(provided) provided.")
end
function parsepathop(::Type{MoveAbsPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(MoveAbsPathOp, tokens, i, 2)
op = MoveAbsPathOp((x_measure(tokens[i]), y_measure(tokens[i + 1])))
return (op, i + 2)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::MoveAbsPathOp) =
MoveAbsPathOp(resolve(box, units, t, p.to))
struct MoveRelPathOp <: PathOp
to::Vec
end
function parsepathop(::Type{MoveRelPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(MoveRelPathOp, tokens, i, 2)
op = MoveRelPathOp((tokens[i], tokens[i + 1]))
return (op, i + 2)
end
function resolve_offset(box::AbsoluteBox, units::UnitBox, t::Transform, p::Vec)
absp = resolve(box, units, t, p)
zer0 = resolve(box, units, t, (0w, 0h))
return (absp[1] - zer0[1], absp[2] - zer0[2])
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::MoveRelPathOp) =
MoveRelPathOp(resolve_offset(box, units, t, p.to))
struct ClosePathOp <: PathOp
end
parsepathop(::Type{ClosePathOp}, tokens::AbstractArray, i) = (ClosePathOp(), i)
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::ClosePathOp) = p
struct LineAbsPathOp <: PathOp
to::Vec
end
function parsepathop(::Type{LineAbsPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(LineAbsPathOp, tokens, i, 2)
op = LineAbsPathOp((x_measure(tokens[i]), y_measure(tokens[i + 1])))
return (op, i + 2)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::LineAbsPathOp) =
LineAbsPathOp(resolve(box, units, t, p.to))
struct LineRelPathOp <: PathOp
to::Vec
end
function parsepathop(::Type{LineRelPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(LineRelPathOp, tokens, i, 2)
op = LineRelPathOp((x_measure(tokens[i]), y_measure(tokens[i + 1])))
return (op, i + 2)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::LineRelPathOp) =
LineRelPathOp(resolve(box, units, t, p.to))
struct HorLineAbsPathOp <: PathOp
x::Measure
end
function parsepathop(::Type{HorLineAbsPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(HorLineAbsPathOp, tokens, i, 1)
op = HorLineAbsPathOp(x_measure(tokens[i]))
return (op, i + 1)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::HorLineAbsPathOp) =
HorLineAbsPathOp(resolve(box, units, t, (p.x, 0mm))[1])
struct HorLineRelPathOp <: PathOp
Δx::Measure
end
function parsepathop(::Type{HorLineRelPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(HorLineRelPathOp, tokens, i, 1)
op = HorLineRelPathOp(x_measure(tokens[i]))
return (op, i + 1)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::HorLineRelPathOp) =
HorLineRelPathOp(resolve(box, units, t, p.Δx))
struct VertLineAbsPathOp <: PathOp
y::Measure
end
function parsepathop(::Type{VertLineAbsPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(VertLineAbsPathOp, tokens, i, 1)
op = VertLineAbsPathOp(y_measure(tokens[i]))
return (op, i + 1)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::VertLineAbsPathOp) =
VertLineAbsPathOp(resolve(box, units, t, (0mm, p.y))[2])
struct VertLineRelPathOp <: PathOp
Δy::Measure
end
function parsepathop(::Type{VertLineRelPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(VertLineRelPathOp, tokens, i, 1)
op = VertLineRelPathOp(y_measure(tokens[i]))
return (op, i + 1)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::VertLineRelPathOp) =
VertLineAbsPathOp(resolve(box, units, t, (0mmm, p.Δy))[2])
struct CubicCurveAbsPathOp <: PathOp
ctrl1::Vec
ctrl2::Vec
to::Vec
end
function parsepathop(::Type{CubicCurveAbsPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(CubicCurveAbsPathOp, tokens, i, 6)
op = CubicCurveAbsPathOp((tokens[i], tokens[i + 1]),
(tokens[i + 2], tokens[i + 3]),
(tokens[i + 4], tokens[i + 5]))
return (op, i + 6)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::CubicCurveAbsPathOp) =
CubicCurveAbsPathOp(
resolve(box, units, t, p.ctrl1),
resolve(box, units, t, p.ctrl2),
resolve(box, units, t, p.to))
struct CubicCurveRelPathOp <: PathOp
ctrl1::Vec
ctrl2::Vec
to::Vec
end
function parsepathop(::Type{CubicCurveRelPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(CubicCurveRelPathOp, tokens, i, 6)
op = CubicCurveRelPathOp((tokens[i], tokens[i + 1]),
(tokens[i + 2], tokens[i + 3]),
(tokens[i + 4], tokens[i + 5]))
return (op, i + 6)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::CubicCurveRelPathOp) =
CubicCurveRelPathOp(
resolve(box, units, t, p.ctrl1),
resolve(box, units, t, p.ctrl2),
resolve(box, units, t, p.to))
struct CubicCurveShortAbsPathOp <: PathOp
ctrl2::Vec
to::Vec
end
function parsepathop(::Type{CubicCurveShortAbsPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(CubicCurveShortAbsPathOp, tokens, i, 4)
op = CubicCurveShortAbsPathOp((x_measure(tokens[i]), y_measure(tokens[i + 1])),
(x_measure(tokens[i + 2]), y_measure(tokens[i + 3])))
return (op, i + 4)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::CubicCurveShortAbsPathOp) =
CubicCurveShortAbsPathOp(
resolve_offset(box, units, t, p.ctrl2),
resolve_offset(box, units, t, p.to))
struct CubicCurveShortRelPathOp <: PathOp
ctrl2::Vec
to::Vec
end
function parsepathop(::Type{CubicCurveShortRelPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(CubicCurveShortRelPathOp, tokens, i, 4)
op = CubicCurveShortRelPathOp((x_measure(tokens[i]), y_measure(tokens[i + 1])),
(x_measure(tokens[i + 2]), y_measure(tokens[i + 3])))
return (op, i + 4)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::CubicCurveShortRelPathOp) =
CubicCurveShortRelPathOp(
resolve(box, units, t, p.ctrl2),
resolve(box, units, t, p.to))
struct QuadCurveAbsPathOp <: PathOp
ctrl1::Vec
to::Vec
end
function parsepathop(::Type{QuadCurveAbsPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(QuadCurveAbsPathOp, tokens, i, 4)
op = QuadCurveAbsPathOp((tokens[i], tokens[i + 1]),
(tokens[i + 2], tokens[i + 3]))
return (op, i + 4)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::QuadCurveAbsPathOp) =
QuadCurveAbsPathOp(
resolve(box, units, t, p.ctrl1),
resolve(box, units, t, p.to))
struct QuadCurveRelPathOp <: PathOp
ctrl1::Vec
to::Vec
end
function parsepathop(::Type{QuadCurveRelPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(QuadCurveRelPathOp, tokens, i, 4)
op = QuadCurveRelPathOp((tokens[i], tokens[i + 1]),
(tokens[i + 2], tokens[i + 3]))
return (op, i + 4)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::QuadCurveRelPathOp) =
QuadCurveRelPathOp(
(resolve(box, units, t, p.ctrl1[1]),
resolve(box, units, t, p.ctrl1[2])),
(resolve(box, units, t, p.to[1]),
resolve(box, units, t, p.to[2])))
struct QuadCurveShortAbsPathOp <: PathOp
to::Vec
end
function parsepathop(::Type{QuadCurveShortAbsPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(QuadCurveShortAbsPathOp, tokens, i, 2)
op = QuadCurveShortAbsPathOp((tokens[i], tokens[i + 1]))
return (op, i + 2)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::QuadCurveShortAbsPathOp) =
QuadCurveShortAbsPathOp(resolve(box, units, t, p.to))
struct QuadCurveShortRelPathOp <: PathOp
to::Vec
end
function parsepathop(::Type{QuadCurveShortRelPathOp}, tokens::AbstractArray, i)
assert_pathop_tokens_len(QuadCurveShortRelPathOp, tokens, i, 2)
op = QuadCurveShortRelPathOp((tokens[i], tokens[i + 1]))
return (op, i + 2)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::QuadCurveShortRelPathOp) =
QuadCurveShortRelPathOp(
(resolve(box, units, t, p.to[1]),
resolve(box, units, t, p.to[2])))
struct ArcAbsPathOp <: PathOp
rx::Measure
ry::Measure
rotation::Float64
largearc::Bool
sweep::Bool
to::Vec
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::ArcAbsPathOp) =
ArcAbsPathOp(
resolve(box, units, t, p.rx),
resolve(box, units, t, p.ry),
p.rotation,
p.largearc,
p.sweep,
resolve(box, units, t, p.to))
struct ArcRelPathOp <: PathOp
rx::Measure
ry::Measure
rotation::Float64
largearc::Bool
sweep::Bool
to::Vec
end
function parsepathop(::Type{T}, tokens::AbstractArray, i) where T <: Union{ArcAbsPathOp, ArcRelPathOp}
assert_pathop_tokens_len(T, tokens, i, 7)
if isa(tokens[i + 3], Bool)
largearc = tokens[i + 3]
elseif tokens[i + 3] == 0
largearc = false
elseif tokens[i + 3] == 1
largearc = true
else
error("largearc argument to the arc path operation must be boolean")
end
if isa(tokens[i + 4], Bool)
sweep = tokens[i + 4]
elseif tokens[i + 4] == 0
sweep = false
elseif tokens[i + 4] == 1
sweep = true
else
error("sweep argument to the arc path operation must be boolean")
end
isa(tokens[i + 2], Number) || error("path arc operation requires a numerical rotation")
op = T(x_measure(tokens[i]),
y_measure(tokens[i + 1]),
convert(Float64, tokens[i + 2]),
largearc, sweep,
(x_measure(tokens[i + 5]), y_measure(tokens[i + 6])))
return (op, i + 7)
end
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::ArcRelPathOp) =
ArcRelPathOp(
resolve(box, units, t, p.rx),
resolve(box, units, t, p.ry),
p.rotation,
p.largearc,
p.sweep,
(resolve(box, units, t, p.to[1]),
resolve(box, units, t, p.to[2])))
const path_ops = Dict(
:M => MoveAbsPathOp,
:m => MoveRelPathOp,
:Z => ClosePathOp,
:z => ClosePathOp,
:L => LineAbsPathOp,
:l => LineRelPathOp,
:H => HorLineAbsPathOp,
:h => HorLineRelPathOp,
:V => VertLineAbsPathOp,
:v => VertLineRelPathOp,
:C => CubicCurveAbsPathOp,
:c => CubicCurveRelPathOp,
:S => CubicCurveShortAbsPathOp,
:s => CubicCurveShortRelPathOp,
:Q => QuadCurveAbsPathOp,
:q => QuadCurveRelPathOp,
:T => QuadCurveShortAbsPathOp,
:t => QuadCurveShortRelPathOp,
:A => ArcAbsPathOp,
:a => ArcRelPathOp
)
# A path is an array of symbols, numbers, and measures following SVGs path
# mini-language.
function parsepath(tokens::AbstractArray)
ops = PathOp[]
last_op_type = nothing
i = 1
while i <= length(tokens)
tok = tokens[i]
strt = i
if isa(tok, Symbol)
if !haskey(path_ops, tok)
error("$(tok) is not a valid path operation")
else
op_type = path_ops[tok]
i += 1
op, i = parsepathop(op_type, tokens, i)
push!(ops, op)
last_op_type = op_type
end
else
op, i = parsepathop(last_op_type, tokens, i)
push!(ops, op)
end
end
return ops
end
struct PathPrimitive <: FormPrimitive
ops::Vector{PathOp}
end
const Path = Form{PathPrimitive}
path(tokens::AbstractArray, tag=empty_tag) = Path([PathPrimitive(parsepath(tokens))], tag)
path(tokens::AbstractArray{T}, tag=empty_tag) where T <: AbstractArray =
Path([PathPrimitive(parsepath(ts)) for ts in tokens], tag)
resolve(box::AbsoluteBox, units::UnitBox, t::Transform, p::PathPrimitive) =
PathPrimitive([resolve(box, units, t, op) for op in p.ops])
# TODO: boundingbox
# From cairo_backends.jl:
function draw(img::Image, prim::PathPrimitive)
for op in prim.ops
draw_path_op(img, op)
end
fillstroke(img)
end
draw_path_op(img::Image, op::MoveAbsPathOp) = move_to(img, op.to)
draw_path_op(img::Image, op::MoveRelPathOp) = rel_move_to(img, op.to)
draw_path_op(img::Image, op::ClosePathOp) = close_path(img)
draw_path_op(img::Image, op::LineAbsPathOp) = line_to(img, op.to)
draw_path_op(img::Image, op::LineRelPathOp) = rel_line_to(img, op.to)
function draw_path_op(img::Image, op::HorLineAbsPathOp)
pos = current_point(img)
line_to(img, (op.x, pos.y))
end
draw_path_op(img::Image, op::HorLineRelPathOp) = rel_line_to(img, (op.Δx, 0.0mm))
function draw_path_op(img::Image, op::VertLineAbsPathOp)
pos = current_point(img)
line_to(img, (pos.x, op.y))
end
draw_path_op(img::Image, op::VertLineRelPathOp) = rel_line_to(img, (0.0mm, op.Δy))
function draw_path_op(img::Image, op::CubicCurveAbsPathOp)
curve_to(img, op.ctrl1, op.ctrl2, op.to)
img.last_ctrl2_point = op.ctrl2
end
function draw_path_op(img::Image, op::CubicCurveRelPathOp)
xy = current_point(img)
rel_curve_to(img, op.ctrl1, op.ctrl2, op.to)
img.last_ctrl2_point = (op.ctrl2[1] + xy[1], op.ctrl2[2] + xy[2])
end
function draw_path_op(img::Image, op::CubicCurveShortAbsPathOp)
xy = current_point(img)
ctrl1 = img.last_ctrl2_point
if ctrl1 === nothing
ctrl1 = xy
else
ctrl1 = (2*xy[1] - ctrl1[1], 2*xy[2] - ctrl1[2])
end
curve_to(img, ctrl1, op.ctrl2, op.to)
img.last_ctrl2_point = op.ctrl2
end
function draw_path_op(img::Image, op::CubicCurveShortRelPathOp)
xy = current_point(img)
x1, y1 = xy[1].value, xy[2].value
x2, y2 = op.to[1].value, op.to[2].value
ctrl1 = img.last_ctrl2_point
if ctrl1 === nothing
ctrl1 = xy
else
ctrl1 = (Measure(abs=(2*x1 - ctrl1[1].value) - x1),
Measure(abs=(2*y1 - ctrl1[2].value) - y1))
end
cx, cy = ctrl1[1].value, ctrl1[2].value
rel_curve_to(img, ctrl1, op.ctrl2, op.to)
img.last_ctrl2_point =
(Measure(abs=op.ctrl2[1].value + xy.x.abs),
Measure(abs=op.ctrl2[2].value + xy.y.abs))
end
function draw_path_op(img::Image, op::QuadCurveAbsPathOp)
xy = current_point(img)
x1, y1 = xy[1].value, xy[2].value
x2, y2 = op.to[1].value, op.to[2].value
cx, cy = op.ctrl1[1].value, op.ctrl1[2].value
curve_to(img,
(Measure(abs=(x1 + 2*cx)/3),
Measure(abs=(y1 + 2*cy)/3)),
(Measure(abs=(x2 + 2*cx)/3),
Measure(abs=(y2 + 2*cy)/3)),
op.to)
img.last_ctrl1_point = op.ctrl1
end
function draw_path_op(img::Image, op::QuadCurveRelPathOp)
xy = current_point(img)
x1, y1 = xy[1].value, xy[2].value
x2, y2 = op.to[1].value, op.to[2].value
cx, cy = op.ctrl1[1].value, op.ctrl1[2].value
rel_curve_to(img,
(Measure(abs=(x1 + 2*cx)/3),
Measure(abs=(y1 + 2*cy)/3)),
(Measure(abs=(x2 + 2*cx)/3),
Measure(abs=(y2 + 2*cy)/3)),
op.to)
img.last_ctrl1_point =
(Measure(abs=op.ctrl1[1].value + xy.x.abs),
Measure(abs=op.ctrl1[2].value + xy.y.abs))
end
function draw_path_op(img::Image, op::QuadCurveShortAbsPathOp)
xy = current_point(img)
x1, y1 = xy[1].value, xy[2].value
x2, y2 = op.to[1].value, op.to[2].value
ctrl1 = img.last_ctrl1_point
if img.last_ctrl1_point === nothing
ctrl1 = xy
else
ctrl1 = (Measure(abs=2*x1 - ctrl1[1].value),
Measure(abs=2*y1 - ctrl1[2].value))
end
cx, cy = ctrl1[1].value, ctrl1[2].value
curve_to(img,
(Measure(abs=(x1 + 2*cx)/3),
Measure(abs=(y1 + 2*cy)/3)),
(Measure(abs=(x2 + 2*cx)/3),
Measure(abs=(y2 + 2*cy)/3)),
(Measure(abs=x2), Measure(abs=y2)))
img.last_ctrl1_point = ctrl1
end
function draw_path_op(img::Image, op::QuadCurveShortRelPathOp)
xy = current_point(img)
x1, y1 = xy[1].value, xy[2].value
x2, y2 = x1 + op.to[1].value, y1 + op.to[2].value
ctrl1 = img.last_ctrl1_point
if ctrl1 === nothing
ctrl1 = xy
else
ctrl1 = (Measure(abs=(2*x1 - ctrl1[1].value) - x1),
Measure(abs=(2*y1 - ctrl1[2].value) - y1))
end
cx, cy = ctrl1[1].value, ctrl1[2].value
rel_curve_to(img,
(Measure(abs=(x1 + 2*cx)/3),
Measure(abs=(y1 + 2*cy)/3)),
(Measure(abs=(x2 + 2*cx)/3),
Measure(abs=(y2 + 2*cy)/3)),
(Measure(abs=x2), Measure(abs=y2)))
img.last_ctrl1_point =
(Measure(abs=op.ctrl1[1].value + x1),
Measure(abs=op.ctrl1[2].value + y1))
end
function draw_path_op(img::Image, op::ArcAbsPathOp)
xy = current_point(img)
x1, y1 = xy[1].value, xy[2].value
x2, y2 = op.to[1].value, op.to[2].value
rx, ry = op.rx.abs, op.ry.abs
φ = deg2rad(op.rotation)
draw_endpoint_arc(img, rx, ry, φ, op.largearc, op.sweep, x1, y1, x2, y2)
end
function draw_path_op(img::Image, op::ArcRelPathOp)
xy = current_point(img)
x1, y1 = xy[1].value, xy[2].value
x2, y2 = x1 + op.to[1].value, y1 + op.to[2].value
rx, ry = op.rx.abs, op.ry.abs
φ = deg2rad(op.rotation)
draw_endpoint_arc(img, rx, ry, φ, op.largearc, op.sweep, x1, y1, x2, y2)
end
# Draw an SVG style elliptical arc
function draw_endpoint_arc(img::Image, rx::Float64, ry::Float64, φ::Float64,
largearc::Bool, sweep::Bool,
x1::Float64, y1::Float64,
x2::Float64, y2::Float64)
function uvangle(ux, uy, vx, vy)
t = (ux * vx + uy * vy) / (sqrt(ux^2 + uy^2) * sqrt(vx^2 + vy^2))
t = max(min(t, 1.0), -1.0)
return (ux * vy - uy * vx < 0.0 ? -1 : 1.0) * acos(t)
end
# From: http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter
xm, ym = (x1 - x2)/2, (y1 - y2)/2
x1p = cos(φ) * xm + sin(φ) * ym
y1p = -sin(φ) * xm + cos(φ) * ym
u = (rx^2 * ry^2 - rx^2 * y1p^2 - ry^2 * x1p^2) / (rx^2 * y1p^2 + ry^2 * x1p^2)
u = u >= 0.0 ? sqrt(u) : 0.0
cxp = u * (rx * y1p) / ry
cyp = -u * (ry * x1p) / rx
if sweep == largearc
cxp = -cxp
cyp = -cyp
end
cx = (x1 + x2)/2 + cos(φ) * cxp - sin(φ) * cyp
cy = (y1 + y2)/2 + sin(φ) * cxp + cos(φ) * cyp
θ1 = uvangle(1.0, 0.0, (x1p - cxp) / rx, (y1p - cyp) / ry)
Δθ = uvangle((x1p - cxp) / rx, (y1p - cyp) / ry,
(-x1p - cxp) / rx, (-y1p - cyp) / ry) % (2.0*π)
if Δθ > 0.0 && !sweep
Δθ -= 2*π
elseif Δθ < 0.0 && sweep
Δθ += 2*π
end
Cairo.save(img.ctx)
Cairo.translate(img.ctx,
absolute_native_units(img, cx),
absolute_native_units(img, cy))
Cairo.rotate(img.ctx, φ)
Cairo.scale(img.ctx, rx, ry)
if sweep
arc(img, 0.0, 0.0, 1.0, θ1, θ1 + Δθ)
else
arc_negative(img, 0.0, 0.0, 1.0, θ1, θ1 + Δθ)
end
Cairo.restore(img.ctx)
end
# From svg.jl:
function svg_print_path_op(io::IO, op::MoveAbsPathOp)
print(io, 'M')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::MoveRelPathOp)
print(io, 'm')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
svg_print_path_op(io::IO, op::ClosePathOp) = print(io, 'z')
function svg_print_path_op(io::IO, op::LineAbsPathOp)
print(io, 'L')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::LineRelPathOp)
print(io, 'l')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::HorLineAbsPathOp)
print(io, 'H')
svg_print_float(io, op.x.value)
end
function svg_print_path_op(io::IO, op::HorLineRelPathOp)
print(io, 'h')
svg_print_float(io, op.Δx.value)
end
function svg_print_path_op(io::IO, op::VertLineAbsPathOp)
print(io, 'V')
svg_print_float(io, op.y.value)
end
function svg_print_path_op(io::IO, op::VertLineRelPathOp)
print(io, 'v')
svg_print_float(io, op.Δy.value)
end
function svg_print_path_op(io::IO, op::CubicCurveAbsPathOp)
print(io, 'C')
svg_print_float(io, op.ctrl1[1].value)
print(io, ' ')
svg_print_float(io, op.ctrl1[2].value)
print(io, ' ')
svg_print_float(io, op.ctrl2[1].value)
print(io, ' ')
svg_print_float(io, op.ctrl2[2].value)
print(io, ' ')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::CubicCurveRelPathOp)
print(io, 'c')
svg_print_float(io, op.ctrl1[1].value)
print(io, ' ')
svg_print_float(io, op.ctrl1[2].value)
print(io, ' ')
svg_print_float(io, op.ctrl2[1].value)
print(io, ' ')
svg_print_float(io, op.ctrl2[2].value)
print(io, ' ')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::CubicCurveShortAbsPathOp)
print(io, 'S')
svg_print_float(io, op.ctrl2[1].value)
print(io, ' ')
svg_print_float(io, op.ctrl2[2].value)
print(io, ' ')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::CubicCurveShortRelPathOp)
print(io, 's')
svg_print_float(io, op.ctrl2[1].value)
print(io, ' ')
svg_print_float(io, op.ctrl2[2].value)
print(io, ' ')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::QuadCurveAbsPathOp)
print(io, 'Q')
svg_print_float(io, op.ctrl1[1].value)
print(io, ' ')
svg_print_float(io, op.ctrl1[2].value)
print(io, ' ')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::QuadCurveRelPathOp)
print(io, 'q')
svg_print_float(io, op.ctrl1[1].value)
print(io, ' ')
svg_print_float(io, op.ctrl1[2].value)
print(io, ' ')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::QuadCurveShortAbsPathOp)
print(io, 'T')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::QuadCurveShortRelPathOp)
print(io, 't')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::ArcAbsPathOp)
print(io, 'A')
svg_print_float(io, op.rx.value)
print(io, ' ')
svg_print_float(io, op.ry.value)
print(io, ' ')
svg_print_float(io, op.rotation)
print(io, ' ',
op.largearc ? 1 : 0, ' ',
op.sweep ? 1 : 0, ' ')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function svg_print_path_op(io::IO, op::ArcRelPathOp)
print(io, 'a')
svg_print_float(io, op.rx.value)
print(io, ' ')
svg_print_float(io, op.ry.value)
print(io, ' ')
svg_print_float(io, op.rotation)
print(io, ' ',
op.largearc ? 1 : 0, ' ',
op.sweep ? 1 : 0, ' ')
svg_print_float(io, op.to[1].value)
print(io, ' ')
svg_print_float(io, op.to[2].value)
end
function draw(img::SVG, prim::PathPrimitive, idx::Int)
indent(img)
print(img.out, "<path d=\"")
for op in prim.ops
svg_print_path_op(img.out, op)
end
print(img.out, '"')
print_vector_properties(img, idx)
print(img.out, "/>\n")
end
================================================
FILE: src/batch.jl
================================================
"""
A form batch is a vectorized form with n primitives transformed into a simpler
representation: one primitive repositioned n times.
On certain backends this leads to more efficient drawing. For example, SVG can
be shortened by using <def> and <use> tags, and raster graphics can render the
form primitive to a back buffer and blit it into place for faster drawing.
Batching is an optimization transform that happens at draw time. There's
currently no mechanism to manually batch. E.g. contexts cannot have FormBatch
children.
"""
struct FormBatch{P <: FormPrimitive}
primitive::P
offsets::Vector{AbsoluteVec2}
end
"""
Attempt to batch a form. Return a Nothing singleton if the Form could not be
batched, and FormBatch object if the original form can be replaced.
"""
batch(form::Form{P}) where P = nothing
# Note: in tests using random data, this optimization wasn't worth it. I'm
# keeping it around out of hopes I find a more clever version that is
# worthwhile, or benchmarks using real data show different results.
# maximum distance between offsets to be considered redundand in mm
const offset_redundancy_threshold = 0.05
"""
Produce a new array of offsets in which near duplicate values have been removed.
"""
function filter_redundant_offsets!(offsets::Vector{AbsoluteVec2})
isempty(offsets) && return offsets
sort!(offsets)
nonredundant_offsets = AbsoluteVec2[offsets[1]]
for i in 2:length(offsets)
# use l1 distance for perf
d = abs(offsets[i-1][1].value - offsets[i][1].value) +
abs(offsets[i-1][2].value - offsets[i][2].value)
d > offset_redundancy_threshold && push!(nonredundant_offsets, offsets[i])
end
@show (length(offsets), length(nonredundant_offsets))
return nonredundant_offsets
end
#=
function batch{T <: CirclePrimitive}(form::Form{T})
# circles can be batched if they all have the same radius.
r = form.primitives[1].radius
n = length(form.primitives)
for i in 2:n
form.primitives[i].radius == r || return Nothing
end
prim = CirclePrimitive((0mm, 0mm), r)
offsets = Array{AbsoluteVec2}(n)
for i in 1:n
offsets[i] = form.primitives[i].center
end
return FormBatch(prim, offsets)
end
=#
# TODO: same for polygon, rectangle, ellipse
# TODO: batch needs to be exposed as something that users can construct and
# insert into a context. It doesn't make sense to make the same polygon over and
# over and then try to convert it to FormBach.
# Don't attempt to optimize for batching if the form is smaller than this.
const batch_length_threshold = 100
"""
Count the number of unique primitives in a property, stopping when max_count is
exceeded.
"""
function count_unique_primitives(property::Property, max_count::Int)
unique_primitives = Set{eltype(property.primitives)}()
for primitive in property.primitives
push!(unique_primitives, primitive)
length(unique_primitives) > max_count && break
end
return length(unique_primitives)
end
"""
Remove and return vector forms and vector properties from the Context.
"""
function excise_vector_children!(ctx::Context)
# excise vector forms
prev_form_child = form_child = ctx.form_children
forms = Form[]
while !isa(form_child, ListNull)
if length(form_child.head.primitives) > 1
push!(forms, form_child.head)
if prev_form_child == form_child
prev_form_child = ctx.form_children = form_child.tail
else
prev_form_child.tail = form_child.tail
end
else
prev_form_child = form_child
end
form_child = form_child.tail
end
# excise vector properties
prev_property_child = property_child = ctx.property_children
properties = Property[]
while !isa(property_child, ListNull)
if length(property_child.head.primitives) > 1
push!(properties, property_child.head)
if prev_property_child == property_child
prev_property_child = ctx.property_children = property_child.tail
else
prev_property_child.tail = property_child.tail
end
else
prev_property_child = property_child
end
property_child = property_child.tail
end
return (forms, properties)
end
"""
Attempt to transform a tree into an equivalent tree that can more easily be
batched.
What this does is look for patterns in which a long vector form is accompanied
by a large vector property that has a relatively small number of unique values.
If there are n unique values, we can split it into n contexts, each with a
shorter vector form and only scalar properties.
"""
function optimize_batching(ctx::Context)
# condition 1: has a 1 or more long vector forms
max_form_length = 0
form_child = ctx.form_children
while !isa(form_child, ListNull)
max_form_length = max(max_form_length, length(form_child.head.primitives))
form_child = form_child.tail
end
max_form_length < batch_length_threshold && return ctx
# condition 2: has a 1 or more long vector properties each with a smaller
# number of unique values
max_count = div(max_form_length, batch_length_threshold) + 1
max_unique_primitives = 0
prop_child = ctx.property_children
while !isa(prop_child, ListNull)
if length(prop_child.head.primitives) > 1
max_unique_primitives = max(max_unique_primitives,
count_unique_primitives(prop_child.head, max_count))
end
prop_child = prop_child.tail
end
# don't batch when there are not many forms per unique property primitive
if max_unique_primitives == 0 ||
div(max_form_length, max_unique_primitives) + 1 < batch_length_threshold
return ctx
end
# non-destructive since this happens at draw time and draw should not modify
# the context.
ctx = copy(ctx)
# step 1: remove vector form and vector properties
forms, properties = excise_vector_children!(ctx)
# step 2: split primitives into groups on the cross product of property
# primives
n = length(forms[1].primitives)
grouped_forms = Dict{UInt, Vector{Form}}()
grouped_properties = Dict{UInt, Vector{Property}}()
for i in 1:n
h = UInt(0)
for property in properties
h = hash(property.primitives[i], h)
end
if !haskey(grouped_forms, h)
grouped_forms[h] = Form[similar(form) for form in forms]
group_prop = Array{Property}(undef, length(properties))
for j in 1:length(properties)
group_prop[j] = Property([properties[j].primitives[i]])
end
grouped_properties[h] = group_prop
end
for j in 1:length(forms)
push!(grouped_forms[h][j].primitives, forms[j].primitives[i])
end
end
# step 3: put forms in new contexts and insert into the ctx
for (h, fs) in grouped_forms
subctx = context()
compose!(subctx, fs...)
compose!(subctx, grouped_properties[h]...)
compose!(ctx, subctx)
end
return ctx
end
================================================
FILE: src/cairo_backends.jl
================================================
import .Cairo: CairoContext, CairoSurface, CairoARGBSurface, CairoEPSSurface,
CairoPDFSurface, CairoSVGSurface, CairoImageSurface
abstract type ImageBackend end
abstract type PNGBackend <: ImageBackend end
abstract type VectorImageBackend <: ImageBackend end
abstract type SVGBackend <: VectorImageBackend end
abstract type PDFBackend <: VectorImageBackend end
abstract type PSBackend <: VectorImageBackend end
abstract type CairoBackend <: VectorImageBackend end
mutable struct ImagePropertyState
stroke::RGBA{Float64}
fill::RGBA{Float64}
stroke_dash::Array{Float64,1}
stroke_linecap::LineCap
stroke_linejoin::LineJoin
visible::Bool
linewidth::AbsoluteLength
fontsize::AbsoluteLength
font::AbstractString
clip::Union{ClipPrimitive, Nothing}
arrow::Bool
end
mutable struct ImagePropertyFrame
# Vector properties in this frame.
vector_properties::Dict{Type, Property}
# True if this property frame has scalar properties. Scalar properties are
# emitted as a group (<g> tag) that must be closed when the frame is popped.
has_scalar_properties::Bool
end
ImagePropertyFrame() = ImagePropertyFrame(Dict{Type, Property}(), false)
mutable struct Image{B<:ImageBackend} <: Backend
out::IO
surface::CairoSurface
ctx::CairoContext
width::Float64
height::Float64
# Current state
stroke::RGBA{Float64}
fill::RGBA{Float64}
stroke_dash::Array{Float64,1}
stroke_linecap::LineCap
stroke_linejoin::LineJoin
visible::Bool
linewidth::AbsoluteLength
fontsize::AbsoluteLength
font::AbstractString
clip::Union{ClipPrimitive, Nothing}
arrow::Bool
# Keep track of property
state_stack::Vector{ImagePropertyState}
property_stack::Vector{ImagePropertyFrame}
vector_properties::Dict{Type, Union{Property, Nothing}}
# Close the surface when finished
owns_surface::Bool
# Backend is responsible for opening/closing the file
ownedfile::Bool
# Filename when ownedfile is true
filename::Union{AbstractString, Nothing}
# True when finish has been called and no more drawing should occur
finished::Bool
# Emit on finish
emit_on_finish::Bool
# Points (or pixels for PNG) per mm
ppmm::Float64
# For use with the t/T and s/S commands in SVG-style paths
last_ctrl1_point::Union{AbsoluteVec2, Nothing}
last_ctrl2_point::Union{AbsoluteVec2, Nothing}
end
function Image{B}(surface::CairoSurface,
ctx::CairoContext,
out::IO;
width = 0,
height = 0,
stroke = default_stroke_color == nothing ?
RGBA{Float64
gitextract_ye7p7qi7/
├── .github/
│ └── workflows/
│ ├── CI.yml
│ ├── CompatHelper.yml
│ └── TagBot.yml
├── .gitignore
├── LICENSE.md
├── Project.toml
├── README.md
├── TODO.md
├── deps/
│ ├── glyphsize.c
│ ├── glyphsize.json
│ ├── mkfile
│ └── snap.svg-min.js
├── docs/
│ ├── Project.toml
│ ├── make.jl
│ └── src/
│ ├── gallery/
│ │ ├── forms.md
│ │ ├── properties.md
│ │ └── transforms.md
│ ├── index.md
│ ├── library.md
│ └── tutorial.md
├── src/
│ ├── Compose.jl
│ ├── abandoned.jl
│ ├── batch.jl
│ ├── cairo_backends.jl
│ ├── container.jl
│ ├── fontfallback.jl
│ ├── form.jl
│ ├── immerse_backend.jl
│ ├── list.jl
│ ├── measure.jl
│ ├── misc.jl
│ ├── pango.jl
│ ├── pgf_backend.jl
│ ├── property.jl
│ ├── stack.jl
│ ├── svg.jl
│ ├── table-jump.jl
│ └── table.jl
└── test/
├── .gitignore
├── Project.toml
├── examples/
│ ├── arc_sector.jl
│ ├── arrow.jl
│ ├── bezigon.jl
│ ├── dashedlines.jl
│ ├── forms_and_nans.jl
│ ├── golden_rect.jl
│ ├── linecaps.jl
│ ├── linejoins.jl
│ ├── polygon_forms.jl
│ ├── primitives.jl
│ ├── text.jl
│ ├── transformations.jl
│ └── unicode.jl
├── immerse.jl
├── misc.jl
├── runtests.jl
└── svg.jl
SYMBOL INDEX (72 symbols across 2 files)
FILE: deps/glyphsize.c
function dumpfont (line 12) | void dumpfont(FT_Library library, const char* fn)
function main (line 79) | int main(int argc, char* argv[])
FILE: deps/snap.svg-min.js
function a (line 12) | function a(c,t){if(c){if(c.tagName)return x(c);if(y(c,"array")&&a.set)re...
function v (line 12) | function v(c,a){if(a){"#text"==c&&(c=G.doc.createTextNode(a.text||""));"...
function y (line 13) | function y(c,a){a=J.prototype.toLowerCase.call(a);return"finite"==a?isFi...
function M (line 14) | function M(c){if("function"==typeof c||Object(c)!==c)return c;var a=new ...
function A (line 14) | function A(c,a,b){function m(){var e=Array.prototype.slice.call(argument...
function w (line 15) | function w(c,a,b,m,e,f){return null==e?(c-=b,a-=m,c||a?(180*I.atan2(-a,-...
function z (line 15) | function z(c){return c%360*C/180}
function d (line 15) | function d(c){var a=[];c=c.replace(/(?:^|\s)(\w+)\(([^)]+)\)/g,function(...
function f (line 16) | function f(c,t){var b=O(c),m=new a.Matrix;if(b)for(var e=0,f=b.length;e<...
function n (line 17) | function n(c,t){if(null==t){var m=!0;t="linearGradient"==c.type||"radial...
function u (line 18) | function u(c){c=c.node.ownerSVGElement&&x(c.node.ownerSVGElement)||c.nod...
function p (line 18) | function p(c){return c.node.ownerSVGElement&&
function b (line 19) | function b(c,a,m){function b(c){if(null==c)return aa;if(c==+c)return c;v...
function q (line 21) | function q(c){y(c,"array")||(c=Array.prototype.slice.call(arguments,0));...
function e (line 21) | function e(c){if(c.snap in E)return E[c.snap];var a=this.id=V(),b;try{b=...
function l (line 22) | function l(c){this.node=c}
function r (line 22) | function r(c,a){var b=v(c);a.appendChild(b);return x(b)}
function s (line 22) | function s(c,a){var b,m,f,d=s.prototype;if(c&&"svg"==c.tagName){if(c.sna...
function x (line 23) | function x(c){return!c||c instanceof e||c instanceof l?c:c.tagName&&"svg...
function m (line 39) | function m(c){function a(c,
function e (line 41) | function e(c,a,b){return function(m){m=m.slice(c,a);1==m.length&&(m=m[0]...
function d (line 41) | function d(c){return function(){var a=c?"<"+this.type:"",b=this.node.att...
function w (line 63) | function w(a,d,f,b,q,e){null==
function k (line 64) | function k(a){return a[0]*a[0]+a[1]*a[1]}
function p (line 64) | function p(a){var d=f.sqrt(k(a));a[0]&&(a[0]/=d);a[1]&&(a[1]/=d)}
function w (line 69) | function w(h){return function(d){k.stop();d instanceof A&&1==d.node.chil...
function z (line 71) | function z(a){k.stop();a==+a&&(a+="px");this.node.style.fontSize=a}
function d (line 71) | function d(a){var b=[];a=a.childNodes;for(var e=0,f=a.length;e<f;e++){va...
function f (line 71) | function f(){k.stop();return this.node.style.fontSize}
function b (line 78) | function b(d){return function(){k.stop();var b=M.doc.defaultView.getComp...
function d (line 78) | function d(a){return function(b){k.stop();var d="marker"+a.charAt(0).toU...
function w (line 82) | function w(a){return a}
function z (line 82) | function z(a){return function(b){return+b.toFixed(3)+a}}
function a (line 84) | function a(){this.parentNode.removeChild(this)}
function d (line 89) | function d(){return this.selectAll("stop")}
function n (line 89) | function n(b,d){var f=e("stop"),k={offset:+d+"%"};b=a.color(b);k["stop-c...
function u (line 89) | function u(){if("linearGradient"==this.type){var b=e(this.node,"x1")||0,...
function p (line 90) | function p(a,d){function f(a,b){for(var d=(b-u)/(a-w),e=w;e<a;e++)h[e].o...
function b (line 91) | function b(b,k,p,q,w){b=a._.make("linearGradient",b);b.stops=d;b.addStop...
function q (line 91) | function q(b,k,p,q,w,h){b=a._.make("radialGradient",b);b.stops=d;b.addSt...
function A (line 93) | function A(a){var b=A.ps=A.ps||{};b[a]?b[a].sleep=100:b[a]={sleep:100};s...
function w (line 93) | function w(a,b,d,e){null==a&&(a=b=d=e=0);null==b&&(b=a.y,d=a.width,e=a.h...
function z (line 94) | function z(){return this.join(",").replace(N,"$1")}
function d (line 94) | function d(a){a=C(a);a.toString=z;return a}
function f (line 94) | function f(a,b,d,h,f,k,l,n,p){if(null==p)return e(a,b,d,h,f,k,l,n);if(0>...
function n (line 94) | function n(b,d){function e(a){return+(+a).toFixed(3)}return a._.cacher(f...
function u (line 96) | function u(a,b,d,e,h,f,k,l,n){var p=1-n,q=ma(p,3),s=ma(p,2),c=n*n,t=c*n,...
function p (line 96) | function p(b,d,e,h,f,n,k,l){a.is(b,
function b (line 97) | function b(a,b,d){return b>=a.x&&b<=a.x+a.width&&d>=a.y&&d<=a.y+a.height}
function q (line 97) | function q(a,d){a=w(a);d=w(d);return b(d,a.x,a.y)||b(d,a.x2,a.y)||b(d,a....
function e (line 97) | function e(a,b,d,e,h,f,n,k,l){null==l&&(l=1);l=(1<l?1:0>l?0:l)/2;for(var...
function l (line 98) | function l(a,b,d){a=I(a);b=I(b);for(var h,f,l,n,k,s,r,O,x,c,t=d?0:[],w=0...
function r (line 102) | function r(a){var b=A(a);if(b.bbox)return C(b.bbox);if(!a)return w();a=I...
function s (line 102) | function s(a,b,d,e,h){if(h)return[["M",+a+ +h,b],["l",d-2*h,0],["a",h,h,...
function x (line 103) | function x(a,b,d,e,h){null==h&&null==e&&(e=d);a=+a;b=+b;d=+d;e=+e;if(nul...
function G (line 103) | function G(b){var e=
function h (line 106) | function h(a,b,d,e){return[a,b,d,e,d,
function J (line 107) | function J(a,b,d,e,h,f){var l=1/3,n=2/3;return[l*a+n*d,l*b+n*e,l*h+n*d,l...
function K (line 107) | function K(b,d,e,h,f,l,n,k,p,s){var r=120*S/180,q=S/180*(+f||0),c=[],t,x...
function U (line 109) | function U(a,b,d,e,h,f,l,k){for(var n=[],p=[[],[]],s,r,c,t,q=0;2>q;++q)0...
function I (line 110) | function I(a,b){var e=!b&&A(a);if(!b&&e.curve)return d(e.curve);var f=G(...
function P (line 113) | function P(a,
function A (line 125) | function A(a){var b=a[0];switch(b.toLowerCase()){case "t":return[b,0,0];...
function w (line 125) | function w(b,d,f){d=q(d).replace(/\.{3}|\u2026/g,b);b=a.parseTransformSt...
function z (line 127) | function z(a){return a}
function d (line 127) | function d(a){return function(b){return+b.toFixed(3)+a}}
function f (line 127) | function f(b){return a.rgb(b[0],b[1],b[2])}
function n (line 127) | function n(a){var b=0,d,f,k,n,h,p,q=[];d=0;for(f=a.length;d<f;d++){h="["...
function u (line 127) | function u(a){for(var b=[],d=0,f=a.length;d<f;d++)for(var k=1,n=a[d].len...
function u (line 134) | function u(r,v,w){(r.originalEvent||r).preventDefault();this._drag.x=v;
Condensed preview — 57 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (465K chars).
[
{
"path": ".github/workflows/CI.yml",
"chars": 1477,
"preview": "name: CI\n\non:\n pull_request:\n branches:\n - master\n push:\n branches:\n - master\n tags: '*'\n\njobs:\n t"
},
{
"path": ".github/workflows/CompatHelper.yml",
"chars": 638,
"preview": "name: CompatHelper\n\non:\n schedule:\n - cron: '0 0 * * 0'\n issues:\n types: [opened, reopened]\n\njobs:\n build:\n "
},
{
"path": ".github/workflows/TagBot.yml",
"chars": 360,
"preview": "name: TagBot\non:\n issue_comment:\n types:\n - created\n workflow_dispatch:\njobs:\n TagBot:\n if: github.event_n"
},
{
"path": ".gitignore",
"chars": 715,
"preview": "*~\n*swp\n\n# System-specific files and directories generated by the BinaryProvider and BinDeps packages\n# They contain abs"
},
{
"path": "LICENSE.md",
"chars": 1170,
"preview": "Compose is licensed under the MIT License:\n\n> Copyright (c) 2012--2015: Daniel C. Jones and other contributors\n>\n> Permi"
},
{
"path": "Project.toml",
"chars": 955,
"preview": "name = \"Compose\"\nuuid = \"a81c6b42-2e10-5240-aca2-a61377ecd94b\"\nversion = \"0.9.6\"\n\n[deps]\nBase64 = \"2a0f44e3-6c83-55bd-87"
},
{
"path": "README.md",
"chars": 1338,
"preview": "# Compose!\n\n[![][docs-latest-img]][docs-latest-url] [![][travis-img]][travis-url] [![][codecov-img]][codecov-url]\n\nCompo"
},
{
"path": "TODO.md",
"chars": 139,
"preview": "\n* Coherent hstack and vstack functions.\n* Documentation!!!\n* Functions for arranging canvases in, e.g. grids.\n* Embeddi"
},
{
"path": "deps/glyphsize.c",
"chars": 2832,
"preview": "\n/* Use freetype to read a font and dump typeface name and glyph sizes for\n * printable ascii characters into an easily "
},
{
"path": "deps/glyphsize.json",
"chars": 43509,
"preview": "{\n\"Helvetica Neue Bold\": {\n \"widths\": {\n \" \": 1.18, \"!\": 1.18, \"\\\"\": 1.96, \"#\": 2.35, \"$\": 2.35,\n \"%"
},
{
"path": "deps/mkfile",
"chars": 1021,
"preview": "\n# Mkfile for updating the glyphsize table. This is not intended for general use.\n# If you really want to use it, you'll"
},
{
"path": "deps/snap.svg-min.js",
"chars": 73203,
"preview": "(function(N){var k=/[\\.\\/]/,L=/\\s*,\\s*/,C=function(a,d){return a-d},a,v,y={n:{}},M=function(){for(var a=0,d=this.length;"
},
{
"path": "docs/Project.toml",
"chars": 305,
"preview": "[deps]\nCairo = \"159f3aea-2a34-519c-b102-8c37f9878175\"\nColors = \"5ae59095-9a9b-59fe-a467-6f913c188581\"\nCompose = \"a81c6b4"
},
{
"path": "docs/make.jl",
"chars": 628,
"preview": "using Documenter, Compose\nimport Cairo\n\nstruct SVGJSWritable{T}\n x :: T\nend\nBase.show(io::IO, m::MIME\"text/html\", x::"
},
{
"path": "docs/src/gallery/forms.md",
"chars": 6321,
"preview": "```@meta\nAuthor = [\"Mattriks\"]\n```\n\n\n# [Forms](@id forms_gallery)\n\n## [`arc`](@ref)\n \n```@example\nusing Compose\nset_defa"
},
{
"path": "docs/src/gallery/properties.md",
"chars": 1589,
"preview": "```@meta\nAuthor = [\"Mattriks\"]\n```\n\n\n# [Properties](@id properties_gallery)\n\n\n## [`arrow`](@ref)\n \n```@example\nusing Com"
},
{
"path": "docs/src/gallery/transforms.md",
"chars": 2720,
"preview": "```@meta\nAuthor = [\"Mattriks\"]\n```\n\n\n# [Transformations](@id transforms_gallery)\n\n## [`Mirror`](@ref)\n\n```@example\nusing"
},
{
"path": "docs/src/index.md",
"chars": 1422,
"preview": "```@meta\nAuthor = [\"Daniel C. Jones\", \"Gio Borje\", \"Tamas Nagy\"]\n```\n\n# Compose\n\nCompose is a declarative vector graphic"
},
{
"path": "docs/src/library.md",
"chars": 37,
"preview": "```@autodocs\nModules = [Compose]\n```\n"
},
{
"path": "docs/src/tutorial.md",
"chars": 12933,
"preview": "```@meta\nAuthor = [\"Daniel C. Jones\", \"Gio Borje\", \"Tamas Nagy\"]\n```\n\n# Tutorial\n\n\n## Compose is declarative\n\nIn a decla"
},
{
"path": "src/Compose.jl",
"chars": 9246,
"preview": "module Compose\n\nusing Colors\nusing IterTools\nusing DataStructures\nusing Measures\nusing Requires\nusing Dates\nusing Printf"
},
{
"path": "src/abandoned.jl",
"chars": 24543,
"preview": "\n# Path Primitives\n\n\n# From form.jl:\n# Path\n# ----\n\n# An implementation of the SVG path mini-language.\n\nabstract type Pa"
},
{
"path": "src/batch.jl",
"chars": 7218,
"preview": "\"\"\"\nA form batch is a vectorized form with n primitives transformed into a simpler\nrepresentation: one primitive reposit"
},
{
"path": "src/cairo_backends.jl",
"chars": 28676,
"preview": "import .Cairo: CairoContext, CairoSurface, CairoARGBSurface, CairoEPSSurface,\nCairoPDFSurface, CairoSVGSurface, CairoIma"
},
{
"path": "src/container.jl",
"chars": 21162,
"preview": "# A container is a node in the tree that can have Forms, Properties, or other\n# Containers as children.\nabstract type Co"
},
{
"path": "src/fontfallback.jl",
"chars": 7041,
"preview": "# Font handling when pango and fontconfig are not available.\n\n# Define this even if we're not calling pango, since cairo"
},
{
"path": "src/form.jl",
"chars": 29927,
"preview": "# A form is something that ends up as geometry in the graphic.\n\nabstract type FormPrimitive end\n\nconst empty_tag = Symbo"
},
{
"path": "src/immerse_backend.jl",
"chars": 2099,
"preview": "# The Immerse backend\n# To the Cairo backend, this adds just one feature: keeping track of\n# the rendered coordinates of"
},
{
"path": "src/list.jl",
"chars": 1144,
"preview": "# Basic list\n\nabstract type List{T} end\n\nstruct ListNull{T} <: List{T} end\n\ncopy(l::ListNull{T}) where {T} = l\n\nmutable "
},
{
"path": "src/measure.jl",
"chars": 15206,
"preview": "using Measures: Add, Min, Max, Div, Mul, Neg\nusing LinearAlgebra\n\n# Measure Constants\n# -----------------\n\nconst cx = Le"
},
{
"path": "src/misc.jl",
"chars": 6415,
"preview": "iszero(x::T) where T = x == zero(T)\n\nMaybe(T::Type) = Union{T, Nothing}\n\nfunction in_expr_args(ex::Expr)\n ex.head ==="
},
{
"path": "src/pango.jl",
"chars": 14022,
"preview": "# Estimation of text extents using pango.\n\nconst libpangocairo = Cairo.libpangocairo\nconst libpango = Cairo.libpango\ncon"
},
{
"path": "src/pgf_backend.jl",
"chars": 22366,
"preview": "mutable struct PGFPropertyFrame\n # Vector properties in this frame.\n vector_properties::Dict{Type, Property}\n\n "
},
{
"path": "src/property.jl",
"chars": 14821,
"preview": "abstract type PropertyPrimitive end\n\n# Meaningless isless function used to sort in optimize_batching\nfunction Base.isles"
},
{
"path": "src/stack.jl",
"chars": 4522,
"preview": "# Convenience function for rearranging contexts\n\n# Create a new context containing the given contexts stacked horizontal"
},
{
"path": "src/svg.jl",
"chars": 41368,
"preview": "using Base64\nusing UUIDs\nusing Random\n\nconst snapsvgjs = joinpath(@__DIR__, \"..\", \"deps\", \"snap.svg-min.js\")\n\n# Packages"
},
{
"path": "src/table-jump.jl",
"chars": 5790,
"preview": "using JuMP\n\nis_approx_integer(x::Float64) = abs(x - round(x)) < 1e-8\n\nfunction realize(tbl::Table, drawctx::ParentDrawCo"
},
{
"path": "src/table.jl",
"chars": 12642,
"preview": "# A special kind of container promise that performs table layout optimization.\n\nmutable struct Table <: ContainerPromise"
},
{
"path": "test/.gitignore",
"chars": 7,
"preview": "/*.pdf\n"
},
{
"path": "test/Project.toml",
"chars": 479,
"preview": "[deps]\nCairo = \"159f3aea-2a34-519c-b102-8c37f9878175\"\nColors = \"5ae59095-9a9b-59fe-a467-6f913c188581\"\nEzXML = \"8f5d6c58-"
},
{
"path": "test/examples/arc_sector.jl",
"chars": 493,
"preview": "using Compose\nimport Cairo, Fontconfig\n\nimgs = [SVG(\"arc_sector.svg\", 7cm, 7cm),\n PDF(\"arc_sector.pdf\", 7cm, 7cm)"
},
{
"path": "test/examples/arrow.jl",
"chars": 402,
"preview": "using Compose\nimport Cairo, Fontconfig\n\nimgs = [SVG(\"arrow.svg\", 5cm, 5cm),\n PDF(\"arrow.pdf\", 5cm, 5cm)]\n\nX = [0"
},
{
"path": "test/examples/bezigon.jl",
"chars": 799,
"preview": "using Compose\nimport Cairo, Fontconfig\n\nset_default_graphic_size(6.6inch, 3.3inch)\n\n# See Picasso's \"dog\" sketch\ndog = ["
},
{
"path": "test/examples/dashedlines.jl",
"chars": 863,
"preview": "# Draw lines with various dash styles.\n\nusing Compose, Colors\nimport Cairo, Fontconfig\n\nfunction draw_lines(dash_pattern"
},
{
"path": "test/examples/forms_and_nans.jl",
"chars": 439,
"preview": "using Compose\nimport Cairo, Fontconfig\n\nset_default_graphic_size(14cm, 10cm)\n\n\ny = [0.26, 0.5, missing, 0.4, NaN, 0.48, "
},
{
"path": "test/examples/golden_rect.jl",
"chars": 443,
"preview": "using Compose, Colors\nusing Base.MathConstants\n\nfunction golden_rect(n::Int)\n poly_points = [(0, 0), (1, 0), (1, 1), "
},
{
"path": "test/examples/linecaps.jl",
"chars": 573,
"preview": "# Draw lines with various dash styles.\n\nusing Compose, Colors\nimport Cairo, Fontconfig\n\nfunction draw_lines(caps)\n if"
},
{
"path": "test/examples/linejoins.jl",
"chars": 679,
"preview": "# Draw lines with various dash styles.\n\nusing Compose, Colors\nimport Cairo, Fontconfig\n\nfunction draw_lines(joins)\n i"
},
{
"path": "test/examples/polygon_forms.jl",
"chars": 180,
"preview": "using Compose\n\ncompose(context(),\n ngon(0.15, 0.15, 0.08, 5),\n star(0.35, 0.15, 0.08, 5, 0.3),\n xgon(0.55, 0.15"
},
{
"path": "test/examples/primitives.jl",
"chars": 458,
"preview": "using Compose\n\nrawimg = read(joinpath(@__DIR__,\"smiley.png\"));\n\ncompose(context(),\n rectangle(0.1,0.1,0.1,0.1),\n c"
},
{
"path": "test/examples/text.jl",
"chars": 594,
"preview": "# Draw some text to a PNG image.\n\nusing Compose\n\nlines = \"hello and goodbye\\nFoo<sub>Sub</sub>Bar<sup>Sup</sup>\\nA Third"
},
{
"path": "test/examples/transformations.jl",
"chars": 479,
"preview": "using Compose\nimport Cairo, Fontconfig\n\nimgs = [SVG(\"transformations.svg\", 7cm, 7cm),\n PDF(\"transformations.pdf\","
},
{
"path": "test/examples/unicode.jl",
"chars": 410,
"preview": "# Draw some unicodes to an image.\n# https://github.com/GiovineItalia/Compose.jl/pull/360#issuecomment-539283765\n\nusing C"
},
{
"path": "test/immerse.jl",
"chars": 2239,
"preview": "# These tests are designed to ensure that Immerse.jl works. If you\n# need to edit these tests to make them pass, that's "
},
{
"path": "test/misc.jl",
"chars": 7703,
"preview": "using Compose, Test, Random, Colors\n\n# must be before importing cairo\n@testset \"missing cairo errors\" begin\n ctx = co"
},
{
"path": "test/runtests.jl",
"chars": 329,
"preview": "using Test\n\ninclude(\"misc.jl\")\ninclude(\"svg.jl\")\ninclude(\"immerse.jl\")\n\n# Run the examples\ncd(joinpath(@__DIR__, \"output"
},
{
"path": "test/svg.jl",
"chars": 691,
"preview": "using Compose\nusing Test\nusing EzXML\nusing Colors\nusing Measures\n\n@testset \"Issue 267\" begin\n global c = compose(cont"
}
]
About this extraction
This page contains the full source code of the GiovineItalia/Compose.jl GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 57 files (429.5 KB), approximately 148.3k tokens, and a symbol index with 72 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.