Scalable Executable Vector Graphics Interface

Sevgi

Create SVG with Ruby

The power of Ruby

Use Ruby's elegant programming model and computational power to create precise SVG without reaching for a vector editor every time.

Rich helpers

Extend the DSL through mixins and use helpers for tiling, hatching, rulers, grids, transforms, and geometry.

Neat output

Generate properly indented, readable, lightly validated SVG output without artificial bloat.

Script mode

Run executable .sevgi files directly when a drawing belongs in a small, repeatable script.

Round trip

Bring existing SVG/XML back into the DSL workflow when a visual editor is part of the process.

PDF/PNG export

Export SVG drawings to PDF or PNG through the optional native output pipeline when a workflow needs fixed artifacts.

Showcase Examples

These examples1 are the executable .sevgi files from showcase/srv, not copies written for the site. The test suite runs each file and compares its output. Open the Ruby panel for the script and the SVG panel for the result. Most are small enough to read in one sitting, though a few keep enough detail to show how a real drawing comes together.

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

SVG :minimal, width: 100, height: 100 do
  rect x: 0, y: 0, width: 100, height: 100, fill: "white"
  path fill: "purple", d: %w[
    M10 101 V50 A40 40 0 0 1 90 50 V101
    L76 85 L63 101 L50 85 L37 101 L24 85 Z
  ]

  [25, 50].each do |x|
    circle cx: x, cy: 40, r: 8, fill: "white"
  end
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

SVG :minimal, width: 100, height: 100 do
  rect x: 0, y: 0, width: 100, height: 100, fill: "#222222"
  path fill: "#e5c39c", d: %w[
    M10 101 V50 A40 40 0 0 1 90 50 V101
    L76 85 L63 101 L50 85 L37 101 L24 85 Z
  ]

  [25, 50].each do |x|
    circle cx: x, cy: 40, r: 8, fill: "#222222"
  end
end.Save
<svg width="100" height="100">
  <rect x="0" y="0" width="100" height="100" fill="white"/>
  <path fill="purple" d="M10 101 V50 A40 40 0 0 1 90 50 V101 L76 85 L63 101 L50 85 L37 101 L24 85 Z"/>
  <circle cx="25" cy="40" r="8" fill="white"/>
  <circle cx="50" cy="40" r="8" fill="white"/>
</svg>
<svg width="100" height="100">
  <rect x="0" y="0" width="100" height="100" fill="#222222"/>
  <path fill="#e5c39c" d="M10 101 V50 A40 40 0 0 1 90 50 V101 L76 85 L63 101 L50 85 L37 101 L24 85 Z"/>
  <circle cx="25" cy="40" r="8" fill="#222222"/>
  <circle cx="50" cy="40" r="8" fill="#222222"/>
</svg>

Pokey

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

