Full Code of GiovineItalia/Compose.jl for AI

master 2a442dd2fcc8 cached
57 files
429.5 KB
148.3k tokens
72 symbols
1 requests
Download .txt
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
```

![](tomato.svg)

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
```

![](tomato_bisque.svg)

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

![](tomatos.svg)

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
```

![](tomato_bisque_triangle.svg)


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

![](circles.svg)

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
```

![](cycled_circles.svg)

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
```

![](circles_fill_vectorized.svg)

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
```

![](sierpinski.svg)

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&#162; in a &#36;"))
cents_ina_dollar |> SVG("dollar.svg",5cm,1cm)
nothing # hide
```

![](dollar.svg)

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
```

![](font_fontsize.svg)




================================================
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
Download .txt
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
Download .txt
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.

Copied to clipboard!