SIZE = 20
COLORS = %w[#FF6961 #77DD77 #FFD700].freeze
COLS = 9
ROWS = 4

SVG :minimal,
    width: COLS * SIZE,
    height: ROWS * SIZE,
    viewBox: "0 0 #{COLS * SIZE} #{ROWS * SIZE}" do
  css ".cell" => { stroke: "white" }

  COLS.times do |col|
    ROWS.times do |row|
      rect class: "cell",
           x: col * SIZE, y: row * SIZE,
           width: SIZE, height: SIZE,
           rx: (SIZE * 0.1).round,
           fill: COLORS[(col + row) % COLORS.length]
    end
  end
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

SIZE = 20
COLORS = %w[#f27b72 #7fdc9c #f1c95b].freeze
COLS = 9
ROWS = 4

SVG :minimal,
    width: COLS * SIZE,
    height: ROWS * SIZE,
    viewBox: "0 0 #{COLS * SIZE} #{ROWS * SIZE}" do
  css ".cell" => { stroke: "white" }

  COLS.times do |col|
    ROWS.times do |row|
      rect class: "cell",
           x: col * SIZE, y: row * SIZE,
           width: SIZE, height: SIZE,
           rx: (SIZE * 0.1).round,
           fill: COLORS[(col + row) % COLORS.length]
    end
  end
end.Save
<svg width="180" height="80" viewBox="0 0 180 80">
  <style type="text/css">
    <![CDATA[
      .cell {
        stroke: white;
      }
    ]]>
  </style>
  <rect class="cell" x="0" y="0" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="0" y="20" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="0" y="40" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="0" y="60" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="20" y="0" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="20" y="20" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="20" y="40" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="20" y="60" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="40" y="0" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="40" y="20" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="40" y="40" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="40" y="60" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="60" y="0" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="60" y="20" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="60" y="40" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="60" y="60" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="80" y="0" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="80" y="20" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="80" y="40" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="80" y="60" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="100" y="0" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="100" y="20" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="100" y="40" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="100" y="60" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="120" y="0" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="120" y="20" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="120" y="40" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="120" y="60" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="140" y="0" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="140" y="20" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="140" y="40" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="140" y="60" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="160" y="0" width="20" height="20" rx="2" fill="#FFD700"/>
  <rect class="cell" x="160" y="20" width="20" height="20" rx="2" fill="#FF6961"/>
  <rect class="cell" x="160" y="40" width="20" height="20" rx="2" fill="#77DD77"/>
  <rect class="cell" x="160" y="60" width="20" height="20" rx="2" fill="#FFD700"/>
</svg>
<svg width="180" height="80" viewBox="0 0 180 80">
  <style type="text/css">
    <![CDATA[
      .cell {
        stroke: white;
      }
    ]]>
  </style>
  <rect class="cell" x="0" y="0" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="0" y="20" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="0" y="40" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="0" y="60" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="20" y="0" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="20" y="20" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="20" y="40" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="20" y="60" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="40" y="0" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="40" y="20" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="40" y="40" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="40" y="60" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="60" y="0" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="60" y="20" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="60" y="40" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="60" y="60" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="80" y="0" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="80" y="20" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="80" y="40" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="80" y="60" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="100" y="0" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="100" y="20" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="100" y="40" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="100" y="60" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="120" y="0" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="120" y="20" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="120" y="40" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="120" y="60" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="140" y="0" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="140" y="20" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="140" y="40" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="140" y="60" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="160" y="0" width="20" height="20" rx="2" fill="#f1c95b"/>
  <rect class="cell" x="160" y="20" width="20" height="20" rx="2" fill="#f27b72"/>
  <rect class="cell" x="160" y="40" width="20" height="20" rx="2" fill="#7fdc9c"/>
  <rect class="cell" x="160" y="60" width="20" height="20" rx="2" fill="#f1c95b"/>
</svg>

Grid

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

STAR = <<~PATH
  m 7.06716,10 v -2.930223 h 2.932843 l -2.073449,-2.073131 2.073449,-2.068098
  h -2.932843 v -2.928548 l -2.07848,2.074807 -2.067578,-2.074807 v 2.928547
  h -2.921102 l 2.060869,2.068098 -2.060869,2.073131 h 2.921102 v 2.930223
  l 2.067578,-2.066419 2.07848,2.066419
PATH

MARGIN = 4
SIZE = 48

SVG :minimal, width: SIZE, height: SIZE do
  rect width: SIZE, height: SIZE, rx: 1, fill: "white"

  Symbol("Star") { path d: STAR, fill: "purple" }
  Tile "star", nx: 4, dx: 10, ox: MARGIN, ny: 4, dy: 10, oy: MARGIN
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

STAR = <<~PATH
  m 7.06716,10 v -2.930223 h 2.932843 l -2.073449,-2.073131 2.073449,-2.068098
  h -2.932843 v -2.928548 l -2.07848,2.074807 -2.067578,-2.074807 v 2.928547
  h -2.921102 l 2.060869,2.068098 -2.060869,2.073131 h 2.921102 v 2.930223
  l 2.067578,-2.066419 2.07848,2.066419
PATH

MARGIN = 4
SIZE = 48

SVG :minimal, width: SIZE, height: SIZE do
  rect width: SIZE, height: SIZE, rx: 1, fill: "#222222"

  Symbol("Star") { path d: STAR, fill: "#e5c39c" }
  Tile "star", nx: 4, dx: 10, ox: MARGIN, ny: 4, dy: 10, oy: MARGIN
end.Save
<svg width="48" height="48">
  <rect width="48" height="48" rx="1" fill="white"/>
  <symbol id="star">
    <title>Star</title>
    <path
      d="m 7.06716,10 v -2.930223 h 2.932843 l -2.073449,-2.073131 2.073449,-2.068098
h -2.932843 v -2.928548 l -2.07848,2.074807 -2.067578,-2.074807 v 2.928547
h -2.921102 l 2.060869,2.068098 -2.060869,2.073131 h 2.921102 v 2.930223
l 2.067578,-2.066419 2.07848,2.066419
"
      fill="purple"
    />
  </symbol>
  <use id="star-1-1" href="#star" class="tile-row-1 tile-row-first tile-col-1 tile-col-first" x="4" y="4"/>
  <use id="star-1-2" href="#star" class="tile-row-1 tile-row-first tile-col-2" x="14" y="4"/>
  <use id="star-1-3" href="#star" class="tile-row-1 tile-row-first tile-col-3" x="24" y="4"/>
  <use id="star-1-4" href="#star" class="tile-row-1 tile-row-first tile-col-4 tile-col-last" x="34" y="4"/>
  <use id="star-2-1" href="#star" class="tile-row-2 tile-col-1 tile-col-first" x="4" y="14"/>
  <use id="star-2-2" href="#star" class="tile-row-2 tile-col-2" x="14" y="14"/>
  <use id="star-2-3" href="#star" class="tile-row-2 tile-col-3" x="24" y="14"/>
  <use id="star-2-4" href="#star" class="tile-row-2 tile-col-4 tile-col-last" x="34" y="14"/>
  <use id="star-3-1" href="#star" class="tile-row-3 tile-col-1 tile-col-first" x="4" y="24"/>
  <use id="star-3-2" href="#star" class="tile-row-3 tile-col-2" x="14" y="24"/>
  <use id="star-3-3" href="#star" class="tile-row-3 tile-col-3" x="24" y="24"/>
  <use id="star-3-4" href="#star" class="tile-row-3 tile-col-4 tile-col-last" x="34" y="24"/>
  <use id="star-4-1" href="#star" class="tile-row-4 tile-row-last tile-col-1 tile-col-first" x="4" y="34"/>
  <use id="star-4-2" href="#star" class="tile-row-4 tile-row-last tile-col-2" x="14" y="34"/>
  <use id="star-4-3" href="#star" class="tile-row-4 tile-row-last tile-col-3" x="24" y="34"/>
  <use id="star-4-4" href="#star" class="tile-row-4 tile-row-last tile-col-4 tile-col-last" x="34" y="34"/>
</svg>
<svg width="48" height="48">
  <rect width="48" height="48" rx="1" fill="#222222"/>
  <symbol id="star">
    <title>Star</title>
    <path
      d="m 7.06716,10 v -2.930223 h 2.932843 l -2.073449,-2.073131 2.073449,-2.068098
h -2.932843 v -2.928548 l -2.07848,2.074807 -2.067578,-2.074807 v 2.928547
h -2.921102 l 2.060869,2.068098 -2.060869,2.073131 h 2.921102 v 2.930223
l 2.067578,-2.066419 2.07848,2.066419
"
      fill="#e5c39c"
    />
  </symbol>
  <use id="star-1-1" href="#star" class="tile-row-1 tile-row-first tile-col-1 tile-col-first" x="4" y="4"/>
  <use id="star-1-2" href="#star" class="tile-row-1 tile-row-first tile-col-2" x="14" y="4"/>
  <use id="star-1-3" href="#star" class="tile-row-1 tile-row-first tile-col-3" x="24" y="4"/>
  <use id="star-1-4" href="#star" class="tile-row-1 tile-row-first tile-col-4 tile-col-last" x="34" y="4"/>
  <use id="star-2-1" href="#star" class="tile-row-2 tile-col-1 tile-col-first" x="4" y="14"/>
  <use id="star-2-2" href="#star" class="tile-row-2 tile-col-2" x="14" y="14"/>
  <use id="star-2-3" href="#star" class="tile-row-2 tile-col-3" x="24" y="14"/>
  <use id="star-2-4" href="#star" class="tile-row-2 tile-col-4 tile-col-last" x="34" y="14"/>
  <use id="star-3-1" href="#star" class="tile-row-3 tile-col-1 tile-col-first" x="4" y="24"/>
  <use id="star-3-2" href="#star" class="tile-row-3 tile-col-2" x="14" y="24"/>
  <use id="star-3-3" href="#star" class="tile-row-3 tile-col-3" x="24" y="24"/>
  <use id="star-3-4" href="#star" class="tile-row-3 tile-col-4 tile-col-last" x="34" y="24"/>
  <use id="star-4-1" href="#star" class="tile-row-4 tile-row-last tile-col-1 tile-col-first" x="4" y="34"/>
  <use id="star-4-2" href="#star" class="tile-row-4 tile-row-last tile-col-2" x="14" y="34"/>
  <use id="star-4-3" href="#star" class="tile-row-4 tile-row-last tile-col-3" x="24" y="34"/>
  <use id="star-4-4" href="#star" class="tile-row-4 tile-row-last tile-col-4 tile-col-last" x="34" y="34"/>
</svg>

Stars

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true
# Example taken from: https://svg-tutorial.com/svg/use

SVG :minimal, width: 200, height: 200, viewBox: "-100 -100 200 200" do
  path id: "branch", stroke: "purple", "stroke-width": 5, d: <<~PATH
    M 0 0 L 0 -90
    M 0 -20 L 20 -34
    M 0 -20 L -20 -34
    M 0 -40 L 20 -54
    M 0 -40 L -20 -54
    M 0 -60 L 20 -74
    M 0 -60 L -20 -74
  PATH

  60.step(300, 60) { use(href: "#branch").Rotate it }
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true
# Example taken from: https://svg-tutorial.com/svg/use

SVG :minimal, width: 200, height: 200, viewBox: "-100 -100 200 200" do
  path id: "branch", stroke: "#e5c39c", "stroke-width": 5, d: <<~PATH
    M 0 0 L 0 -90
    M 0 -20 L 20 -34
    M 0 -20 L -20 -34
    M 0 -40 L 20 -54
    M 0 -40 L -20 -54
    M 0 -60 L 20 -74
    M 0 -60 L -20 -74
  PATH

  60.step(300, 60) { use(href: "#branch").Rotate it }
end.Save
<svg width="200" height="200" viewBox="-100 -100 200 200">
  <path
    id="branch"
    stroke="purple"
    stroke-width="5"
    d="M 0 0 L 0 -90
M 0 -20 L 20 -34
M 0 -20 L -20 -34
M 0 -40 L 20 -54
M 0 -40 L -20 -54
M 0 -60 L 20 -74
M 0 -60 L -20 -74
"
  />
  <use href="#branch" transform="rotate(60)"/>
  <use href="#branch" transform="rotate(120)"/>
  <use href="#branch" transform="rotate(180)"/>
  <use href="#branch" transform="rotate(240)"/>
  <use href="#branch" transform="rotate(300)"/>
</svg>
<svg width="200" height="200" viewBox="-100 -100 200 200">
  <path
    id="branch"
    stroke="#e5c39c"
    stroke-width="5"
    d="M 0 0 L 0 -90
M 0 -20 L 20 -34
M 0 -20 L -20 -34
M 0 -40 L 20 -54
M 0 -40 L -20 -54
M 0 -60 L 20 -74
M 0 -60 L -20 -74
"
  />
  <use href="#branch" transform="rotate(60)"/>
  <use href="#branch" transform="rotate(120)"/>
  <use href="#branch" transform="rotate(180)"/>
  <use href="#branch" transform="rotate(240)"/>
  <use href="#branch" transform="rotate(300)"/>
</svg>

Snowflake

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

CLOVER = <<~PATH
  m 0,10 c 5.53264,0 10,-4.479747 10,-10 -5.52589,0 -10,4.488702 -10,10
PATH

CENTER = 13
SIZE = 26

SVG :minimal, width: SIZE, height: SIZE do
  rect width: SIZE, height: SIZE, rx: 0.75, fill: "white"
  defs { path id: "Clover", d: CLOVER, fill: "purple" }

  4.times do |quarter|
    leaf = use href: "#Clover", x: CENTER, y: CENTER - 10
    leaf.Rotate quarter * 90, CENTER, CENTER
  end
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

CLOVER = <<~PATH
  m 0,10 c 5.53264,0 10,-4.479747 10,-10 -5.52589,0 -10,4.488702 -10,10
PATH

CENTER = 13
SIZE = 26

SVG :minimal, width: SIZE, height: SIZE do
  rect width: SIZE, height: SIZE, rx: 0.75, fill: "#222222"
  defs { path id: "Clover", d: CLOVER, fill: "#e5c39c" }

  4.times do |quarter|
    leaf = use href: "#Clover", x: CENTER, y: CENTER - 10
    leaf.Rotate quarter * 90, CENTER, CENTER
  end
end.Save
<svg width="26" height="26">
  <rect width="26" height="26" rx="0.75" fill="white"/>
  <defs>
    <path id="Clover" d="m 0,10 c 5.53264,0 10,-4.479747 10,-10 -5.52589,0 -10,4.488702 -10,10
" fill="purple"/>
  </defs>
  <use href="#Clover" x="13" y="3"/>
  <use href="#Clover" x="13" y="3" transform="rotate(90, 13, 13)"/>
  <use href="#Clover" x="13" y="3" transform="rotate(180, 13, 13)"/>
  <use href="#Clover" x="13" y="3" transform="rotate(270, 13, 13)"/>
</svg>
<svg width="26" height="26">
  <rect width="26" height="26" rx="0.75" fill="#222222"/>
  <defs>
    <path id="Clover" d="m 0,10 c 5.53264,0 10,-4.479747 10,-10 -5.52589,0 -10,4.488702 -10,10
" fill="#e5c39c"/>
  </defs>
  <use href="#Clover" x="13" y="3"/>
  <use href="#Clover" x="13" y="3" transform="rotate(90, 13, 13)"/>
  <use href="#Clover" x="13" y="3" transform="rotate(180, 13, 13)"/>
  <use href="#Clover" x="13" y="3" transform="rotate(270, 13, 13)"/>
</svg>

Clover

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

TULIP = <<~PATH
  m 7.072424,8.784891 c -1.62123,1.620145 -4.24191,1.620145 -5.860483,0
  -1.611497,-1.619275 -1.62034,-4.239086 0,-5.854824 l 2.928473,-2.930067
  -0.48823,3.907639 3.42024,-0.977572 -0.98,3.417962 3.90758,-0.488766
  -2.92758,2.925628
PATH

CENTER = 13
SIDE = 3.5
ANCHOR = [1.211941, 8.784891].freeze
CORNER = [CENTER + (SIDE / 2), CENTER - (SIDE / 2)].freeze
SIZE = 26

SVG :minimal, width: SIZE, height: SIZE do
  rect width: SIZE, height: SIZE, rx: 0.75, fill: "white"
  defs { path id: "Tulip", d: TULIP, fill: "purple" }

  4.times do |quarter|
    flower = use href: "#Tulip", x: CORNER[0] - ANCHOR[0], y: CORNER[1] - ANCHOR[1]
    flower.Rotate quarter * 90, CENTER, CENTER
  end

  square x: CENTER - (SIDE / 2), y: CENTER - (SIDE / 2), length: SIDE, fill: "purple"
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

TULIP = <<~PATH
  m 7.072424,8.784891 c -1.62123,1.620145 -4.24191,1.620145 -5.860483,0
  -1.611497,-1.619275 -1.62034,-4.239086 0,-5.854824 l 2.928473,-2.930067
  -0.48823,3.907639 3.42024,-0.977572 -0.98,3.417962 3.90758,-0.488766
  -2.92758,2.925628
PATH

CENTER = 13
SIDE = 3.5
ANCHOR = [1.211941, 8.784891].freeze
CORNER = [CENTER + (SIDE / 2), CENTER - (SIDE / 2)].freeze
SIZE = 26

SVG :minimal, width: SIZE, height: SIZE do
  rect width: SIZE, height: SIZE, rx: 0.75, fill: "#222222"
  defs { path id: "Tulip", d: TULIP, fill: "#e5c39c" }

  4.times do |quarter|
    flower = use href: "#Tulip", x: CORNER[0] - ANCHOR[0], y: CORNER[1] - ANCHOR[1]
    flower.Rotate quarter * 90, CENTER, CENTER
  end

  square x: CENTER - (SIDE / 2), y: CENTER - (SIDE / 2), length: SIDE, fill: "#e5c39c"
end.Save
<svg width="26" height="26">
  <rect width="26" height="26" rx="0.75" fill="white"/>
  <defs>
    <path
      id="Tulip"
      d="m 7.072424,8.784891 c -1.62123,1.620145 -4.24191,1.620145 -5.860483,0
-1.611497,-1.619275 -1.62034,-4.239086 0,-5.854824 l 2.928473,-2.930067
-0.48823,3.907639 3.42024,-0.977572 -0.98,3.417962 3.90758,-0.488766
-2.92758,2.925628
"
      fill="purple"
    />
  </defs>
  <use href="#Tulip" x="13.538059" y="2.465109"/>
  <use href="#Tulip" x="13.538059" y="2.465109" transform="rotate(90, 13, 13)"/>
  <use href="#Tulip" x="13.538059" y="2.465109" transform="rotate(180, 13, 13)"/>
  <use href="#Tulip" x="13.538059" y="2.465109" transform="rotate(270, 13, 13)"/>
  <rect width="3.5" height="3.5" x="11.25" y="11.25" fill="purple"/>
</svg>
<svg width="26" height="26">
  <rect width="26" height="26" rx="0.75" fill="#222222"/>
  <defs>
    <path
      id="Tulip"
      d="m 7.072424,8.784891 c -1.62123,1.620145 -4.24191,1.620145 -5.860483,0
-1.611497,-1.619275 -1.62034,-4.239086 0,-5.854824 l 2.928473,-2.930067
-0.48823,3.907639 3.42024,-0.977572 -0.98,3.417962 3.90758,-0.488766
-2.92758,2.925628
"
      fill="#e5c39c"
    />
  </defs>
  <use href="#Tulip" x="13.538059" y="2.465109"/>
  <use href="#Tulip" x="13.538059" y="2.465109" transform="rotate(90, 13, 13)"/>
  <use href="#Tulip" x="13.538059" y="2.465109" transform="rotate(180, 13, 13)"/>
  <use href="#Tulip" x="13.538059" y="2.465109" transform="rotate(270, 13, 13)"/>
  <rect width="3.5" height="3.5" x="11.25" y="11.25" fill="#e5c39c"/>
</svg>

Tulips

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

SVG :minimal, width: 180, height: 90 do
  rect id: "frame", width: 180, height: 90, rx: 5, fill: "white"

  circle id: "head", cx: 70, cy: 45, r: 40, fill: "purple"
  circle id: "eye", cx: 80, cy: 23, r: 6, fill: "white"
  polygon id: "mouth", points: %w[70,45 110,15 110,75], fill: "white"

  Symbol "dot" do
    circle cx: 110, cy: 45, r: 6, fill: "purple"
  end

  g id: "dots" do
    TileX "dot", n: 3, d: 18
  end
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

SVG :minimal, width: 180, height: 90 do
  rect id: "frame", width: 180, height: 90, rx: 5, fill: "#222222"

  circle id: "head", cx: 70, cy: 45, r: 40, fill: "#e5c39c"
  circle id: "eye", cx: 80, cy: 23, r: 6, fill: "#222222"
  polygon id: "mouth", points: %w[70,45 110,15 110,75], fill: "#222222"

  Symbol "dot" do
    circle cx: 110, cy: 45, r: 6, fill: "#e5c39c"
  end

  g id: "dots" do
    TileX "dot", n: 3, d: 18
  end
end.Save
<svg width="180" height="90">
  <rect id="frame" width="180" height="90" rx="5" fill="white"/>
  <circle id="head" cx="70" cy="45" r="40" fill="purple"/>
  <circle id="eye" cx="80" cy="23" r="6" fill="white"/>
  <polygon id="mouth" points="70,45 110,15 110,75" fill="white"/>
  <symbol id="dot">
    <title>Dot</title>
    <circle cx="110" cy="45" r="6" fill="purple"/>
  </symbol>
  <g id="dots">
    <use id="dot-1" href="#dot" class="tile-col-1 tile-col-first"/>
    <use id="dot-2" href="#dot" class="tile-col-2" x="18"/>
    <use id="dot-3" href="#dot" class="tile-col-3 tile-col-last" x="36"/>
  </g>
</svg>
<svg width="180" height="90">
  <rect id="frame" width="180" height="90" rx="5" fill="#222222"/>
  <circle id="head" cx="70" cy="45" r="40" fill="#e5c39c"/>
  <circle id="eye" cx="80" cy="23" r="6" fill="#222222"/>
  <polygon id="mouth" points="70,45 110,15 110,75" fill="#222222"/>
  <symbol id="dot">
    <title>Dot</title>
    <circle cx="110" cy="45" r="6" fill="#e5c39c"/>
  </symbol>
  <g id="dots">
    <use id="dot-1" href="#dot" class="tile-col-1 tile-col-first"/>
    <use id="dot-2" href="#dot" class="tile-col-2" x="18"/>
    <use id="dot-3" href="#dot" class="tile-col-3 tile-col-last" x="36"/>
  </g>
</svg>

Pacman

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

LED_COUNT = 10
LED_GAP = 2
LED_WIDTH = 10
TOTAL_WIDTH = (LED_COUNT * (LED_WIDTH + LED_GAP)) + 8

dim = proc do |led, x:, **|
  led[:"fill-opacity"] = 0.3 if x >= 7
end

SVG :minimal, width: TOTAL_WIDTH, height: 30, viewBox: "0 0 #{TOTAL_WIDTH} 30" do
  rect x: 2, y: 2, width: TOTAL_WIDTH - 4, height: 26,
       rx: 4, fill: "none", stroke: "#666"

  TileX "led", n: LED_COUNT, d: LED_WIDTH + LED_GAP, o: 5, proc: dim do
    rect y: 5, width: LED_WIDTH, height: 20, rx: 3, fill: "green"
  end
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

LED_COUNT = 10
LED_GAP = 2
LED_WIDTH = 10
TOTAL_WIDTH = (LED_COUNT * (LED_WIDTH + LED_GAP)) + 8

dim = proc do |led, x:, **|
  led[:"fill-opacity"] = 0.3 if x >= 7
end

SVG :minimal, width: TOTAL_WIDTH, height: 30, viewBox: "0 0 #{TOTAL_WIDTH} 30" do
  rect x: 2, y: 2, width: TOTAL_WIDTH - 4, height: 26,
       rx: 4, fill: "none", stroke: "#d8d8d8"

  TileX "led", n: LED_COUNT, d: LED_WIDTH + LED_GAP, o: 5, proc: dim do
    rect y: 5, width: LED_WIDTH, height: 20, rx: 3, fill: "#7bd88f"
  end
end.Save
<svg width="128" height="30" viewBox="0 0 128 30">
  <rect x="2" y="2" width="124" height="26" rx="4" fill="none" stroke="#666"/>
  <defs>
    <g id="led">
      <rect y="5" width="10" height="20" rx="3" fill="green"/>
    </g>
  </defs>
  <use id="led-1" href="#led" class="tile-col-1 tile-col-first" x="5"/>
  <use id="led-2" href="#led" class="tile-col-2" x="17"/>
  <use id="led-3" href="#led" class="tile-col-3" x="29"/>
  <use id="led-4" href="#led" class="tile-col-4" x="41"/>
  <use id="led-5" href="#led" class="tile-col-5" x="53"/>
  <use id="led-6" href="#led" class="tile-col-6" x="65"/>
  <use id="led-7" href="#led" class="tile-col-7" x="77"/>
  <use id="led-8" href="#led" class="tile-col-8" x="89" fill-opacity="0.3"/>
  <use id="led-9" href="#led" class="tile-col-9" x="101" fill-opacity="0.3"/>
  <use id="led-10" href="#led" class="tile-col-10 tile-col-last" x="113" fill-opacity="0.3"/>
</svg>
<svg width="128" height="30" viewBox="0 0 128 30">
  <rect x="2" y="2" width="124" height="26" rx="4" fill="none" stroke="#d8d8d8"/>
  <defs>
    <g id="led">
      <rect y="5" width="10" height="20" rx="3" fill="#7bd88f"/>
    </g>
  </defs>
  <use id="led-1" href="#led" class="tile-col-1 tile-col-first" x="5"/>
  <use id="led-2" href="#led" class="tile-col-2" x="17"/>
  <use id="led-3" href="#led" class="tile-col-3" x="29"/>
  <use id="led-4" href="#led" class="tile-col-4" x="41"/>
  <use id="led-5" href="#led" class="tile-col-5" x="53"/>
  <use id="led-6" href="#led" class="tile-col-6" x="65"/>
  <use id="led-7" href="#led" class="tile-col-7" x="77"/>
  <use id="led-8" href="#led" class="tile-col-8" x="89" fill-opacity="0.3"/>
  <use id="led-9" href="#led" class="tile-col-9" x="101" fill-opacity="0.3"/>
  <use id="led-10" href="#led" class="tile-col-10 tile-col-last" x="113" fill-opacity="0.3"/>
</svg>

Meter

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

HEART = "M10,35 A20,20,0,0,1,50,35 A20,20,0,0,1,90,35 Q90,65,50,95 Q10,65,10,35 Z"

SVG :minimal, width: 120, height: 120, viewBox: "-10 -10 120 120" do
  mask id: "heart",
       maskUnits: "userSpaceOnUse",
       maskContentUnits: "userSpaceOnUse",
       x: 0, y: 0, width: 100, height: 100 do
    square length: 100, fill: "white"
    path d: HEART, fill: "black"
  end

  polygon points: %w[-10,120 120,120 120,-10], fill: "#e5c39c"
  circle cx: 50, cy: 50, r: 50, mask: "url(#heart)", fill: "purple"
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

HEART = "M10,35 A20,20,0,0,1,50,35 A20,20,0,0,1,90,35 Q90,65,50,95 Q10,65,10,35 Z"

SVG :minimal, width: 120, height: 120, viewBox: "-10 -10 120 120" do
  mask id: "heart",
       maskUnits: "userSpaceOnUse",
       maskContentUnits: "userSpaceOnUse",
       x: 0, y: 0, width: 100, height: 100 do
    square length: 100, fill: "white"
    path d: HEART, fill: "black"
  end

  polygon points: %w[-10,120 120,120 120,-10], fill: "#800080"
  circle cx: 50, cy: 50, r: 50, mask: "url(#heart)", fill: "#e5c39c"
end.Save
<svg width="120" height="120" viewBox="-10 -10 120 120">
  <mask id="heart" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" x="0" y="0" width="100" height="100">
    <rect width="100" height="100" fill="white"/>
    <path d="M10,35 A20,20,0,0,1,50,35 A20,20,0,0,1,90,35 Q90,65,50,95 Q10,65,10,35 Z" fill="black"/>
  </mask>
  <polygon points="-10,120 120,120 120,-10" fill="#e5c39c"/>
  <circle cx="50" cy="50" r="50" mask="url(#heart)" fill="purple"/>
</svg>
<svg width="120" height="120" viewBox="-10 -10 120 120">
  <mask id="heart" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" x="0" y="0" width="100" height="100">
    <rect width="100" height="100" fill="white"/>
    <path d="M10,35 A20,20,0,0,1,50,35 A20,20,0,0,1,90,35 Q90,65,50,95 Q10,65,10,35 Z" fill="black"/>
  </mask>
  <polygon points="-10,120 120,120 120,-10" fill="#800080"/>
  <circle cx="50" cy="50" r="50" mask="url(#heart)" fill="#e5c39c"/>
</svg>

Heart

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

STYLE = {
  fill: "purple",
  mask: "url(#hole)",
  stroke: "none"
}.freeze

SVG :minimal, width: 100, height: 100, viewBox: "0 0 100 100" do
  mask id: "hole",
       maskUnits: "userSpaceOnUse",
       maskContentUnits: "userSpaceOnUse",
       x: 0, y: 0, width: 100, height: 100 do
    square length: 100, fill: "white"
    circle cx: 50, cy: 50, r: 15, fill: "black"
  end

  circle cx: 50, cy: 50, r: 30, **STYLE

  [0, 45, 90, 135].each do |angle|
    tooth = rect x: 45, y: 10, width: 10, height: 80, **STYLE
    tooth.Rotate angle, 50, 50
  end
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

STYLE = {
  fill: "#e5c39c",
  mask: "url(#hole)",
  stroke: "none"
}.freeze

SVG :minimal, width: 100, height: 100, viewBox: "0 0 100 100" do
  mask id: "hole",
       maskUnits: "userSpaceOnUse",
       maskContentUnits: "userSpaceOnUse",
       x: 0, y: 0, width: 100, height: 100 do
    square length: 100, fill: "white"
    circle cx: 50, cy: 50, r: 15, fill: "black"
  end

  circle cx: 50, cy: 50, r: 30, **STYLE

  [0, 45, 90, 135].each do |angle|
    tooth = rect x: 45, y: 10, width: 10, height: 80, **STYLE
    tooth.Rotate angle, 50, 50
  end
end.Save
<svg width="100" height="100" viewBox="0 0 100 100">
  <mask id="hole" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" x="0" y="0" width="100" height="100">
    <rect width="100" height="100" fill="white"/>
    <circle cx="50" cy="50" r="15" fill="black"/>
  </mask>
  <circle cx="50" cy="50" r="30" fill="purple" mask="url(#hole)" stroke="none"/>
  <rect x="45" y="10" width="10" height="80" fill="purple" mask="url(#hole)" stroke="none"/>
  <rect x="45" y="10" width="10" height="80" fill="purple" mask="url(#hole)" stroke="none" transform="rotate(45, 50, 50)"/>
  <rect x="45" y="10" width="10" height="80" fill="purple" mask="url(#hole)" stroke="none" transform="rotate(90, 50, 50)"/>
  <rect x="45" y="10" width="10" height="80" fill="purple" mask="url(#hole)" stroke="none" transform="rotate(135, 50, 50)"/>
</svg>
<svg width="100" height="100" viewBox="0 0 100 100">
  <mask id="hole" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse" x="0" y="0" width="100" height="100">
    <rect width="100" height="100" fill="white"/>
    <circle cx="50" cy="50" r="15" fill="black"/>
  </mask>
  <circle cx="50" cy="50" r="30" fill="#e5c39c" mask="url(#hole)" stroke="none"/>
  <rect x="45" y="10" width="10" height="80" fill="#e5c39c" mask="url(#hole)" stroke="none"/>
  <rect x="45" y="10" width="10" height="80" fill="#e5c39c" mask="url(#hole)" stroke="none" transform="rotate(45, 50, 50)"/>
  <rect x="45" y="10" width="10" height="80" fill="#e5c39c" mask="url(#hole)" stroke="none" transform="rotate(90, 50, 50)"/>
  <rect x="45" y="10" width="10" height="80" fill="#e5c39c" mask="url(#hole)" stroke="none" transform="rotate(135, 50, 50)"/>
</svg>

Gear

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

logo = Decompile <<~SVG, id: "Mark"
  <svg xmlns="http://www.w3.org/2000/svg">
    <g id="Mark">
      <path id="Logo" d="m 30,30 c 0,0 18.39,7.089444 18.39,15 C 48.39,52.910556 30,60 30,60 M 30,0 C 30,0 11.61,7.089442 11.61,14.999998 C 11.61,22.910556 30,30 30,30" fill="none"/>
      <use id="SCVN" href="#Logo" class="passive" transform="matrix(-1,0,0,1,60,0)"/>
      <use id="SCVP" href="#Logo" class="active"/>
    </g>
  </svg>
SVG

STYLE = {
  ".active" => {
    fill: "none", stroke: "purple", "stroke-linecap": "round", "stroke-width": 2.0
  },
  ".passive" => {
    fill: "none", stroke: "lightgrey", "stroke-linecap": "round", "stroke-width": 2.0
  }
}.freeze

opacities = [0.8, 0.86, 0.92, 0.97, 1.0].freeze
fade = proc do |tile, x:, y:, **|
  tile[:opacity] = opacities.fetch(x + y)
end

SVG :minimal, width: 260, height: 135, viewBox: "0 0 260 135" do
  css STYLE
  rect width: 260, height: 135, fill: "white"

  defs { logo.evaluate self }
  Tile "Mark", nx: 4, dx: 65, ox: 5, ny: 2, dy: 65, oy: 5, proc: fade
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

logo = Decompile <<~SVG, id: "Mark"
  <svg xmlns="http://www.w3.org/2000/svg">
    <g id="Mark">
      <path id="Logo" d="m 30,30 c 0,0 18.39,7.089444 18.39,15 C 48.39,52.910556 30,60 30,60 M 30,0 C 30,0 11.61,7.089442 11.61,14.999998 C 11.61,22.910556 30,30 30,30" fill="none"/>
      <use id="SCVN" href="#Logo" class="passive" transform="matrix(-1,0,0,1,60,0)"/>
      <use id="SCVP" href="#Logo" class="active"/>
    </g>
  </svg>
SVG

STYLE = {
  ".active" => {
    fill: "none", stroke: "#e5c39c", "stroke-linecap": "round", "stroke-width": 2.0
  },
  ".passive" => {
    fill: "none", stroke: "#52525b", "stroke-linecap": "round", "stroke-width": 2.0
  }
}.freeze

opacities = [0.8, 0.86, 0.92, 0.97, 1.0].freeze
fade = proc do |tile, x:, y:, **|
  tile[:opacity] = opacities.fetch(x + y)
end

SVG :minimal, width: 260, height: 135, viewBox: "0 0 260 135" do
  css STYLE
  rect width: 260, height: 135, fill: "#222222"

  defs { logo.evaluate self }
  Tile "Mark", nx: 4, dx: 65, ox: 5, ny: 2, dy: 65, oy: 5, proc: fade
end.Save
<svg width="260" height="135" viewBox="0 0 260 135">
  <style type="text/css">
    <![CDATA[
      .active {
        fill: none;
        stroke: purple;
        stroke-linecap: round;
        stroke-width: 2.0;
      }
      .passive {
        fill: none;
        stroke: lightgrey;
        stroke-linecap: round;
        stroke-width: 2.0;
      }
    ]]>
  </style>
  <rect width="260" height="135" fill="white"/>
  <defs>
    <g id="Mark" xmlns="http://www.w3.org/2000/svg">
      <path
        id="Logo"
        d="m 30,30 c 0,0 18.39,7.089444 18.39,15 C 48.39,52.910556 30,60 30,60 M 30,0 C 30,0 11.61,7.089442 11.61,14.999998 C 11.61,22.910556 30,30 30,30"
        fill="none"
      />
      <use id="SCVN" href="#Logo" class="passive" transform="matrix(-1,0,0,1,60,0)"/>
      <use id="SCVP" href="#Logo" class="active"/>
    </g>
  </defs>
  <use id="Mark-1-1" href="#Mark" class="tile-row-1 tile-row-first tile-col-1 tile-col-first" x="5" y="5" opacity="0.8"/>
  <use id="Mark-1-2" href="#Mark" class="tile-row-1 tile-row-first tile-col-2" x="70" y="5" opacity="0.86"/>
  <use id="Mark-1-3" href="#Mark" class="tile-row-1 tile-row-first tile-col-3" x="135" y="5" opacity="0.92"/>
  <use id="Mark-1-4" href="#Mark" class="tile-row-1 tile-row-first tile-col-4 tile-col-last" x="200" y="5" opacity="0.97"/>
  <use id="Mark-2-1" href="#Mark" class="tile-row-2 tile-row-last tile-col-1 tile-col-first" x="5" y="70" opacity="0.86"/>
  <use id="Mark-2-2" href="#Mark" class="tile-row-2 tile-row-last tile-col-2" x="70" y="70" opacity="0.92"/>
  <use id="Mark-2-3" href="#Mark" class="tile-row-2 tile-row-last tile-col-3" x="135" y="70" opacity="0.97"/>
  <use id="Mark-2-4" href="#Mark" class="tile-row-2 tile-row-last tile-col-4 tile-col-last" x="200" y="70" opacity="1.0"/>
</svg>
<svg width="260" height="135" viewBox="0 0 260 135">
  <style type="text/css">
    <![CDATA[
      .active {
        fill: none;
        stroke: #e5c39c;
        stroke-linecap: round;
        stroke-width: 2.0;
      }
      .passive {
        fill: none;
        stroke: #52525b;
        stroke-linecap: round;
        stroke-width: 2.0;
      }
    ]]>
  </style>
  <rect width="260" height="135" fill="#222222"/>
  <defs>
    <g id="Mark" xmlns="http://www.w3.org/2000/svg">
      <path
        id="Logo"
        d="m 30,30 c 0,0 18.39,7.089444 18.39,15 C 48.39,52.910556 30,60 30,60 M 30,0 C 30,0 11.61,7.089442 11.61,14.999998 C 11.61,22.910556 30,30 30,30"
        fill="none"
      />
      <use id="SCVN" href="#Logo" class="passive" transform="matrix(-1,0,0,1,60,0)"/>
      <use id="SCVP" href="#Logo" class="active"/>
    </g>
  </defs>
  <use id="Mark-1-1" href="#Mark" class="tile-row-1 tile-row-first tile-col-1 tile-col-first" x="5" y="5" opacity="0.8"/>
  <use id="Mark-1-2" href="#Mark" class="tile-row-1 tile-row-first tile-col-2" x="70" y="5" opacity="0.86"/>
  <use id="Mark-1-3" href="#Mark" class="tile-row-1 tile-row-first tile-col-3" x="135" y="5" opacity="0.92"/>
  <use id="Mark-1-4" href="#Mark" class="tile-row-1 tile-row-first tile-col-4 tile-col-last" x="200" y="5" opacity="0.97"/>
  <use id="Mark-2-1" href="#Mark" class="tile-row-2 tile-row-last tile-col-1 tile-col-first" x="5" y="70" opacity="0.86"/>
  <use id="Mark-2-2" href="#Mark" class="tile-row-2 tile-row-last tile-col-2" x="70" y="70" opacity="0.92"/>
  <use id="Mark-2-3" href="#Mark" class="tile-row-2 tile-row-last tile-col-3" x="135" y="70" opacity="0.97"/>
  <use id="Mark-2-4" href="#Mark" class="tile-row-2 tile-row-last tile-col-4 tile-col-last" x="200" y="70" opacity="1.0"/>
</svg>

Logos

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

module CheckerBoard
  extend SVG::Module

  BOARD_MARGIN = 50
  CELL_SIZE = 100
  PIECE_SIZE = 80
  SIZE = (CELL_SIZE * 8) + (BOARD_MARGIN * 2)

  STYLE = {
    ".board-frame" => { fill: "#d1bfa7", stroke: "#6a3f2b" },
    ".inner-frame" => {
      fill: "#6a3f2b",
      stroke: "#6a3f2b",
      "stroke-width": (BOARD_MARGIN * 0.7).round
    },
    ".cell" => { stroke: "white", "stroke-width": 1 },
    ".light.cell" => { fill: "#d4a76f" },
    ".dark.cell" => { fill: "#6a3f2b" },
    ".piece" => {
      filter: "drop-shadow(8px 8px 8px rgba(0, 0, 0, 0.5))",
      stroke: "none"
    },
    ".light.piece" => { fill: "#f5f5f5" },
    ".dark.piece" => { fill: "#333" }
  }.freeze

  base do # Draw the board.
    css STYLE

    square class: "board-frame", length: SIZE
    square class: "inner-frame", x: BOARD_MARGIN, y: BOARD_MARGIN,
           length: SIZE - (BOARD_MARGIN * 2)

    8.times do |row|
      8.times do |col|
        square class: "#{(row + col).even? ? "dark" : "light"} cell",
               x: (col * CELL_SIZE) + BOARD_MARGIN,
               y: (row * CELL_SIZE) + BOARD_MARGIN,
               length: CELL_SIZE
      end
    end
  end

  def call(placement)
    center = BOARD_MARGIN + (CELL_SIZE / 2)

    placement.each do |tone, rows|
      rows.each do |row, cols|
        cols.each do |col|
          circle class: "#{tone} piece",
                 cx: (col * CELL_SIZE) + center,
                 cy: (row * CELL_SIZE) + center,
                 r: PIECE_SIZE / 2
        end
      end
    end
  end
end

placement = {
  dark: {
    0 => [1, 3, 5, 7],
    1 => [0, 2, 4, 6]
  },
  light: {
    6 => [1, 3, 5, 7],
    7 => [0, 2, 4, 6]
  }
}

SVG :minimal,
    width: CheckerBoard::SIZE,
    height: CheckerBoard::SIZE,
    viewBox: "0 0 #{CheckerBoard::SIZE} #{CheckerBoard::SIZE}" do
  Call CheckerBoard, placement
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

module CheckerBoard
  extend SVG::Module

  BOARD_MARGIN = 50
  CELL_SIZE = 100
  PIECE_SIZE = 80
  SIZE = (CELL_SIZE * 8) + (BOARD_MARGIN * 2)

  STYLE = {
    ".board-frame" => { fill: "#705f4b", stroke: "#d3a778" },
    ".inner-frame" => {
      fill: "#d3a778",
      stroke: "#d3a778",
      "stroke-width": (BOARD_MARGIN * 0.7).round
    },
    ".cell" => { stroke: "white", "stroke-width": 1 },
    ".light.cell" => { fill: "#b88a55" },
    ".dark.cell" => { fill: "#d3a778" },
    ".piece" => {
      filter: "drop-shadow(8px 8px 8px rgba(0, 0, 0, 0.5))",
      stroke: "none"
    },
    ".light.piece" => { fill: "#e8e2dc" },
    ".dark.piece" => { fill: "#161616" }
  }.freeze

  base do # Draw the board.
    css STYLE

    square class: "board-frame", length: SIZE
    square class: "inner-frame", x: BOARD_MARGIN, y: BOARD_MARGIN,
           length: SIZE - (BOARD_MARGIN * 2)

    8.times do |row|
      8.times do |col|
        square class: "#{(row + col).even? ? "dark" : "light"} cell",
               x: (col * CELL_SIZE) + BOARD_MARGIN,
               y: (row * CELL_SIZE) + BOARD_MARGIN,
               length: CELL_SIZE
      end
    end
  end

  def call(placement)
    center = BOARD_MARGIN + (CELL_SIZE / 2)

    placement.each do |tone, rows|
      rows.each do |row, cols|
        cols.each do |col|
          circle class: "#{tone} piece",
                 cx: (col * CELL_SIZE) + center,
                 cy: (row * CELL_SIZE) + center,
                 r: PIECE_SIZE / 2
        end
      end
    end
  end
end

placement = {
  dark: {
    0 => [1, 3, 5, 7],
    1 => [0, 2, 4, 6]
  },
  light: {
    6 => [1, 3, 5, 7],
    7 => [0, 2, 4, 6]
  }
}

SVG :minimal,
    width: CheckerBoard::SIZE,
    height: CheckerBoard::SIZE,
    viewBox: "0 0 #{CheckerBoard::SIZE} #{CheckerBoard::SIZE}" do
  Call CheckerBoard, placement
end.Save
<svg width="900" height="900" viewBox="0 0 900 900">
  <style type="text/css">
    <![CDATA[
      .board-frame {
        fill: #d1bfa7;
        stroke: #6a3f2b;
      }
      .inner-frame {
        fill: #6a3f2b;
        stroke: #6a3f2b;
        stroke-width: 35;
      }
      .cell {
        stroke: white;
        stroke-width: 1;
      }
      .light.cell {
        fill: #d4a76f;
      }
      .dark.cell {
        fill: #6a3f2b;
      }
      .piece {
        filter: drop-shadow(8px 8px 8px rgba(0, 0, 0, 0.5));
        stroke: none;
      }
      .light.piece {
        fill: #f5f5f5;
      }
      .dark.piece {
        fill: #333;
      }
    ]]>
  </style>
  <rect width="900" height="900" class="board-frame"/>
  <rect width="800" height="800" class="inner-frame" x="50" y="50"/>
  <rect width="100" height="100" class="dark cell" x="50" y="50"/>
  <rect width="100" height="100" class="light cell" x="150" y="50"/>
  <rect width="100" height="100" class="dark cell" x="250" y="50"/>
  <rect width="100" height="100" class="light cell" x="350" y="50"/>
  <rect width="100" height="100" class="dark cell" x="450" y="50"/>
  <rect width="100" height="100" class="light cell" x="550" y="50"/>
  <rect width="100" height="100" class="dark cell" x="650" y="50"/>
  <rect width="100" height="100" class="light cell" x="750" y="50"/>
  <rect width="100" height="100" class="light cell" x="50" y="150"/>
  <rect width="100" height="100" class="dark cell" x="150" y="150"/>
  <rect width="100" height="100" class="light cell" x="250" y="150"/>
  <rect width="100" height="100" class="dark cell" x="350" y="150"/>
  <rect width="100" height="100" class="light cell" x="450" y="150"/>
  <rect width="100" height="100" class="dark cell" x="550" y="150"/>
  <rect width="100" height="100" class="light cell" x="650" y="150"/>
  <rect width="100" height="100" class="dark cell" x="750" y="150"/>
  <rect width="100" height="100" class="dark cell" x="50" y="250"/>
  <rect width="100" height="100" class="light cell" x="150" y="250"/>
  <rect width="100" height="100" class="dark cell" x="250" y="250"/>
  <rect width="100" height="100" class="light cell" x="350" y="250"/>
  <rect width="100" height="100" class="dark cell" x="450" y="250"/>
  <rect width="100" height="100" class="light cell" x="550" y="250"/>
  <rect width="100" height="100" class="dark cell" x="650" y="250"/>
  <rect width="100" height="100" class="light cell" x="750" y="250"/>
  <rect width="100" height="100" class="light cell" x="50" y="350"/>
  <rect width="100" height="100" class="dark cell" x="150" y="350"/>
  <rect width="100" height="100" class="light cell" x="250" y="350"/>
  <rect width="100" height="100" class="dark cell" x="350" y="350"/>
  <rect width="100" height="100" class="light cell" x="450" y="350"/>
  <rect width="100" height="100" class="dark cell" x="550" y="350"/>
  <rect width="100" height="100" class="light cell" x="650" y="350"/>
  <rect width="100" height="100" class="dark cell" x="750" y="350"/>
  <rect width="100" height="100" class="dark cell" x="50" y="450"/>
  <rect width="100" height="100" class="light cell" x="150" y="450"/>
  <rect width="100" height="100" class="dark cell" x="250" y="450"/>
  <rect width="100" height="100" class="light cell" x="350" y="450"/>
  <rect width="100" height="100" class="dark cell" x="450" y="450"/>
  <rect width="100" height="100" class="light cell" x="550" y="450"/>
  <rect width="100" height="100" class="dark cell" x="650" y="450"/>
  <rect width="100" height="100" class="light cell" x="750" y="450"/>
  <rect width="100" height="100" class="light cell" x="50" y="550"/>
  <rect width="100" height="100" class="dark cell" x="150" y="550"/>
  <rect width="100" height="100" class="light cell" x="250" y="550"/>
  <rect width="100" height="100" class="dark cell" x="350" y="550"/>
  <rect width="100" height="100" class="light cell" x="450" y="550"/>
  <rect width="100" height="100" class="dark cell" x="550" y="550"/>
  <rect width="100" height="100" class="light cell" x="650" y="550"/>
  <rect width="100" height="100" class="dark cell" x="750" y="550"/>
  <rect width="100" height="100" class="dark cell" x="50" y="650"/>
  <rect width="100" height="100" class="light cell" x="150" y="650"/>
  <rect width="100" height="100" class="dark cell" x="250" y="650"/>
  <rect width="100" height="100" class="light cell" x="350" y="650"/>
  <rect width="100" height="100" class="dark cell" x="450" y="650"/>
  <rect width="100" height="100" class="light cell" x="550" y="650"/>
  <rect width="100" height="100" class="dark cell" x="650" y="650"/>
  <rect width="100" height="100" class="light cell" x="750" y="650"/>
  <rect width="100" height="100" class="light cell" x="50" y="750"/>
  <rect width="100" height="100" class="dark cell" x="150" y="750"/>
  <rect width="100" height="100" class="light cell" x="250" y="750"/>
  <rect width="100" height="100" class="dark cell" x="350" y="750"/>
  <rect width="100" height="100" class="light cell" x="450" y="750"/>
  <rect width="100" height="100" class="dark cell" x="550" y="750"/>
  <rect width="100" height="100" class="light cell" x="650" y="750"/>
  <rect width="100" height="100" class="dark cell" x="750" y="750"/>
  <circle class="dark piece" cx="200" cy="100" r="40"/>
  <circle class="dark piece" cx="400" cy="100" r="40"/>
  <circle class="dark piece" cx="600" cy="100" r="40"/>
  <circle class="dark piece" cx="800" cy="100" r="40"/>
  <circle class="dark piece" cx="100" cy="200" r="40"/>
  <circle class="dark piece" cx="300" cy="200" r="40"/>
  <circle class="dark piece" cx="500" cy="200" r="40"/>
  <circle class="dark piece" cx="700" cy="200" r="40"/>
  <circle class="light piece" cx="200" cy="700" r="40"/>
  <circle class="light piece" cx="400" cy="700" r="40"/>
  <circle class="light piece" cx="600" cy="700" r="40"/>
  <circle class="light piece" cx="800" cy="700" r="40"/>
  <circle class="light piece" cx="100" cy="800" r="40"/>
  <circle class="light piece" cx="300" cy="800" r="40"/>
  <circle class="light piece" cx="500" cy="800" r="40"/>
  <circle class="light piece" cx="700" cy="800" r="40"/>
</svg>
<svg width="900" height="900" viewBox="0 0 900 900">
  <style type="text/css">
    <![CDATA[
      .board-frame {
        fill: #705f4b;
        stroke: #d3a778;
      }
      .inner-frame {
        fill: #d3a778;
        stroke: #d3a778;
        stroke-width: 35;
      }
      .cell {
        stroke: white;
        stroke-width: 1;
      }
      .light.cell {
        fill: #b88a55;
      }
      .dark.cell {
        fill: #d3a778;
      }
      .piece {
        filter: drop-shadow(8px 8px 8px rgba(0, 0, 0, 0.5));
        stroke: none;
      }
      .light.piece {
        fill: #e8e2dc;
      }
      .dark.piece {
        fill: #161616;
      }
    ]]>
  </style>
  <rect width="900" height="900" class="board-frame"/>
  <rect width="800" height="800" class="inner-frame" x="50" y="50"/>
  <rect width="100" height="100" class="dark cell" x="50" y="50"/>
  <rect width="100" height="100" class="light cell" x="150" y="50"/>
  <rect width="100" height="100" class="dark cell" x="250" y="50"/>
  <rect width="100" height="100" class="light cell" x="350" y="50"/>
  <rect width="100" height="100" class="dark cell" x="450" y="50"/>
  <rect width="100" height="100" class="light cell" x="550" y="50"/>
  <rect width="100" height="100" class="dark cell" x="650" y="50"/>
  <rect width="100" height="100" class="light cell" x="750" y="50"/>
  <rect width="100" height="100" class="light cell" x="50" y="150"/>
  <rect width="100" height="100" class="dark cell" x="150" y="150"/>
  <rect width="100" height="100" class="light cell" x="250" y="150"/>
  <rect width="100" height="100" class="dark cell" x="350" y="150"/>
  <rect width="100" height="100" class="light cell" x="450" y="150"/>
  <rect width="100" height="100" class="dark cell" x="550" y="150"/>
  <rect width="100" height="100" class="light cell" x="650" y="150"/>
  <rect width="100" height="100" class="dark cell" x="750" y="150"/>
  <rect width="100" height="100" class="dark cell" x="50" y="250"/>
  <rect width="100" height="100" class="light cell" x="150" y="250"/>
  <rect width="100" height="100" class="dark cell" x="250" y="250"/>
  <rect width="100" height="100" class="light cell" x="350" y="250"/>
  <rect width="100" height="100" class="dark cell" x="450" y="250"/>
  <rect width="100" height="100" class="light cell" x="550" y="250"/>
  <rect width="100" height="100" class="dark cell" x="650" y="250"/>
  <rect width="100" height="100" class="light cell" x="750" y="250"/>
  <rect width="100" height="100" class="light cell" x="50" y="350"/>
  <rect width="100" height="100" class="dark cell" x="150" y="350"/>
  <rect width="100" height="100" class="light cell" x="250" y="350"/>
  <rect width="100" height="100" class="dark cell" x="350" y="350"/>
  <rect width="100" height="100" class="light cell" x="450" y="350"/>
  <rect width="100" height="100" class="dark cell" x="550" y="350"/>
  <rect width="100" height="100" class="light cell" x="650" y="350"/>
  <rect width="100" height="100" class="dark cell" x="750" y="350"/>
  <rect width="100" height="100" class="dark cell" x="50" y="450"/>
  <rect width="100" height="100" class="light cell" x="150" y="450"/>
  <rect width="100" height="100" class="dark cell" x="250" y="450"/>
  <rect width="100" height="100" class="light cell" x="350" y="450"/>
  <rect width="100" height="100" class="dark cell" x="450" y="450"/>
  <rect width="100" height="100" class="light cell" x="550" y="450"/>
  <rect width="100" height="100" class="dark cell" x="650" y="450"/>
  <rect width="100" height="100" class="light cell" x="750" y="450"/>
  <rect width="100" height="100" class="light cell" x="50" y="550"/>
  <rect width="100" height="100" class="dark cell" x="150" y="550"/>
  <rect width="100" height="100" class="light cell" x="250" y="550"/>
  <rect width="100" height="100" class="dark cell" x="350" y="550"/>
  <rect width="100" height="100" class="light cell" x="450" y="550"/>
  <rect width="100" height="100" class="dark cell" x="550" y="550"/>
  <rect width="100" height="100" class="light cell" x="650" y="550"/>
  <rect width="100" height="100" class="dark cell" x="750" y="550"/>
  <rect width="100" height="100" class="dark cell" x="50" y="650"/>
  <rect width="100" height="100" class="light cell" x="150" y="650"/>
  <rect width="100" height="100" class="dark cell" x="250" y="650"/>
  <rect width="100" height="100" class="light cell" x="350" y="650"/>
  <rect width="100" height="100" class="dark cell" x="450" y="650"/>
  <rect width="100" height="100" class="light cell" x="550" y="650"/>
  <rect width="100" height="100" class="dark cell" x="650" y="650"/>
  <rect width="100" height="100" class="light cell" x="750" y="650"/>
  <rect width="100" height="100" class="light cell" x="50" y="750"/>
  <rect width="100" height="100" class="dark cell" x="150" y="750"/>
  <rect width="100" height="100" class="light cell" x="250" y="750"/>
  <rect width="100" height="100" class="dark cell" x="350" y="750"/>
  <rect width="100" height="100" class="light cell" x="450" y="750"/>
  <rect width="100" height="100" class="dark cell" x="550" y="750"/>
  <rect width="100" height="100" class="light cell" x="650" y="750"/>
  <rect width="100" height="100" class="dark cell" x="750" y="750"/>
  <circle class="dark piece" cx="200" cy="100" r="40"/>
  <circle class="dark piece" cx="400" cy="100" r="40"/>
  <circle class="dark piece" cx="600" cy="100" r="40"/>
  <circle class="dark piece" cx="800" cy="100" r="40"/>
  <circle class="dark piece" cx="100" cy="200" r="40"/>
  <circle class="dark piece" cx="300" cy="200" r="40"/>
  <circle class="dark piece" cx="500" cy="200" r="40"/>
  <circle class="dark piece" cx="700" cy="200" r="40"/>
  <circle class="light piece" cx="200" cy="700" r="40"/>
  <circle class="light piece" cx="400" cy="700" r="40"/>
  <circle class="light piece" cx="600" cy="700" r="40"/>
  <circle class="light piece" cx="800" cy="700" r="40"/>
  <circle class="light piece" cx="100" cy="800" r="40"/>
  <circle class="light piece" cx="300" cy="800" r="40"/>
  <circle class="light piece" cx="500" cy="800" r="40"/>
  <circle class="light piece" cx="700" cy="800" r="40"/>
</svg>

Checkers

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

WIDTH = 150 # 15 cm width (ruler's length)
HEIGHT = 20 # 2 cm height
PAGE_WIDTH = 170
PAGE_HEIGHT = 30

STYLE = {
  ".labels" => { fill: "black", font: "3pt monospace" },
  ".majors" => { stroke: "black", "stroke-width": 0.3 },
  ".halves" => { stroke: "black", "stroke-width": 0.15 },
  ".minors" => { stroke: "black", "stroke-width": 0.15 },
  ".frame" => { stroke: "black", "stroke-width": 0.15, fill: "none" }
}.freeze

SVG width: "#{PAGE_WIDTH}mm", height: "#{PAGE_HEIGHT}mm",
    viewBox: "0 0 #{PAGE_WIDTH} #{PAGE_HEIGHT}" do
  css STYLE

  ruler = g id: "ruler" do
    rect id: "frame", width: WIDTH, height: HEIGHT, class: "frame"

    layer id: "minors" do
      length = 2

      (0..WIDTH).step(1) do |x|
        VLineBy x:, y: 0, length:, class: "minors"
        VLineBy x:, y: HEIGHT, length: -length, class: "minors"
      end
    end

    layer id: "halves" do
      length = 4

      (0..WIDTH).step(5) do |x|
        VLineBy x:, y: 0, length:, class: "halves"
        VLineBy x:, y: HEIGHT, length: -length, class: "halves"
      end
    end

    layer id: "majors" do
      length = 6

      (10..(WIDTH - 10)).step(10) do |x|
        VLineBy x:, y: 0, length:, class: "majors"
        VLineBy x:, y: HEIGHT, length: -length, class: "majors"
      end

      layer id: "labels" do
        (10..(WIDTH - 10)).step(10).each_with_index do |x, i|
          text (i + 1).to_s, "text-anchor": "middle", x:, y: length + 5.5, class: "labels"
        end
      end
    end
  end

  offset_x = (PAGE_WIDTH - WIDTH) / 2
  offset_y = (PAGE_HEIGHT - HEIGHT) / 2
  ruler.Translate offset_x, offset_y
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

WIDTH = 150 # 15 cm width (ruler's length)
HEIGHT = 20 # 2 cm height
PAGE_WIDTH = 170
PAGE_HEIGHT = 30

STYLE = {
  ".labels" => { fill: "white", font: "3pt monospace" },
  ".majors" => { stroke: "white", "stroke-width": 0.3 },
  ".halves" => { stroke: "white", "stroke-width": 0.15 },
  ".minors" => { stroke: "white", "stroke-width": 0.15 },
  ".frame" => { stroke: "white", "stroke-width": 0.15, fill: "none" }
}.freeze

SVG width: "#{PAGE_WIDTH}mm", height: "#{PAGE_HEIGHT}mm",
    viewBox: "0 0 #{PAGE_WIDTH} #{PAGE_HEIGHT}" do
  css STYLE

  ruler = g id: "ruler" do
    rect id: "frame", width: WIDTH, height: HEIGHT, class: "frame"

    layer id: "minors" do
      length = 2

      (0..WIDTH).step(1) do |x|
        VLineBy x:, y: 0, length:, class: "minors"
        VLineBy x:, y: HEIGHT, length: -length, class: "minors"
      end
    end

    layer id: "halves" do
      length = 4

      (0..WIDTH).step(5) do |x|
        VLineBy x:, y: 0, length:, class: "halves"
        VLineBy x:, y: HEIGHT, length: -length, class: "halves"
      end
    end

    layer id: "majors" do
      length = 6

      (10..(WIDTH - 10)).step(10) do |x|
        VLineBy x:, y: 0, length:, class: "majors"
        VLineBy x:, y: HEIGHT, length: -length, class: "majors"
      end

      layer id: "labels" do
        (10..(WIDTH - 10)).step(10).each_with_index do |x, i|
          text (i + 1).to_s, "text-anchor": "middle", x:, y: length + 5.5, class: "labels"
        end
      end
    end
  end

  offset_x = (PAGE_WIDTH - WIDTH) / 2
  offset_y = (PAGE_HEIGHT - HEIGHT) / 2
  ruler.Translate offset_x, offset_y
end.Save
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="170mm" height="30mm" viewBox="0 0 170 30">
  <style type="text/css">
    <![CDATA[
      .labels {
        fill: black;
        font: 3pt monospace;
      }
      .majors {
        stroke: black;
        stroke-width: 0.3;
      }
      .halves {
        stroke: black;
        stroke-width: 0.15;
      }
      .minors {
        stroke: black;
        stroke-width: 0.15;
      }
      .frame {
        stroke: black;
        stroke-width: 0.15;
        fill: none;
      }
    ]]>
  </style>
  <g id="ruler" transform="translate(10 5)">
    <rect id="frame" width="150" height="20" class="frame"/>
    <g id="minors">
      <path d="M 0 0 v 2" class="minors"/>
      <path d="M 0 20 v -2" class="minors"/>
      <path d="M 1 0 v 2" class="minors"/>
      <path d="M 1 20 v -2" class="minors"/>
      <path d="M 2 0 v 2" class="minors"/>
      <path d="M 2 20 v -2" class="minors"/>
      <path d="M 3 0 v 2" class="minors"/>
      <path d="M 3 20 v -2" class="minors"/>
      <path d="M 4 0 v 2" class="minors"/>
      <path d="M 4 20 v -2" class="minors"/>
      <path d="M 5 0 v 2" class="minors"/>
      <path d="M 5 20 v -2" class="minors"/>
      <path d="M 6 0 v 2" class="minors"/>
      <path d="M 6 20 v -2" class="minors"/>
      <path d="M 7 0 v 2" class="minors"/>
      <path d="M 7 20 v -2" class="minors"/>
      <path d="M 8 0 v 2" class="minors"/>
      <path d="M 8 20 v -2" class="minors"/>
      <path d="M 9 0 v 2" class="minors"/>
      <path d="M 9 20 v -2" class="minors"/>
      <path d="M 10 0 v 2" class="minors"/>
      <path d="M 10 20 v -2" class="minors"/>
      <path d="M 11 0 v 2" class="minors"/>
      <path d="M 11 20 v -2" class="minors"/>
      <path d="M 12 0 v 2" class="minors"/>
      <path d="M 12 20 v -2" class="minors"/>
      <path d="M 13 0 v 2" class="minors"/>
      <path d="M 13 20 v -2" class="minors"/>
      <path d="M 14 0 v 2" class="minors"/>
      <path d="M 14 20 v -2" class="minors"/>
      <path d="M 15 0 v 2" class="minors"/>
      <path d="M 15 20 v -2" class="minors"/>
      <path d="M 16 0 v 2" class="minors"/>
      <path d="M 16 20 v -2" class="minors"/>
      <path d="M 17 0 v 2" class="minors"/>
      <path d="M 17 20 v -2" class="minors"/>
      <path d="M 18 0 v 2" class="minors"/>
      <path d="M 18 20 v -2" class="minors"/>
      <path d="M 19 0 v 2" class="minors"/>
      <path d="M 19 20 v -2" class="minors"/>
      <path d="M 20 0 v 2" class="minors"/>
      <path d="M 20 20 v -2" class="minors"/>
      <path d="M 21 0 v 2" class="minors"/>
      <path d="M 21 20 v -2" class="minors"/>
      <path d="M 22 0 v 2" class="minors"/>
      <path d="M 22 20 v -2" class="minors"/>
      <path d="M 23 0 v 2" class="minors"/>
      <path d="M 23 20 v -2" class="minors"/>
      <path d="M 24 0 v 2" class="minors"/>
      <path d="M 24 20 v -2" class="minors"/>
      <path d="M 25 0 v 2" class="minors"/>
      <path d="M 25 20 v -2" class="minors"/>
      <path d="M 26 0 v 2" class="minors"/>
      <path d="M 26 20 v -2" class="minors"/>
      <path d="M 27 0 v 2" class="minors"/>
      <path d="M 27 20 v -2" class="minors"/>
      <path d="M 28 0 v 2" class="minors"/>
      <path d="M 28 20 v -2" class="minors"/>
      <path d="M 29 0 v 2" class="minors"/>
      <path d="M 29 20 v -2" class="minors"/>
      <path d="M 30 0 v 2" class="minors"/>
      <path d="M 30 20 v -2" class="minors"/>
      <path d="M 31 0 v 2" class="minors"/>
      <path d="M 31 20 v -2" class="minors"/>
      <path d="M 32 0 v 2" class="minors"/>
      <path d="M 32 20 v -2" class="minors"/>
      <path d="M 33 0 v 2" class="minors"/>
      <path d="M 33 20 v -2" class="minors"/>
      <path d="M 34 0 v 2" class="minors"/>
      <path d="M 34 20 v -2" class="minors"/>
      <path d="M 35 0 v 2" class="minors"/>
      <path d="M 35 20 v -2" class="minors"/>
      <path d="M 36 0 v 2" class="minors"/>
      <path d="M 36 20 v -2" class="minors"/>
      <path d="M 37 0 v 2" class="minors"/>
      <path d="M 37 20 v -2" class="minors"/>
      <path d="M 38 0 v 2" class="minors"/>
      <path d="M 38 20 v -2" class="minors"/>
      <path d="M 39 0 v 2" class="minors"/>
      <path d="M 39 20 v -2" class="minors"/>
      <path d="M 40 0 v 2" class="minors"/>
      <path d="M 40 20 v -2" class="minors"/>
      <path d="M 41 0 v 2" class="minors"/>
      <path d="M 41 20 v -2" class="minors"/>
      <path d="M 42 0 v 2" class="minors"/>
      <path d="M 42 20 v -2" class="minors"/>
      <path d="M 43 0 v 2" class="minors"/>
      <path d="M 43 20 v -2" class="minors"/>
      <path d="M 44 0 v 2" class="minors"/>
      <path d="M 44 20 v -2" class="minors"/>
      <path d="M 45 0 v 2" class="minors"/>
      <path d="M 45 20 v -2" class="minors"/>
      <path d="M 46 0 v 2" class="minors"/>
      <path d="M 46 20 v -2" class="minors"/>
      <path d="M 47 0 v 2" class="minors"/>
      <path d="M 47 20 v -2" class="minors"/>
      <path d="M 48 0 v 2" class="minors"/>
      <path d="M 48 20 v -2" class="minors"/>
      <path d="M 49 0 v 2" class="minors"/>
      <path d="M 49 20 v -2" class="minors"/>
      <path d="M 50 0 v 2" class="minors"/>
      <path d="M 50 20 v -2" class="minors"/>
      <path d="M 51 0 v 2" class="minors"/>
      <path d="M 51 20 v -2" class="minors"/>
      <path d="M 52 0 v 2" class="minors"/>
      <path d="M 52 20 v -2" class="minors"/>
      <path d="M 53 0 v 2" class="minors"/>
      <path d="M 53 20 v -2" class="minors"/>
      <path d="M 54 0 v 2" class="minors"/>
      <path d="M 54 20 v -2" class="minors"/>
      <path d="M 55 0 v 2" class="minors"/>
      <path d="M 55 20 v -2" class="minors"/>
      <path d="M 56 0 v 2" class="minors"/>
      <path d="M 56 20 v -2" class="minors"/>
      <path d="M 57 0 v 2" class="minors"/>
      <path d="M 57 20 v -2" class="minors"/>
      <path d="M 58 0 v 2" class="minors"/>
      <path d="M 58 20 v -2" class="minors"/>
      <path d="M 59 0 v 2" class="minors"/>
      <path d="M 59 20 v -2" class="minors"/>
      <path d="M 60 0 v 2" class="minors"/>
      <path d="M 60 20 v -2" class="minors"/>
      <path d="M 61 0 v 2" class="minors"/>
      <path d="M 61 20 v -2" class="minors"/>
      <path d="M 62 0 v 2" class="minors"/>
      <path d="M 62 20 v -2" class="minors"/>
      <path d="M 63 0 v 2" class="minors"/>
      <path d="M 63 20 v -2" class="minors"/>
      <path d="M 64 0 v 2" class="minors"/>
      <path d="M 64 20 v -2" class="minors"/>
      <path d="M 65 0 v 2" class="minors"/>
      <path d="M 65 20 v -2" class="minors"/>
      <path d="M 66 0 v 2" class="minors"/>
      <path d="M 66 20 v -2" class="minors"/>
      <path d="M 67 0 v 2" class="minors"/>
      <path d="M 67 20 v -2" class="minors"/>
      <path d="M 68 0 v 2" class="minors"/>
      <path d="M 68 20 v -2" class="minors"/>
      <path d="M 69 0 v 2" class="minors"/>
      <path d="M 69 20 v -2" class="minors"/>
      <path d="M 70 0 v 2" class="minors"/>
      <path d="M 70 20 v -2" class="minors"/>
      <path d="M 71 0 v 2" class="minors"/>
      <path d="M 71 20 v -2" class="minors"/>
      <path d="M 72 0 v 2" class="minors"/>
      <path d="M 72 20 v -2" class="minors"/>
      <path d="M 73 0 v 2" class="minors"/>
      <path d="M 73 20 v -2" class="minors"/>
      <path d="M 74 0 v 2" class="minors"/>
      <path d="M 74 20 v -2" class="minors"/>
      <path d="M 75 0 v 2" class="minors"/>
      <path d="M 75 20 v -2" class="minors"/>
      <path d="M 76 0 v 2" class="minors"/>
      <path d="M 76 20 v -2" class="minors"/>
      <path d="M 77 0 v 2" class="minors"/>
      <path d="M 77 20 v -2" class="minors"/>
      <path d="M 78 0 v 2" class="minors"/>
      <path d="M 78 20 v -2" class="minors"/>
      <path d="M 79 0 v 2" class="minors"/>
      <path d="M 79 20 v -2" class="minors"/>
      <path d="M 80 0 v 2" class="minors"/>
      <path d="M 80 20 v -2" class="minors"/>
      <path d="M 81 0 v 2" class="minors"/>
      <path d="M 81 20 v -2" class="minors"/>
      <path d="M 82 0 v 2" class="minors"/>
      <path d="M 82 20 v -2" class="minors"/>
      <path d="M 83 0 v 2" class="minors"/>
      <path d="M 83 20 v -2" class="minors"/>
      <path d="M 84 0 v 2" class="minors"/>
      <path d="M 84 20 v -2" class="minors"/>
      <path d="M 85 0 v 2" class="minors"/>
      <path d="M 85 20 v -2" class="minors"/>
      <path d="M 86 0 v 2" class="minors"/>
      <path d="M 86 20 v -2" class="minors"/>
      <path d="M 87 0 v 2" class="minors"/>
      <path d="M 87 20 v -2" class="minors"/>
      <path d="M 88 0 v 2" class="minors"/>
      <path d="M 88 20 v -2" class="minors"/>
      <path d="M 89 0 v 2" class="minors"/>
      <path d="M 89 20 v -2" class="minors"/>
      <path d="M 90 0 v 2" class="minors"/>
      <path d="M 90 20 v -2" class="minors"/>
      <path d="M 91 0 v 2" class="minors"/>
      <path d="M 91 20 v -2" class="minors"/>
      <path d="M 92 0 v 2" class="minors"/>
      <path d="M 92 20 v -2" class="minors"/>
      <path d="M 93 0 v 2" class="minors"/>
      <path d="M 93 20 v -2" class="minors"/>
      <path d="M 94 0 v 2" class="minors"/>
      <path d="M 94 20 v -2" class="minors"/>
      <path d="M 95 0 v 2" class="minors"/>
      <path d="M 95 20 v -2" class="minors"/>
      <path d="M 96 0 v 2" class="minors"/>
      <path d="M 96 20 v -2" class="minors"/>
      <path d="M 97 0 v 2" class="minors"/>
      <path d="M 97 20 v -2" class="minors"/>
      <path d="M 98 0 v 2" class="minors"/>
      <path d="M 98 20 v -2" class="minors"/>
      <path d="M 99 0 v 2" class="minors"/>
      <path d="M 99 20 v -2" class="minors"/>
      <path d="M 100 0 v 2" class="minors"/>
      <path d="M 100 20 v -2" class="minors"/>
      <path d="M 101 0 v 2" class="minors"/>
      <path d="M 101 20 v -2" class="minors"/>
      <path d="M 102 0 v 2" class="minors"/>
      <path d="M 102 20 v -2" class="minors"/>
      <path d="M 103 0 v 2" class="minors"/>
      <path d="M 103 20 v -2" class="minors"/>
      <path d="M 104 0 v 2" class="minors"/>
      <path d="M 104 20 v -2" class="minors"/>
      <path d="M 105 0 v 2" class="minors"/>
      <path d="M 105 20 v -2" class="minors"/>
      <path d="M 106 0 v 2" class="minors"/>
      <path d="M 106 20 v -2" class="minors"/>
      <path d="M 107 0 v 2" class="minors"/>
      <path d="M 107 20 v -2" class="minors"/>
      <path d="M 108 0 v 2" class="minors"/>
      <path d="M 108 20 v -2" class="minors"/>
      <path d="M 109 0 v 2" class="minors"/>
      <path d="M 109 20 v -2" class="minors"/>
      <path d="M 110 0 v 2" class="minors"/>
      <path d="M 110 20 v -2" class="minors"/>
      <path d="M 111 0 v 2" class="minors"/>
      <path d="M 111 20 v -2" class="minors"/>
      <path d="M 112 0 v 2" class="minors"/>
      <path d="M 112 20 v -2" class="minors"/>
      <path d="M 113 0 v 2" class="minors"/>
      <path d="M 113 20 v -2" class="minors"/>
      <path d="M 114 0 v 2" class="minors"/>
      <path d="M 114 20 v -2" class="minors"/>
      <path d="M 115 0 v 2" class="minors"/>
      <path d="M 115 20 v -2" class="minors"/>
      <path d="M 116 0 v 2" class="minors"/>
      <path d="M 116 20 v -2" class="minors"/>
      <path d="M 117 0 v 2" class="minors"/>
      <path d="M 117 20 v -2" class="minors"/>
      <path d="M 118 0 v 2" class="minors"/>
      <path d="M 118 20 v -2" class="minors"/>
      <path d="M 119 0 v 2" class="minors"/>
      <path d="M 119 20 v -2" class="minors"/>
      <path d="M 120 0 v 2" class="minors"/>
      <path d="M 120 20 v -2" class="minors"/>
      <path d="M 121 0 v 2" class="minors"/>
      <path d="M 121 20 v -2" class="minors"/>
      <path d="M 122 0 v 2" class="minors"/>
      <path d="M 122 20 v -2" class="minors"/>
      <path d="M 123 0 v 2" class="minors"/>
      <path d="M 123 20 v -2" class="minors"/>
      <path d="M 124 0 v 2" class="minors"/>
      <path d="M 124 20 v -2" class="minors"/>
      <path d="M 125 0 v 2" class="minors"/>
      <path d="M 125 20 v -2" class="minors"/>
      <path d="M 126 0 v 2" class="minors"/>
      <path d="M 126 20 v -2" class="minors"/>
      <path d="M 127 0 v 2" class="minors"/>
      <path d="M 127 20 v -2" class="minors"/>
      <path d="M 128 0 v 2" class="minors"/>
      <path d="M 128 20 v -2" class="minors"/>
      <path d="M 129 0 v 2" class="minors"/>
      <path d="M 129 20 v -2" class="minors"/>
      <path d="M 130 0 v 2" class="minors"/>
      <path d="M 130 20 v -2" class="minors"/>
      <path d="M 131 0 v 2" class="minors"/>
      <path d="M 131 20 v -2" class="minors"/>
      <path d="M 132 0 v 2" class="minors"/>
      <path d="M 132 20 v -2" class="minors"/>
      <path d="M 133 0 v 2" class="minors"/>
      <path d="M 133 20 v -2" class="minors"/>
      <path d="M 134 0 v 2" class="minors"/>
      <path d="M 134 20 v -2" class="minors"/>
      <path d="M 135 0 v 2" class="minors"/>
      <path d="M 135 20 v -2" class="minors"/>
      <path d="M 136 0 v 2" class="minors"/>
      <path d="M 136 20 v -2" class="minors"/>
      <path d="M 137 0 v 2" class="minors"/>
      <path d="M 137 20 v -2" class="minors"/>
      <path d="M 138 0 v 2" class="minors"/>
      <path d="M 138 20 v -2" class="minors"/>
      <path d="M 139 0 v 2" class="minors"/>
      <path d="M 139 20 v -2" class="minors"/>
      <path d="M 140 0 v 2" class="minors"/>
      <path d="M 140 20 v -2" class="minors"/>
      <path d="M 141 0 v 2" class="minors"/>
      <path d="M 141 20 v -2" class="minors"/>
      <path d="M 142 0 v 2" class="minors"/>
      <path d="M 142 20 v -2" class="minors"/>
      <path d="M 143 0 v 2" class="minors"/>
      <path d="M 143 20 v -2" class="minors"/>
      <path d="M 144 0 v 2" class="minors"/>
      <path d="M 144 20 v -2" class="minors"/>
      <path d="M 145 0 v 2" class="minors"/>
      <path d="M 145 20 v -2" class="minors"/>
      <path d="M 146 0 v 2" class="minors"/>
      <path d="M 146 20 v -2" class="minors"/>
      <path d="M 147 0 v 2" class="minors"/>
      <path d="M 147 20 v -2" class="minors"/>
      <path d="M 148 0 v 2" class="minors"/>
      <path d="M 148 20 v -2" class="minors"/>
      <path d="M 149 0 v 2" class="minors"/>
      <path d="M 149 20 v -2" class="minors"/>
      <path d="M 150 0 v 2" class="minors"/>
      <path d="M 150 20 v -2" class="minors"/>
    </g>
    <g id="halves">
      <path d="M 0 0 v 4" class="halves"/>
      <path d="M 0 20 v -4" class="halves"/>
      <path d="M 5 0 v 4" class="halves"/>
      <path d="M 5 20 v -4" class="halves"/>
      <path d="M 10 0 v 4" class="halves"/>
      <path d="M 10 20 v -4" class="halves"/>
      <path d="M 15 0 v 4" class="halves"/>
      <path d="M 15 20 v -4" class="halves"/>
      <path d="M 20 0 v 4" class="halves"/>
      <path d="M 20 20 v -4" class="halves"/>
      <path d="M 25 0 v 4" class="halves"/>
      <path d="M 25 20 v -4" class="halves"/>
      <path d="M 30 0 v 4" class="halves"/>
      <path d="M 30 20 v -4" class="halves"/>
      <path d="M 35 0 v 4" class="halves"/>
      <path d="M 35 20 v -4" class="halves"/>
      <path d="M 40 0 v 4" class="halves"/>
      <path d="M 40 20 v -4" class="halves"/>
      <path d="M 45 0 v 4" class="halves"/>
      <path d="M 45 20 v -4" class="halves"/>
      <path d="M 50 0 v 4" class="halves"/>
      <path d="M 50 20 v -4" class="halves"/>
      <path d="M 55 0 v 4" class="halves"/>
      <path d="M 55 20 v -4" class="halves"/>
      <path d="M 60 0 v 4" class="halves"/>
      <path d="M 60 20 v -4" class="halves"/>
      <path d="M 65 0 v 4" class="halves"/>
      <path d="M 65 20 v -4" class="halves"/>
      <path d="M 70 0 v 4" class="halves"/>
      <path d="M 70 20 v -4" class="halves"/>
      <path d="M 75 0 v 4" class="halves"/>
      <path d="M 75 20 v -4" class="halves"/>
      <path d="M 80 0 v 4" class="halves"/>
      <path d="M 80 20 v -4" class="halves"/>
      <path d="M 85 0 v 4" class="halves"/>
      <path d="M 85 20 v -4" class="halves"/>
      <path d="M 90 0 v 4" class="halves"/>
      <path d="M 90 20 v -4" class="halves"/>
      <path d="M 95 0 v 4" class="halves"/>
      <path d="M 95 20 v -4" class="halves"/>
      <path d="M 100 0 v 4" class="halves"/>
      <path d="M 100 20 v -4" class="halves"/>
      <path d="M 105 0 v 4" class="halves"/>
      <path d="M 105 20 v -4" class="halves"/>
      <path d="M 110 0 v 4" class="halves"/>
      <path d="M 110 20 v -4" class="halves"/>
      <path d="M 115 0 v 4" class="halves"/>
      <path d="M 115 20 v -4" class="halves"/>
      <path d="M 120 0 v 4" class="halves"/>
      <path d="M 120 20 v -4" class="halves"/>
      <path d="M 125 0 v 4" class="halves"/>
      <path d="M 125 20 v -4" class="halves"/>
      <path d="M 130 0 v 4" class="halves"/>
      <path d="M 130 20 v -4" class="halves"/>
      <path d="M 135 0 v 4" class="halves"/>
      <path d="M 135 20 v -4" class="halves"/>
      <path d="M 140 0 v 4" class="halves"/>
      <path d="M 140 20 v -4" class="halves"/>
      <path d="M 145 0 v 4" class="halves"/>
      <path d="M 145 20 v -4" class="halves"/>
      <path d="M 150 0 v 4" class="halves"/>
      <path d="M 150 20 v -4" class="halves"/>
    </g>
    <g id="majors">
      <path d="M 10 0 v 6" class="majors"/>
      <path d="M 10 20 v -6" class="majors"/>
      <path d="M 20 0 v 6" class="majors"/>
      <path d="M 20 20 v -6" class="majors"/>
      <path d="M 30 0 v 6" class="majors"/>
      <path d="M 30 20 v -6" class="majors"/>
      <path d="M 40 0 v 6" class="majors"/>
      <path d="M 40 20 v -6" class="majors"/>
      <path d="M 50 0 v 6" class="majors"/>
      <path d="M 50 20 v -6" class="majors"/>
      <path d="M 60 0 v 6" class="majors"/>
      <path d="M 60 20 v -6" class="majors"/>
      <path d="M 70 0 v 6" class="majors"/>
      <path d="M 70 20 v -6" class="majors"/>
      <path d="M 80 0 v 6" class="majors"/>
      <path d="M 80 20 v -6" class="majors"/>
      <path d="M 90 0 v 6" class="majors"/>
      <path d="M 90 20 v -6" class="majors"/>
      <path d="M 100 0 v 6" class="majors"/>
      <path d="M 100 20 v -6" class="majors"/>
      <path d="M 110 0 v 6" class="majors"/>
      <path d="M 110 20 v -6" class="majors"/>
      <path d="M 120 0 v 6" class="majors"/>
      <path d="M 120 20 v -6" class="majors"/>
      <path d="M 130 0 v 6" class="majors"/>
      <path d="M 130 20 v -6" class="majors"/>
      <path d="M 140 0 v 6" class="majors"/>
      <path d="M 140 20 v -6" class="majors"/>
      <g id="labels">
        <text text-anchor="middle" x="10" y="11.5" class="labels">1</text>
        <text text-anchor="middle" x="20" y="11.5" class="labels">2</text>
        <text text-anchor="middle" x="30" y="11.5" class="labels">3</text>
        <text text-anchor="middle" x="40" y="11.5" class="labels">4</text>
        <text text-anchor="middle" x="50" y="11.5" class="labels">5</text>
        <text text-anchor="middle" x="60" y="11.5" class="labels">6</text>
        <text text-anchor="middle" x="70" y="11.5" class="labels">7</text>
        <text text-anchor="middle" x="80" y="11.5" class="labels">8</text>
        <text text-anchor="middle" x="90" y="11.5" class="labels">9</text>
        <text text-anchor="middle" x="100" y="11.5" class="labels">10</text>
        <text text-anchor="middle" x="110" y="11.5" class="labels">11</text>
        <text text-anchor="middle" x="120" y="11.5" class="labels">12</text>
        <text text-anchor="middle" x="130" y="11.5" class="labels">13</text>
        <text text-anchor="middle" x="140" y="11.5" class="labels">14</text>
      </g>
    </g>
  </g>
</svg>
<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="170mm" height="30mm" viewBox="0 0 170 30">
  <style type="text/css">
    <![CDATA[
      .labels {
        fill: white;
        font: 3pt monospace;
      }
      .majors {
        stroke: white;
        stroke-width: 0.3;
      }
      .halves {
        stroke: white;
        stroke-width: 0.15;
      }
      .minors {
        stroke: white;
        stroke-width: 0.15;
      }
      .frame {
        stroke: white;
        stroke-width: 0.15;
        fill: none;
      }
    ]]>
  </style>
  <g id="ruler" transform="translate(10 5)">
    <rect id="frame" width="150" height="20" class="frame"/>
    <g id="minors">
      <path d="M 0 0 v 2" class="minors"/>
      <path d="M 0 20 v -2" class="minors"/>
      <path d="M 1 0 v 2" class="minors"/>
      <path d="M 1 20 v -2" class="minors"/>
      <path d="M 2 0 v 2" class="minors"/>
      <path d="M 2 20 v -2" class="minors"/>
      <path d="M 3 0 v 2" class="minors"/>
      <path d="M 3 20 v -2" class="minors"/>
      <path d="M 4 0 v 2" class="minors"/>
      <path d="M 4 20 v -2" class="minors"/>
      <path d="M 5 0 v 2" class="minors"/>
      <path d="M 5 20 v -2" class="minors"/>
      <path d="M 6 0 v 2" class="minors"/>
      <path d="M 6 20 v -2" class="minors"/>
      <path d="M 7 0 v 2" class="minors"/>
      <path d="M 7 20 v -2" class="minors"/>
      <path d="M 8 0 v 2" class="minors"/>
      <path d="M 8 20 v -2" class="minors"/>
      <path d="M 9 0 v 2" class="minors"/>
      <path d="M 9 20 v -2" class="minors"/>
      <path d="M 10 0 v 2" class="minors"/>
      <path d="M 10 20 v -2" class="minors"/>
      <path d="M 11 0 v 2" class="minors"/>
      <path d="M 11 20 v -2" class="minors"/>
      <path d="M 12 0 v 2" class="minors"/>
      <path d="M 12 20 v -2" class="minors"/>
      <path d="M 13 0 v 2" class="minors"/>
      <path d="M 13 20 v -2" class="minors"/>
      <path d="M 14 0 v 2" class="minors"/>
      <path d="M 14 20 v -2" class="minors"/>
      <path d="M 15 0 v 2" class="minors"/>
      <path d="M 15 20 v -2" class="minors"/>
      <path d="M 16 0 v 2" class="minors"/>
      <path d="M 16 20 v -2" class="minors"/>
      <path d="M 17 0 v 2" class="minors"/>
      <path d="M 17 20 v -2" class="minors"/>
      <path d="M 18 0 v 2" class="minors"/>
      <path d="M 18 20 v -2" class="minors"/>
      <path d="M 19 0 v 2" class="minors"/>
      <path d="M 19 20 v -2" class="minors"/>
      <path d="M 20 0 v 2" class="minors"/>
      <path d="M 20 20 v -2" class="minors"/>
      <path d="M 21 0 v 2" class="minors"/>
      <path d="M 21 20 v -2" class="minors"/>
      <path d="M 22 0 v 2" class="minors"/>
      <path d="M 22 20 v -2" class="minors"/>
      <path d="M 23 0 v 2" class="minors"/>
      <path d="M 23 20 v -2" class="minors"/>
      <path d="M 24 0 v 2" class="minors"/>
      <path d="M 24 20 v -2" class="minors"/>
      <path d="M 25 0 v 2" class="minors"/>
      <path d="M 25 20 v -2" class="minors"/>
      <path d="M 26 0 v 2" class="minors"/>
      <path d="M 26 20 v -2" class="minors"/>
      <path d="M 27 0 v 2" class="minors"/>
      <path d="M 27 20 v -2" class="minors"/>
      <path d="M 28 0 v 2" class="minors"/>
      <path d="M 28 20 v -2" class="minors"/>
      <path d="M 29 0 v 2" class="minors"/>
      <path d="M 29 20 v -2" class="minors"/>
      <path d="M 30 0 v 2" class="minors"/>
      <path d="M 30 20 v -2" class="minors"/>
      <path d="M 31 0 v 2" class="minors"/>
      <path d="M 31 20 v -2" class="minors"/>
      <path d="M 32 0 v 2" class="minors"/>
      <path d="M 32 20 v -2" class="minors"/>
      <path d="M 33 0 v 2" class="minors"/>
      <path d="M 33 20 v -2" class="minors"/>
      <path d="M 34 0 v 2" class="minors"/>
      <path d="M 34 20 v -2" class="minors"/>
      <path d="M 35 0 v 2" class="minors"/>
      <path d="M 35 20 v -2" class="minors"/>
      <path d="M 36 0 v 2" class="minors"/>
      <path d="M 36 20 v -2" class="minors"/>
      <path d="M 37 0 v 2" class="minors"/>
      <path d="M 37 20 v -2" class="minors"/>
      <path d="M 38 0 v 2" class="minors"/>
      <path d="M 38 20 v -2" class="minors"/>
      <path d="M 39 0 v 2" class="minors"/>
      <path d="M 39 20 v -2" class="minors"/>
      <path d="M 40 0 v 2" class="minors"/>
      <path d="M 40 20 v -2" class="minors"/>
      <path d="M 41 0 v 2" class="minors"/>
      <path d="M 41 20 v -2" class="minors"/>
      <path d="M 42 0 v 2" class="minors"/>
      <path d="M 42 20 v -2" class="minors"/>
      <path d="M 43 0 v 2" class="minors"/>
      <path d="M 43 20 v -2" class="minors"/>
      <path d="M 44 0 v 2" class="minors"/>
      <path d="M 44 20 v -2" class="minors"/>
      <path d="M 45 0 v 2" class="minors"/>
      <path d="M 45 20 v -2" class="minors"/>
      <path d="M 46 0 v 2" class="minors"/>
      <path d="M 46 20 v -2" class="minors"/>
      <path d="M 47 0 v 2" class="minors"/>
      <path d="M 47 20 v -2" class="minors"/>
      <path d="M 48 0 v 2" class="minors"/>
      <path d="M 48 20 v -2" class="minors"/>
      <path d="M 49 0 v 2" class="minors"/>
      <path d="M 49 20 v -2" class="minors"/>
      <path d="M 50 0 v 2" class="minors"/>
      <path d="M 50 20 v -2" class="minors"/>
      <path d="M 51 0 v 2" class="minors"/>
      <path d="M 51 20 v -2" class="minors"/>
      <path d="M 52 0 v 2" class="minors"/>
      <path d="M 52 20 v -2" class="minors"/>
      <path d="M 53 0 v 2" class="minors"/>
      <path d="M 53 20 v -2" class="minors"/>
      <path d="M 54 0 v 2" class="minors"/>
      <path d="M 54 20 v -2" class="minors"/>
      <path d="M 55 0 v 2" class="minors"/>
      <path d="M 55 20 v -2" class="minors"/>
      <path d="M 56 0 v 2" class="minors"/>
      <path d="M 56 20 v -2" class="minors"/>
      <path d="M 57 0 v 2" class="minors"/>
      <path d="M 57 20 v -2" class="minors"/>
      <path d="M 58 0 v 2" class="minors"/>
      <path d="M 58 20 v -2" class="minors"/>
      <path d="M 59 0 v 2" class="minors"/>
      <path d="M 59 20 v -2" class="minors"/>
      <path d="M 60 0 v 2" class="minors"/>
      <path d="M 60 20 v -2" class="minors"/>
      <path d="M 61 0 v 2" class="minors"/>
      <path d="M 61 20 v -2" class="minors"/>
      <path d="M 62 0 v 2" class="minors"/>
      <path d="M 62 20 v -2" class="minors"/>
      <path d="M 63 0 v 2" class="minors"/>
      <path d="M 63 20 v -2" class="minors"/>
      <path d="M 64 0 v 2" class="minors"/>
      <path d="M 64 20 v -2" class="minors"/>
      <path d="M 65 0 v 2" class="minors"/>
      <path d="M 65 20 v -2" class="minors"/>
      <path d="M 66 0 v 2" class="minors"/>
      <path d="M 66 20 v -2" class="minors"/>
      <path d="M 67 0 v 2" class="minors"/>
      <path d="M 67 20 v -2" class="minors"/>
      <path d="M 68 0 v 2" class="minors"/>
      <path d="M 68 20 v -2" class="minors"/>
      <path d="M 69 0 v 2" class="minors"/>
      <path d="M 69 20 v -2" class="minors"/>
      <path d="M 70 0 v 2" class="minors"/>
      <path d="M 70 20 v -2" class="minors"/>
      <path d="M 71 0 v 2" class="minors"/>
      <path d="M 71 20 v -2" class="minors"/>
      <path d="M 72 0 v 2" class="minors"/>
      <path d="M 72 20 v -2" class="minors"/>
      <path d="M 73 0 v 2" class="minors"/>
      <path d="M 73 20 v -2" class="minors"/>
      <path d="M 74 0 v 2" class="minors"/>
      <path d="M 74 20 v -2" class="minors"/>
      <path d="M 75 0 v 2" class="minors"/>
      <path d="M 75 20 v -2" class="minors"/>
      <path d="M 76 0 v 2" class="minors"/>
      <path d="M 76 20 v -2" class="minors"/>
      <path d="M 77 0 v 2" class="minors"/>
      <path d="M 77 20 v -2" class="minors"/>
      <path d="M 78 0 v 2" class="minors"/>
      <path d="M 78 20 v -2" class="minors"/>
      <path d="M 79 0 v 2" class="minors"/>
      <path d="M 79 20 v -2" class="minors"/>
      <path d="M 80 0 v 2" class="minors"/>
      <path d="M 80 20 v -2" class="minors"/>
      <path d="M 81 0 v 2" class="minors"/>
      <path d="M 81 20 v -2" class="minors"/>
      <path d="M 82 0 v 2" class="minors"/>
      <path d="M 82 20 v -2" class="minors"/>
      <path d="M 83 0 v 2" class="minors"/>
      <path d="M 83 20 v -2" class="minors"/>
      <path d="M 84 0 v 2" class="minors"/>
      <path d="M 84 20 v -2" class="minors"/>
      <path d="M 85 0 v 2" class="minors"/>
      <path d="M 85 20 v -2" class="minors"/>
      <path d="M 86 0 v 2" class="minors"/>
      <path d="M 86 20 v -2" class="minors"/>
      <path d="M 87 0 v 2" class="minors"/>
      <path d="M 87 20 v -2" class="minors"/>
      <path d="M 88 0 v 2" class="minors"/>
      <path d="M 88 20 v -2" class="minors"/>
      <path d="M 89 0 v 2" class="minors"/>
      <path d="M 89 20 v -2" class="minors"/>
      <path d="M 90 0 v 2" class="minors"/>
      <path d="M 90 20 v -2" class="minors"/>
      <path d="M 91 0 v 2" class="minors"/>
      <path d="M 91 20 v -2" class="minors"/>
      <path d="M 92 0 v 2" class="minors"/>
      <path d="M 92 20 v -2" class="minors"/>
      <path d="M 93 0 v 2" class="minors"/>
      <path d="M 93 20 v -2" class="minors"/>
      <path d="M 94 0 v 2" class="minors"/>
      <path d="M 94 20 v -2" class="minors"/>
      <path d="M 95 0 v 2" class="minors"/>
      <path d="M 95 20 v -2" class="minors"/>
      <path d="M 96 0 v 2" class="minors"/>
      <path d="M 96 20 v -2" class="minors"/>
      <path d="M 97 0 v 2" class="minors"/>
      <path d="M 97 20 v -2" class="minors"/>
      <path d="M 98 0 v 2" class="minors"/>
      <path d="M 98 20 v -2" class="minors"/>
      <path d="M 99 0 v 2" class="minors"/>
      <path d="M 99 20 v -2" class="minors"/>
      <path d="M 100 0 v 2" class="minors"/>
      <path d="M 100 20 v -2" class="minors"/>
      <path d="M 101 0 v 2" class="minors"/>
      <path d="M 101 20 v -2" class="minors"/>
      <path d="M 102 0 v 2" class="minors"/>
      <path d="M 102 20 v -2" class="minors"/>
      <path d="M 103 0 v 2" class="minors"/>
      <path d="M 103 20 v -2" class="minors"/>
      <path d="M 104 0 v 2" class="minors"/>
      <path d="M 104 20 v -2" class="minors"/>
      <path d="M 105 0 v 2" class="minors"/>
      <path d="M 105 20 v -2" class="minors"/>
      <path d="M 106 0 v 2" class="minors"/>
      <path d="M 106 20 v -2" class="minors"/>
      <path d="M 107 0 v 2" class="minors"/>
      <path d="M 107 20 v -2" class="minors"/>
      <path d="M 108 0 v 2" class="minors"/>
      <path d="M 108 20 v -2" class="minors"/>
      <path d="M 109 0 v 2" class="minors"/>
      <path d="M 109 20 v -2" class="minors"/>
      <path d="M 110 0 v 2" class="minors"/>
      <path d="M 110 20 v -2" class="minors"/>
      <path d="M 111 0 v 2" class="minors"/>
      <path d="M 111 20 v -2" class="minors"/>
      <path d="M 112 0 v 2" class="minors"/>
      <path d="M 112 20 v -2" class="minors"/>
      <path d="M 113 0 v 2" class="minors"/>
      <path d="M 113 20 v -2" class="minors"/>
      <path d="M 114 0 v 2" class="minors"/>
      <path d="M 114 20 v -2" class="minors"/>
      <path d="M 115 0 v 2" class="minors"/>
      <path d="M 115 20 v -2" class="minors"/>
      <path d="M 116 0 v 2" class="minors"/>
      <path d="M 116 20 v -2" class="minors"/>
      <path d="M 117 0 v 2" class="minors"/>
      <path d="M 117 20 v -2" class="minors"/>
      <path d="M 118 0 v 2" class="minors"/>
      <path d="M 118 20 v -2" class="minors"/>
      <path d="M 119 0 v 2" class="minors"/>
      <path d="M 119 20 v -2" class="minors"/>
      <path d="M 120 0 v 2" class="minors"/>
      <path d="M 120 20 v -2" class="minors"/>
      <path d="M 121 0 v 2" class="minors"/>
      <path d="M 121 20 v -2" class="minors"/>
      <path d="M 122 0 v 2" class="minors"/>
      <path d="M 122 20 v -2" class="minors"/>
      <path d="M 123 0 v 2" class="minors"/>
      <path d="M 123 20 v -2" class="minors"/>
      <path d="M 124 0 v 2" class="minors"/>
      <path d="M 124 20 v -2" class="minors"/>
      <path d="M 125 0 v 2" class="minors"/>
      <path d="M 125 20 v -2" class="minors"/>
      <path d="M 126 0 v 2" class="minors"/>
      <path d="M 126 20 v -2" class="minors"/>
      <path d="M 127 0 v 2" class="minors"/>
      <path d="M 127 20 v -2" class="minors"/>
      <path d="M 128 0 v 2" class="minors"/>
      <path d="M 128 20 v -2" class="minors"/>
      <path d="M 129 0 v 2" class="minors"/>
      <path d="M 129 20 v -2" class="minors"/>
      <path d="M 130 0 v 2" class="minors"/>
      <path d="M 130 20 v -2" class="minors"/>
      <path d="M 131 0 v 2" class="minors"/>
      <path d="M 131 20 v -2" class="minors"/>
      <path d="M 132 0 v 2" class="minors"/>
      <path d="M 132 20 v -2" class="minors"/>
      <path d="M 133 0 v 2" class="minors"/>
      <path d="M 133 20 v -2" class="minors"/>
      <path d="M 134 0 v 2" class="minors"/>
      <path d="M 134 20 v -2" class="minors"/>
      <path d="M 135 0 v 2" class="minors"/>
      <path d="M 135 20 v -2" class="minors"/>
      <path d="M 136 0 v 2" class="minors"/>
      <path d="M 136 20 v -2" class="minors"/>
      <path d="M 137 0 v 2" class="minors"/>
      <path d="M 137 20 v -2" class="minors"/>
      <path d="M 138 0 v 2" class="minors"/>
      <path d="M 138 20 v -2" class="minors"/>
      <path d="M 139 0 v 2" class="minors"/>
      <path d="M 139 20 v -2" class="minors"/>
      <path d="M 140 0 v 2" class="minors"/>
      <path d="M 140 20 v -2" class="minors"/>
      <path d="M 141 0 v 2" class="minors"/>
      <path d="M 141 20 v -2" class="minors"/>
      <path d="M 142 0 v 2" class="minors"/>
      <path d="M 142 20 v -2" class="minors"/>
      <path d="M 143 0 v 2" class="minors"/>
      <path d="M 143 20 v -2" class="minors"/>
      <path d="M 144 0 v 2" class="minors"/>
      <path d="M 144 20 v -2" class="minors"/>
      <path d="M 145 0 v 2" class="minors"/>
      <path d="M 145 20 v -2" class="minors"/>
      <path d="M 146 0 v 2" class="minors"/>
      <path d="M 146 20 v -2" class="minors"/>
      <path d="M 147 0 v 2" class="minors"/>
      <path d="M 147 20 v -2" class="minors"/>
      <path d="M 148 0 v 2" class="minors"/>
      <path d="M 148 20 v -2" class="minors"/>
      <path d="M 149 0 v 2" class="minors"/>
      <path d="M 149 20 v -2" class="minors"/>
      <path d="M 150 0 v 2" class="minors"/>
      <path d="M 150 20 v -2" class="minors"/>
    </g>
    <g id="halves">
      <path d="M 0 0 v 4" class="halves"/>
      <path d="M 0 20 v -4" class="halves"/>
      <path d="M 5 0 v 4" class="halves"/>
      <path d="M 5 20 v -4" class="halves"/>
      <path d="M 10 0 v 4" class="halves"/>
      <path d="M 10 20 v -4" class="halves"/>
      <path d="M 15 0 v 4" class="halves"/>
      <path d="M 15 20 v -4" class="halves"/>
      <path d="M 20 0 v 4" class="halves"/>
      <path d="M 20 20 v -4" class="halves"/>
      <path d="M 25 0 v 4" class="halves"/>
      <path d="M 25 20 v -4" class="halves"/>
      <path d="M 30 0 v 4" class="halves"/>
      <path d="M 30 20 v -4" class="halves"/>
      <path d="M 35 0 v 4" class="halves"/>
      <path d="M 35 20 v -4" class="halves"/>
      <path d="M 40 0 v 4" class="halves"/>
      <path d="M 40 20 v -4" class="halves"/>
      <path d="M 45 0 v 4" class="halves"/>
      <path d="M 45 20 v -4" class="halves"/>
      <path d="M 50 0 v 4" class="halves"/>
      <path d="M 50 20 v -4" class="halves"/>
      <path d="M 55 0 v 4" class="halves"/>
      <path d="M 55 20 v -4" class="halves"/>
      <path d="M 60 0 v 4" class="halves"/>
      <path d="M 60 20 v -4" class="halves"/>
      <path d="M 65 0 v 4" class="halves"/>
      <path d="M 65 20 v -4" class="halves"/>
      <path d="M 70 0 v 4" class="halves"/>
      <path d="M 70 20 v -4" class="halves"/>
      <path d="M 75 0 v 4" class="halves"/>
      <path d="M 75 20 v -4" class="halves"/>
      <path d="M 80 0 v 4" class="halves"/>
      <path d="M 80 20 v -4" class="halves"/>
      <path d="M 85 0 v 4" class="halves"/>
      <path d="M 85 20 v -4" class="halves"/>
      <path d="M 90 0 v 4" class="halves"/>
      <path d="M 90 20 v -4" class="halves"/>
      <path d="M 95 0 v 4" class="halves"/>
      <path d="M 95 20 v -4" class="halves"/>
      <path d="M 100 0 v 4" class="halves"/>
      <path d="M 100 20 v -4" class="halves"/>
      <path d="M 105 0 v 4" class="halves"/>
      <path d="M 105 20 v -4" class="halves"/>
      <path d="M 110 0 v 4" class="halves"/>
      <path d="M 110 20 v -4" class="halves"/>
      <path d="M 115 0 v 4" class="halves"/>
      <path d="M 115 20 v -4" class="halves"/>
      <path d="M 120 0 v 4" class="halves"/>
      <path d="M 120 20 v -4" class="halves"/>
      <path d="M 125 0 v 4" class="halves"/>
      <path d="M 125 20 v -4" class="halves"/>
      <path d="M 130 0 v 4" class="halves"/>
      <path d="M 130 20 v -4" class="halves"/>
      <path d="M 135 0 v 4" class="halves"/>
      <path d="M 135 20 v -4" class="halves"/>
      <path d="M 140 0 v 4" class="halves"/>
      <path d="M 140 20 v -4" class="halves"/>
      <path d="M 145 0 v 4" class="halves"/>
      <path d="M 145 20 v -4" class="halves"/>
      <path d="M 150 0 v 4" class="halves"/>
      <path d="M 150 20 v -4" class="halves"/>
    </g>
    <g id="majors">
      <path d="M 10 0 v 6" class="majors"/>
      <path d="M 10 20 v -6" class="majors"/>
      <path d="M 20 0 v 6" class="majors"/>
      <path d="M 20 20 v -6" class="majors"/>
      <path d="M 30 0 v 6" class="majors"/>
      <path d="M 30 20 v -6" class="majors"/>
      <path d="M 40 0 v 6" class="majors"/>
      <path d="M 40 20 v -6" class="majors"/>
      <path d="M 50 0 v 6" class="majors"/>
      <path d="M 50 20 v -6" class="majors"/>
      <path d="M 60 0 v 6" class="majors"/>
      <path d="M 60 20 v -6" class="majors"/>
      <path d="M 70 0 v 6" class="majors"/>
      <path d="M 70 20 v -6" class="majors"/>
      <path d="M 80 0 v 6" class="majors"/>
      <path d="M 80 20 v -6" class="majors"/>
      <path d="M 90 0 v 6" class="majors"/>
      <path d="M 90 20 v -6" class="majors"/>
      <path d="M 100 0 v 6" class="majors"/>
      <path d="M 100 20 v -6" class="majors"/>
      <path d="M 110 0 v 6" class="majors"/>
      <path d="M 110 20 v -6" class="majors"/>
      <path d="M 120 0 v 6" class="majors"/>
      <path d="M 120 20 v -6" class="majors"/>
      <path d="M 130 0 v 6" class="majors"/>
      <path d="M 130 20 v -6" class="majors"/>
      <path d="M 140 0 v 6" class="majors"/>
      <path d="M 140 20 v -6" class="majors"/>
      <g id="labels">
        <text text-anchor="middle" x="10" y="11.5" class="labels">1</text>
        <text text-anchor="middle" x="20" y="11.5" class="labels">2</text>
        <text text-anchor="middle" x="30" y="11.5" class="labels">3</text>
        <text text-anchor="middle" x="40" y="11.5" class="labels">4</text>
        <text text-anchor="middle" x="50" y="11.5" class="labels">5</text>
        <text text-anchor="middle" x="60" y="11.5" class="labels">6</text>
        <text text-anchor="middle" x="70" y="11.5" class="labels">7</text>
        <text text-anchor="middle" x="80" y="11.5" class="labels">8</text>
        <text text-anchor="middle" x="90" y="11.5" class="labels">9</text>
        <text text-anchor="middle" x="100" y="11.5" class="labels">10</text>
        <text text-anchor="middle" x="110" y="11.5" class="labels">11</text>
        <text text-anchor="middle" x="120" y="11.5" class="labels">12</text>
        <text text-anchor="middle" x="130" y="11.5" class="labels">13</text>
        <text text-anchor="middle" x="140" y="11.5" class="labels">14</text>
      </g>
    </g>
  </g>
</svg>

Ruler

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

COLS = 15
MULTIPLE = 5
ROWS = 10
UNIT = 6

canvas = SVG.Canvas width: COLS * UNIT, height: ROWS * UNIT
grid = Grid canvas, unit: UNIT, multiple: MULTIPLE

module Guidesheet
  extend SVG::Module

  FRAME = 0.6

  STYLE = {
    ".frame" => { fill: "none", stroke: "blue", "stroke-width": FRAME },
    ".major" => { fill: "none", stroke: "blue", "stroke-width": 0.4 },
    ".minor" => { fill: "none", stroke: "magenta", "stroke-width": 0.12 }
  }.freeze

  base { css STYLE }

  def call(grid)
    layer id: "Squares" do
      Draw grid.x.minor.lines, class: %w[rule minor horizontal]
      Draw grid.y.minor.lines, class: %w[rule minor vertical]
      Draw grid.x.major.lines, class: %w[rule major horizontal]
      Draw grid.y.major.lines, class: %w[rule major vertical]
    end

    rect x: FRAME / 2, y: FRAME / 2,
         width: grid.width - FRAME, height: grid.height - FRAME,
         class: %w[frame rule]
  end
end

SVG :inkscape, canvas, "shape-rendering": "geometricPrecision" do
  rect width: "100%", height: "100%", fill: "white"
  Layer! Guidesheet, grid, attributes: { id: "Guides" }
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

COLS = 15
MULTIPLE = 5
ROWS = 10
UNIT = 6

canvas = SVG.Canvas width: COLS * UNIT, height: ROWS * UNIT
grid = Grid canvas, unit: UNIT, multiple: MULTIPLE

module Guidesheet
  extend SVG::Module

  FRAME = 0.6

  STYLE = {
    ".frame" => { fill: "none", stroke: "#60a5fa", "stroke-width": FRAME },
    ".major" => { fill: "none", stroke: "#60a5fa", "stroke-width": 0.4 },
    ".minor" => { fill: "none", stroke: "#f472b6", "stroke-width": 0.12 }
  }.freeze

  base { css STYLE }

  def call(grid)
    layer id: "Squares" do
      Draw grid.x.minor.lines, class: %w[rule minor horizontal]
      Draw grid.y.minor.lines, class: %w[rule minor vertical]
      Draw grid.x.major.lines, class: %w[rule major horizontal]
      Draw grid.y.major.lines, class: %w[rule major vertical]
    end

    rect x: FRAME / 2, y: FRAME / 2,
         width: grid.width - FRAME, height: grid.height - FRAME,
         class: %w[frame rule]
  end
end

SVG :inkscape, canvas, "shape-rendering": "geometricPrecision" do
  rect width: "100%", height: "100%", fill: "#222222"
  Layer! Guidesheet, grid, attributes: { id: "Guides" }
end.Save
<?xml version="1.0" standalone="no"?>
<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:_="http://sevgi.roktas.dev"
  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  shape-rendering="geometricPrecision"
  width="90.0mm"
  height="60.0mm"
  viewBox="0 0 90 60"
>
  <rect width="100%" height="100%" fill="white"/>
  <g id="Guides" inkscape:groupmode="layer" sodipodi:insensitive="true">
    <style type="text/css">
      <![CDATA[
        .frame {
          fill: none;
          stroke: blue;
          stroke-width: 0.6;
        }
        .major {
          fill: none;
          stroke: blue;
          stroke-width: 0.4;
        }
        .minor {
          fill: none;
          stroke: magenta;
          stroke-width: 0.12;
        }
      ]]>
    </style>
    <g id="Squares" inkscape:groupmode="layer">
      <path d="M 0 0 L 90 0" class="rule minor horizontal"/>
      <path d="M 0 6 L 90 6" class="rule minor horizontal"/>
      <path d="M 0 12 L 90 12" class="rule minor horizontal"/>
      <path d="M 0 18 L 90 18" class="rule minor horizontal"/>
      <path d="M 0 24 L 90 24" class="rule minor horizontal"/>
      <path d="M 0 30 L 90 30" class="rule minor horizontal"/>
      <path d="M 0 36 L 90 36" class="rule minor horizontal"/>
      <path d="M 0 42 L 90 42" class="rule minor horizontal"/>
      <path d="M 0 48 L 90 48" class="rule minor horizontal"/>
      <path d="M 0 54 L 90 54" class="rule minor horizontal"/>
      <path d="M 0 60 L 90 60" class="rule minor horizontal"/>
      <path d="M 0 0 L 0 60" class="rule minor vertical"/>
      <path d="M 6 0 L 6 60" class="rule minor vertical"/>
      <path d="M 12 0 L 12 60" class="rule minor vertical"/>
      <path d="M 18 0 L 18 60" class="rule minor vertical"/>
      <path d="M 24 0 L 24 60" class="rule minor vertical"/>
      <path d="M 30 0 L 30 60" class="rule minor vertical"/>
      <path d="M 36 0 L 36 60" class="rule minor vertical"/>
      <path d="M 42 0 L 42 60" class="rule minor vertical"/>
      <path d="M 48 0 L 48 60" class="rule minor vertical"/>
      <path d="M 54 0 L 54 60" class="rule minor vertical"/>
      <path d="M 60 0 L 60 60" class="rule minor vertical"/>
      <path d="M 66 0 L 66 60" class="rule minor vertical"/>
      <path d="M 72 0 L 72 60" class="rule minor vertical"/>
      <path d="M 78 0 L 78 60" class="rule minor vertical"/>
      <path d="M 84 0 L 84 60" class="rule minor vertical"/>
      <path d="M 90 0 L 90 60" class="rule minor vertical"/>
      <path d="M 0 0 L 90 0" class="rule major horizontal"/>
      <path d="M 0 30 L 90 30" class="rule major horizontal"/>
      <path d="M 0 60 L 90 60" class="rule major horizontal"/>
      <path d="M 0 0 L 0 60" class="rule major vertical"/>
      <path d="M 30 0 L 30 60" class="rule major vertical"/>
      <path d="M 60 0 L 60 60" class="rule major vertical"/>
      <path d="M 90 0 L 90 60" class="rule major vertical"/>
    </g>
    <rect x="0.3" y="0.3" width="89.4" height="59.4" class="frame rule"/>
  </g>
</svg>
<?xml version="1.0" standalone="no"?>
<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:_="http://sevgi.roktas.dev"
  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  shape-rendering="geometricPrecision"
  width="90.0mm"
  height="60.0mm"
  viewBox="0 0 90 60"
>
  <rect width="100%" height="100%" fill="#222222"/>
  <g id="Guides" inkscape:groupmode="layer" sodipodi:insensitive="true">
    <style type="text/css">
      <![CDATA[
        .frame {
          fill: none;
          stroke: #60a5fa;
          stroke-width: 0.6;
        }
        .major {
          fill: none;
          stroke: #60a5fa;
          stroke-width: 0.4;
        }
        .minor {
          fill: none;
          stroke: #f472b6;
          stroke-width: 0.12;
        }
      ]]>
    </style>
    <g id="Squares" inkscape:groupmode="layer">
      <path d="M 0 0 L 90 0" class="rule minor horizontal"/>
      <path d="M 0 6 L 90 6" class="rule minor horizontal"/>
      <path d="M 0 12 L 90 12" class="rule minor horizontal"/>
      <path d="M 0 18 L 90 18" class="rule minor horizontal"/>
      <path d="M 0 24 L 90 24" class="rule minor horizontal"/>
      <path d="M 0 30 L 90 30" class="rule minor horizontal"/>
      <path d="M 0 36 L 90 36" class="rule minor horizontal"/>
      <path d="M 0 42 L 90 42" class="rule minor horizontal"/>
      <path d="M 0 48 L 90 48" class="rule minor horizontal"/>
      <path d="M 0 54 L 90 54" class="rule minor horizontal"/>
      <path d="M 0 60 L 90 60" class="rule minor horizontal"/>
      <path d="M 0 0 L 0 60" class="rule minor vertical"/>
      <path d="M 6 0 L 6 60" class="rule minor vertical"/>
      <path d="M 12 0 L 12 60" class="rule minor vertical"/>
      <path d="M 18 0 L 18 60" class="rule minor vertical"/>
      <path d="M 24 0 L 24 60" class="rule minor vertical"/>
      <path d="M 30 0 L 30 60" class="rule minor vertical"/>
      <path d="M 36 0 L 36 60" class="rule minor vertical"/>
      <path d="M 42 0 L 42 60" class="rule minor vertical"/>
      <path d="M 48 0 L 48 60" class="rule minor vertical"/>
      <path d="M 54 0 L 54 60" class="rule minor vertical"/>
      <path d="M 60 0 L 60 60" class="rule minor vertical"/>
      <path d="M 66 0 L 66 60" class="rule minor vertical"/>
      <path d="M 72 0 L 72 60" class="rule minor vertical"/>
      <path d="M 78 0 L 78 60" class="rule minor vertical"/>
      <path d="M 84 0 L 84 60" class="rule minor vertical"/>
      <path d="M 90 0 L 90 60" class="rule minor vertical"/>
      <path d="M 0 0 L 90 0" class="rule major horizontal"/>
      <path d="M 0 30 L 90 30" class="rule major horizontal"/>
      <path d="M 0 60 L 90 60" class="rule major horizontal"/>
      <path d="M 0 0 L 0 60" class="rule major vertical"/>
      <path d="M 30 0 L 30 60" class="rule major vertical"/>
      <path d="M 60 0 L 60 60" class="rule major vertical"/>
      <path d="M 90 0 L 90 60" class="rule major vertical"/>
    </g>
    <rect x="0.3" y="0.3" width="89.4" height="59.4" class="frame rule"/>
  </g>
</svg>

Squared

#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

COLS = 15
MULTIPLE = 5
ROWS = 10
SLANT = 55
UNIT = 6

canvas = SVG.Canvas width: COLS * UNIT, height: ROWS * UNIT
grid = Grid canvas, unit: UNIT, multiple: MULTIPLE

module Guidesheet
  extend SVG::Module

  FRAME = 0.6

  STYLE = {
    ".angle" => { fill: "none", stroke: "green", "stroke-width": 0.12 },
    ".frame" => { fill: "none", stroke: "blue", "stroke-width": FRAME },
    ".major" => { fill: "none", stroke: "blue", "stroke-width": 0.4 },
    ".minor" => { fill: "none", stroke: "magenta", "stroke-width": 0.12 }
  }.freeze

  base { css STYLE }

  def call(grid)
    layer id: "Slants" do
      TileY "slant-row", n: grid.y.n, d: grid.y.u do
        Hatch grid.rowbox, angle: -SLANT, step: grid.x.su, class: %w[angle slant]
      end
    end

    layer id: "Squares" do
      Draw grid.x.minor.lines, class: %w[rule minor horizontal]
      Draw grid.y.minor.lines, class: %w[rule minor vertical]
      Draw grid.x.major.lines, class: %w[rule major horizontal]
      Draw grid.y.major.lines, class: %w[rule major vertical]
    end

    rect x: FRAME / 2, y: FRAME / 2,
         width: grid.width - FRAME, height: grid.height - FRAME,
         class: %w[frame rule]
  end
end

SVG :inkscape, canvas, "shape-rendering": "geometricPrecision" do
  rect width: "100%", height: "100%", fill: "white"
  Layer! Guidesheet, grid, attributes: { id: "Guides" }
end.Save
#!/usr/bin/env -S ruby -S sevgi
# frozen_string_literal: true

COLS = 15
MULTIPLE = 5
ROWS = 10
SLANT = 55
UNIT = 6

canvas = SVG.Canvas width: COLS * UNIT, height: ROWS * UNIT
grid = Grid canvas, unit: UNIT, multiple: MULTIPLE

module Guidesheet
  extend SVG::Module

  FRAME = 0.6

  STYLE = {
    ".angle" => { fill: "none", stroke: "#4ade80", "stroke-width": 0.12 },
    ".frame" => { fill: "none", stroke: "#60a5fa", "stroke-width": FRAME },
    ".major" => { fill: "none", stroke: "#60a5fa", "stroke-width": 0.4 },
    ".minor" => { fill: "none", stroke: "#f472b6", "stroke-width": 0.12 }
  }.freeze

  base { css STYLE }

  def call(grid)
    layer id: "Slants" do
      TileY "slant-row", n: grid.y.n, d: grid.y.u do
        Hatch grid.rowbox, angle: -SLANT, step: grid.x.su, class: %w[angle slant]
      end
    end

    layer id: "Squares" do
      Draw grid.x.minor.lines, class: %w[rule minor horizontal]
      Draw grid.y.minor.lines, class: %w[rule minor vertical]
      Draw grid.x.major.lines, class: %w[rule major horizontal]
      Draw grid.y.major.lines, class: %w[rule major vertical]
    end

    rect x: FRAME / 2, y: FRAME / 2,
         width: grid.width - FRAME, height: grid.height - FRAME,
         class: %w[frame rule]
  end
end

SVG :inkscape, canvas, "shape-rendering": "geometricPrecision" do
  rect width: "100%", height: "100%", fill: "#222222"
  Layer! Guidesheet, grid, attributes: { id: "Guides" }
end.Save
<?xml version="1.0" standalone="no"?>
<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:_="http://sevgi.roktas.dev"
  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  shape-rendering="geometricPrecision"
  width="90.0mm"
  height="60.0mm"
  viewBox="0 0 90 60"
>
  <rect width="100%" height="100%" fill="white"/>
  <g id="Guides" inkscape:groupmode="layer" sodipodi:insensitive="true">
    <style type="text/css">
      <![CDATA[
        .angle {
          fill: none;
          stroke: green;
          stroke-width: 0.12;
        }
        .frame {
          fill: none;
          stroke: blue;
          stroke-width: 0.6;
        }
        .major {
          fill: none;
          stroke: blue;
          stroke-width: 0.4;
        }
        .minor {
          fill: none;
          stroke: magenta;
          stroke-width: 0.12;
        }
      ]]>
    </style>
    <g id="Slants" inkscape:groupmode="layer">
      <defs>
        <g id="slant-row">
          <path d="M 90 28.376891 L 88.863487 30" class="angle slant"/>
          <path d="M 90 17.91621 L 81.538839 30" class="angle slant"/>
          <path d="M 90 7.455529 L 74.214192 30" class="angle slant"/>
          <path d="M 87.89577 0 L 66.889544 30" class="angle slant"/>
          <path d="M 80.571123 0 L 59.564897 30" class="angle slant"/>
          <path d="M 73.246475 0 L 52.240249 30" class="angle slant"/>
          <path d="M 65.921828 0 L 44.915602 30" class="angle slant"/>
          <path d="M 58.59718 0 L 37.590954 30" class="angle slant"/>
          <path d="M 51.272533 0 L 30.266307 30" class="angle slant"/>
          <path d="M 43.947885 0 L 22.941659 30" class="angle slant"/>
          <path d="M 36.623238 0 L 15.617012 30" class="angle slant"/>
          <path d="M 29.29859 0 L 8.292364 30" class="angle slant"/>
          <path d="M 21.973943 0 L 0.967716 30" class="angle slant"/>
          <path d="M 14.649295 0 L 0 20.921362" class="angle slant"/>
          <path d="M 7.324648 0 L 0 10.460681" class="angle slant"/>
        </g>
      </defs>
      <use id="slant-row-1" href="#slant-row" class="tile-row-1 tile-row-first"/>
      <use id="slant-row-2" href="#slant-row" class="tile-row-2 tile-row-last" y="30"/>
    </g>
    <g id="Squares" inkscape:groupmode="layer">
      <path d="M 0 0 L 90 0" class="rule minor horizontal"/>
      <path d="M 0 6 L 90 6" class="rule minor horizontal"/>
      <path d="M 0 12 L 90 12" class="rule minor horizontal"/>
      <path d="M 0 18 L 90 18" class="rule minor horizontal"/>
      <path d="M 0 24 L 90 24" class="rule minor horizontal"/>
      <path d="M 0 30 L 90 30" class="rule minor horizontal"/>
      <path d="M 0 36 L 90 36" class="rule minor horizontal"/>
      <path d="M 0 42 L 90 42" class="rule minor horizontal"/>
      <path d="M 0 48 L 90 48" class="rule minor horizontal"/>
      <path d="M 0 54 L 90 54" class="rule minor horizontal"/>
      <path d="M 0 60 L 90 60" class="rule minor horizontal"/>
      <path d="M 0 0 L 0 60" class="rule minor vertical"/>
      <path d="M 6 0 L 6 60" class="rule minor vertical"/>
      <path d="M 12 0 L 12 60" class="rule minor vertical"/>
      <path d="M 18 0 L 18 60" class="rule minor vertical"/>
      <path d="M 24 0 L 24 60" class="rule minor vertical"/>
      <path d="M 30 0 L 30 60" class="rule minor vertical"/>
      <path d="M 36 0 L 36 60" class="rule minor vertical"/>
      <path d="M 42 0 L 42 60" class="rule minor vertical"/>
      <path d="M 48 0 L 48 60" class="rule minor vertical"/>
      <path d="M 54 0 L 54 60" class="rule minor vertical"/>
      <path d="M 60 0 L 60 60" class="rule minor vertical"/>
      <path d="M 66 0 L 66 60" class="rule minor vertical"/>
      <path d="M 72 0 L 72 60" class="rule minor vertical"/>
      <path d="M 78 0 L 78 60" class="rule minor vertical"/>
      <path d="M 84 0 L 84 60" class="rule minor vertical"/>
      <path d="M 90 0 L 90 60" class="rule minor vertical"/>
      <path d="M 0 0 L 90 0" class="rule major horizontal"/>
      <path d="M 0 30 L 90 30" class="rule major horizontal"/>
      <path d="M 0 60 L 90 60" class="rule major horizontal"/>
      <path d="M 0 0 L 0 60" class="rule major vertical"/>
      <path d="M 30 0 L 30 60" class="rule major vertical"/>
      <path d="M 60 0 L 60 60" class="rule major vertical"/>
      <path d="M 90 0 L 90 60" class="rule major vertical"/>
    </g>
    <rect x="0.3" y="0.3" width="89.4" height="59.4" class="frame rule"/>
  </g>
</svg>
<?xml version="1.0" standalone="no"?>
<svg
  xmlns="http://www.w3.org/2000/svg"
  xmlns:_="http://sevgi.roktas.dev"
  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  shape-rendering="geometricPrecision"
  width="90.0mm"
  height="60.0mm"
  viewBox="0 0 90 60"
>
  <rect width="100%" height="100%" fill="#222222"/>
  <g id="Guides" inkscape:groupmode="layer" sodipodi:insensitive="true">
    <style type="text/css">
      <![CDATA[
        .angle {
          fill: none;
          stroke: #4ade80;
          stroke-width: 0.12;
        }
        .frame {
          fill: none;
          stroke: #60a5fa;
          stroke-width: 0.6;
        }
        .major {
          fill: none;
          stroke: #60a5fa;
          stroke-width: 0.4;
        }
        .minor {
          fill: none;
          stroke: #f472b6;
          stroke-width: 0.12;
        }
      ]]>
    </style>
    <g id="Slants" inkscape:groupmode="layer">
      <defs>
        <g id="slant-row">
          <path d="M 90 28.376891 L 88.863487 30" class="angle slant"/>
          <path d="M 90 17.91621 L 81.538839 30" class="angle slant"/>
          <path d="M 90 7.455529 L 74.214192 30" class="angle slant"/>
          <path d="M 87.89577 0 L 66.889544 30" class="angle slant"/>
          <path d="M 80.571123 0 L 59.564897 30" class="angle slant"/>
          <path d="M 73.246475 0 L 52.240249 30" class="angle slant"/>
          <path d="M 65.921828 0 L 44.915602 30" class="angle slant"/>
          <path d="M 58.59718 0 L 37.590954 30" class="angle slant"/>
          <path d="M 51.272533 0 L 30.266307 30" class="angle slant"/>
          <path d="M 43.947885 0 L 22.941659 30" class="angle slant"/>
          <path d="M 36.623238 0 L 15.617012 30" class="angle slant"/>
          <path d="M 29.29859 0 L 8.292364 30" class="angle slant"/>
          <path d="M 21.973943 0 L 0.967716 30" class="angle slant"/>
          <path d="M 14.649295 0 L 0 20.921362" class="angle slant"/>
          <path d="M 7.324648 0 L 0 10.460681" class="angle slant"/>
        </g>
      </defs>
      <use id="slant-row-1" href="#slant-row" class="tile-row-1 tile-row-first"/>
      <use id="slant-row-2" href="#slant-row" class="tile-row-2 tile-row-last" y="30"/>
    </g>
    <g id="Squares" inkscape:groupmode="layer">
      <path d="M 0 0 L 90 0" class="rule minor horizontal"/>
      <path d="M 0 6 L 90 6" class="rule minor horizontal"/>
      <path d="M 0 12 L 90 12" class="rule minor horizontal"/>
      <path d="M 0 18 L 90 18" class="rule minor horizontal"/>
      <path d="M 0 24 L 90 24" class="rule minor horizontal"/>
      <path d="M 0 30 L 90 30" class="rule minor horizontal"/>
      <path d="M 0 36 L 90 36" class="rule minor horizontal"/>
      <path d="M 0 42 L 90 42" class="rule minor horizontal"/>
      <path d="M 0 48 L 90 48" class="rule minor horizontal"/>
      <path d="M 0 54 L 90 54" class="rule minor horizontal"/>
      <path d="M 0 60 L 90 60" class="rule minor horizontal"/>
      <path d="M 0 0 L 0 60" class="rule minor vertical"/>
      <path d="M 6 0 L 6 60" class="rule minor vertical"/>
      <path d="M 12 0 L 12 60" class="rule minor vertical"/>
      <path d="M 18 0 L 18 60" class="rule minor vertical"/>
      <path d="M 24 0 L 24 60" class="rule minor vertical"/>
      <path d="M 30 0 L 30 60" class="rule minor vertical"/>
      <path d="M 36 0 L 36 60" class="rule minor vertical"/>
      <path d="M 42 0 L 42 60" class="rule minor vertical"/>
      <path d="M 48 0 L 48 60" class="rule minor vertical"/>
      <path d="M 54 0 L 54 60" class="rule minor vertical"/>
      <path d="M 60 0 L 60 60" class="rule minor vertical"/>
      <path d="M 66 0 L 66 60" class="rule minor vertical"/>
      <path d="M 72 0 L 72 60" class="rule minor vertical"/>
      <path d="M 78 0 L 78 60" class="rule minor vertical"/>
      <path d="M 84 0 L 84 60" class="rule minor vertical"/>
      <path d="M 90 0 L 90 60" class="rule minor vertical"/>
      <path d="M 0 0 L 90 0" class="rule major horizontal"/>
      <path d="M 0 30 L 90 30" class="rule major horizontal"/>
      <path d="M 0 60 L 90 60" class="rule major horizontal"/>
      <path d="M 0 0 L 0 60" class="rule major vertical"/>
      <path d="M 30 0 L 30 60" class="rule major vertical"/>
      <path d="M 60 0 L 60 60" class="rule major vertical"/>
      <path d="M 90 0 L 90 60" class="rule major vertical"/>
    </g>
    <rect x="0.3" y="0.3" width="89.4" height="59.4" class="frame rule"/>
  </g>
</svg>

Copperplate

1

Some examples are adapted from the Victor Book examples.