├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .octocov.yml ├── CHANGELOG.md ├── CREDITS ├── LICENSE ├── Makefile ├── README.md ├── blueprint.go ├── blueprint_test.go ├── coordinates.go ├── example ├── icons │ └── database.go └── png │ └── main.go ├── glyph.go ├── glyph_test.go ├── go.mod ├── go.sum ├── img ├── coordinates.svg ├── database_with_c.svg ├── included │ ├── .keep │ ├── blocks.png │ ├── blocks.svg │ ├── blocks2.png │ ├── blocks2.svg │ ├── blocks2_cc.svg │ ├── blocks_cc.svg │ ├── browser.png │ ├── browser.svg │ ├── browser_cc.svg │ ├── clock.png │ ├── clock.svg │ ├── clock_cc.svg │ ├── cloud.png │ ├── cloud.svg │ ├── cloud_cc.svg │ ├── cube.png │ ├── cube.svg │ ├── cube2.png │ ├── cube2.svg │ ├── cube2_cc.svg │ ├── cube3.png │ ├── cube3.svg │ ├── cube3_cc.svg │ ├── cube4.png │ ├── cube4.svg │ ├── cube4_cc.svg │ ├── cube5.png │ ├── cube5.svg │ ├── cube5_cc.svg │ ├── cube_cc.svg │ ├── cubes.png │ ├── cubes.svg │ ├── cubes2.png │ ├── cubes2.svg │ ├── cubes2_cc.svg │ ├── cubes3.png │ ├── cubes3.svg │ ├── cubes3_cc.svg │ ├── cubes_cc.svg │ ├── database2_cc.svg │ ├── database3_cc.svg │ ├── database4_cc.svg │ ├── database_cc.svg │ ├── db.png │ ├── db.svg │ ├── db2.png │ ├── db2.svg │ ├── db2_cc.svg │ ├── db3.png │ ├── db3.svg │ ├── db3_cc.svg │ ├── db4.png │ ├── db4.svg │ ├── db4_cc.svg │ ├── db_cc.svg │ ├── doc.png │ ├── doc.svg │ ├── doc_cc.svg │ ├── document_cc.svg │ ├── fifo_cc.svg │ ├── gear.png │ ├── gear.svg │ ├── gear_cc.svg │ ├── globe.png │ ├── globe.svg │ ├── globe_cc.svg │ ├── hex.png │ ├── hex.svg │ ├── hex2.png │ ├── hex2.svg │ ├── hex2_cc.svg │ ├── hex_cc.svg │ ├── hexagon2_cc.svg │ ├── hexagon_cc.svg │ ├── key.png │ ├── key.svg │ ├── key_cc.svg │ ├── lb-l4.png │ ├── lb-l4.svg │ ├── lb-l4_cc.svg │ ├── lb-l7.png │ ├── lb-l7.svg │ ├── lb-l7_cc.svg │ ├── lb.png │ ├── lb.svg │ ├── lb_cc.svg │ ├── lifo_cc.svg │ ├── lock.png │ ├── lock.svg │ ├── lock_cc.svg │ ├── metrics.png │ ├── metrics.svg │ ├── metrics_cc.svg │ ├── monitor.png │ ├── monitor.svg │ ├── monitor2.png │ ├── monitor2.svg │ ├── monitor2_cc.svg │ ├── monitor_cc.svg │ ├── page_cc.svg │ ├── pen.png │ ├── pen.svg │ ├── pen2.png │ ├── pen2.svg │ ├── pen2_cc.svg │ ├── pen_cc.svg │ ├── proxy.png │ ├── proxy.svg │ ├── proxy_cc.svg │ ├── queue.png │ ├── queue.svg │ ├── queue2.png │ ├── queue2.svg │ ├── queue2_cc.svg │ ├── queue_cc.svg │ ├── server.png │ ├── server.svg │ ├── server_cc.svg │ ├── servers.png │ ├── servers.svg │ ├── servers_cc.svg │ ├── shield.png │ ├── shield.svg │ ├── shield_cc.svg │ ├── terminal.png │ ├── terminal.svg │ ├── terminal_cc.svg │ ├── text.png │ ├── text.svg │ ├── text_cc.svg │ ├── timer_cc.svg │ ├── unlock.png │ ├── unlock.svg │ ├── unlock_cc.svg │ ├── user.png │ ├── user.svg │ ├── user_cc.svg │ └── write_cc.svg └── logo.svg ├── included.go ├── included.md ├── map.go ├── map_test.go ├── misc ├── coordinates │ └── main.go ├── database_with_c │ └── main.go ├── included │ └── main.go └── logo │ └── main.go ├── points.go └── points_test.go /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | job-test: 11 | name: Test 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | go_version: [1.17] 16 | steps: 17 | - name: Set up Go ${{ matrix.go_version }} 18 | uses: actions/setup-go@v2 19 | with: 20 | go-version: ${{ matrix.go_version }} 21 | 22 | - name: Check out source code 23 | uses: actions/checkout@v2 24 | 25 | - name: Get branch 26 | id: get_branch 27 | run: echo ::set-output name=GITHUB_BRANCH::${GITHUB_REF/refs\/heads\//} 28 | 29 | - name: Update images 30 | run: | 31 | git config --local user.email "action@github.com" 32 | git config --local user.name "GitHub Action" 33 | make ci_doc 34 | env: 35 | GITHUB_BRANCH: ${{ steps.get_branch.outputs.GITHUB_BRANCH }} 36 | 37 | - name: Test 38 | run: make ci 39 | 40 | - name: Run octocov 41 | uses: k1LoW/octocov-action@v0 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | coverage.out 3 | .envrc 4 | .go-version 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /.octocov.yml: -------------------------------------------------------------------------------- 1 | # generated by octocov init 2 | coverage: 3 | if: true 4 | codeToTestRatio: 5 | code: 6 | - '**/*.go' 7 | - '!**/*_test.go' 8 | test: 9 | - '**/*_test.go' 10 | testExecutionTime: 11 | if: true 12 | diff: 13 | datastores: 14 | - artifact://${GITHUB_REPOSITORY} 15 | comment: 16 | if: is_pull_request 17 | report: 18 | if: is_default_branch 19 | datastores: 20 | - artifact://${GITHUB_REPOSITORY} 21 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [v0.5.0](https://github.com/k1LoW/glyph/compare/v0.4.1...v0.5.0) (2020-12-20) 2 | 3 | * Use base colors [#11](https://github.com/k1LoW/glyph/pull/11) ([k1LoW](https://github.com/k1LoW)) 4 | 5 | ## [v0.4.1](https://github.com/k1LoW/glyph/compare/v0.4.0...v0.4.1) (2020-12-11) 6 | 7 | * Fix workaround [#10](https://github.com/k1LoW/glyph/pull/10) ([k1LoW](https://github.com/k1LoW)) 8 | * Refactor code [#9](https://github.com/k1LoW/glyph/pull/9) ([k1LoW](https://github.com/k1LoW)) 9 | * Add workaround for text rendering (png) [#8](https://github.com/k1LoW/glyph/pull/8) ([k1LoW](https://github.com/k1LoW)) 10 | 11 | ## [v0.4.0](https://github.com/k1LoW/glyph/compare/v0.3.0...v0.4.0) (2020-11-30) 12 | 13 | * Add workaround for png (line) rendering [#7](https://github.com/k1LoW/glyph/pull/7) ([k1LoW](https://github.com/k1LoW)) 14 | * Lazy-setting Glyph.lineOps and Glyph.textOpts [#6](https://github.com/k1LoW/glyph/pull/6) ([k1LoW](https://github.com/k1LoW)) 15 | * Add Map.Set and Map.Delete [#5](https://github.com/k1LoW/glyph/pull/5) ([k1LoW](https://github.com/k1LoW)) 16 | 17 | ## [v0.3.0](https://github.com/k1LoW/glyph/compare/v0.2.0...v0.3.0) (2020-11-28) 18 | 19 | * Add function for setting line and text options [#4](https://github.com/k1LoW/glyph/pull/4) ([k1LoW](https://github.com/k1LoW)) 20 | * Fix included icon list [#3](https://github.com/k1LoW/glyph/pull/3) ([k1LoW](https://github.com/k1LoW)) 21 | 22 | ## [v0.2.0](https://github.com/k1LoW/glyph/compare/v0.1.0...v0.2.0) (2020-11-25) 23 | 24 | * Refactor code [#2](https://github.com/k1LoW/glyph/pull/2) ([k1LoW](https://github.com/k1LoW)) 25 | * Add Glyph.textOpts [#1](https://github.com/k1LoW/glyph/pull/1) ([k1LoW](https://github.com/k1LoW)) 26 | 27 | ## [v0.1.0](https://github.com/k1LoW/glyph/compare/332fa1fb9060...v0.1.0) (2020-11-24) 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2020 Ken'ichiro Oyama 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PKG = github.com/k1LoW/glyph 2 | COMMIT = $$(git describe --tags --always) 3 | OSNAME=${shell uname -s} 4 | ifeq ($(OSNAME),Darwin) 5 | DATE = $$(gdate --utc '+%Y-%m-%d_%H:%M:%S') 6 | else 7 | DATE = $$(date --utc '+%Y-%m-%d_%H:%M:%S') 8 | endif 9 | 10 | export GO111MODULE=on 11 | 12 | BUILD_LDFLAGS = -X $(PKG).commit=$(COMMIT) -X $(PKG).date=$(DATE) 13 | 14 | default: test 15 | 16 | ci: depsdev test sec 17 | 18 | test: 19 | go test ./... -coverprofile=coverage.out -covermode=count 20 | 21 | sec: 22 | gosec ./... 23 | 24 | build: 25 | go build -ldflags="$(BUILD_LDFLAGS)" 26 | 27 | doc: 28 | go run ./misc/logo/main.go > img/logo.svg 29 | go run ./misc/coordinates/main.go > img/coordinates.svg 30 | go run ./misc/database_with_c/main.go > img/database_with_c.svg 31 | go run ./misc/included/main.go 32 | 33 | ci_doc: doc 34 | $(eval DIFF_EXIST := $(shell git checkout go.* && git diff --exit-code --quiet || echo "exist")) 35 | test -z "$(DIFF_EXIST)" || (git add -A ./img && git add -A *.md && git commit -m "Update images by GitHub Action (${GITHUB_SHA})" && git push -v origin ${GITHUB_BRANCH}) 36 | 37 | depsdev: 38 | go install github.com/Songmu/ghch/cmd/ghch@v0.10.2 39 | go install github.com/Songmu/gocredits/cmd/gocredits@v0.2.0 40 | go install github.com/securego/gosec/v2/cmd/gosec@v2.8.1 41 | 42 | prerelease: 43 | git pull origin --tag 44 | ghch -w -N ${VER} 45 | gocredits . > CREDITS 46 | git add CHANGELOG.md CREDITS 47 | git commit -m'Bump up version number' 48 | git tag ${VER} 49 | 50 | .PHONY: default test 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # glyph [![build](https://github.com/k1LoW/glyph/workflows/build/badge.svg)](https://github.com/k1LoW/glyph/actions) 2 | 3 |

4 | glyph 5 |

6 | 7 | `glyph` is a embedded icon framework. 8 | 9 | ## Concept 10 | 11 | `glyph` generates icons by connecting predefined coordinates with lines. 12 | 13 | ![img](img/coordinates.svg)![img](img/database_with_c.svg) 14 | 15 | ``` go 16 | package main 17 | 18 | import ( 19 | "os" 20 | "strings" 21 | 22 | "github.com/k1LoW/glyph" 23 | ) 24 | 25 | func main() { 26 | g, _ := glyph.New() 27 | _ = g.Line(strings.Split("b0 d0 h0 j0 j6 h8 d8 b6 b0", " ")) 28 | _ = g.Line(strings.Split("b0 d2 h2 j0", " ")) 29 | _ = g.Line(strings.Split("b2 d4 h4 j2", " ")) 30 | _ = g.Line(strings.Split("b4 d6 h6 j4", " ")) 31 | _ = g.Write(os.Stdout) 32 | } 33 | ``` 34 | 35 | ## Included Icon Set 36 | 37 | `glyph` has [included icon set](included.md). 38 | 39 | ``` go 40 | package main 41 | 42 | import ( 43 | "os" 44 | "strings" 45 | 46 | "github.com/k1LoW/glyph" 47 | ) 48 | 49 | func main() { 50 | g, _ := glyph.Included().Get("browser") 51 | _ = g.Write(os.Stdout) 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /blueprint.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | type LineAndOpts string 9 | 10 | func (l LineAndOpts) Parse() ([]string, []string, error) { 11 | points := []string{} 12 | opts := []string{} 13 | ps := GetPoints() 14 | for _, s := range strings.Split(string(l), " ") { 15 | _, err := ps.Get(s) 16 | if err == nil { 17 | points = append(points, s) 18 | continue 19 | } 20 | if strings.Count(s, ":") != 1 { 21 | return nil, nil, fmt.Errorf("invalid option: %s", s) 22 | } 23 | opts = append(opts, s) 24 | } 25 | return points, opts, nil 26 | } 27 | 28 | type TextAndOpts string 29 | 30 | func (t TextAndOpts) Parse() (string, string, []string, error) { 31 | splited := strings.Split(string(t), " ") 32 | if len(splited) < 2 { 33 | return "", "", []string{}, fmt.Errorf("invalid text and opts: %s", t) 34 | } 35 | text := splited[0] 36 | point := splited[1] 37 | opts := splited[2:] 38 | ps := GetPoints() 39 | _, err := ps.Get(point) 40 | if err != nil { 41 | return "", "", []string{}, err 42 | } 43 | for _, s := range opts { 44 | if strings.Count(s, ":") != 1 { 45 | return "", "", []string{}, fmt.Errorf("invalid option: %s", s) 46 | } 47 | } 48 | return text, point, opts, nil 49 | } 50 | 51 | type Blueprint struct { 52 | Key string `json:"key,omitempty" yaml:"key,omitempty" toml:"key,omitempty"` 53 | RawLines []LineAndOpts `json:"lines,omitempty" yaml:"lines,omitempty" toml:"lines,omitempty"` 54 | RawTexts []TextAndOpts `json:"texts,omitempty" yaml:"texts,omitempty" toml:"texts,omitempty"` 55 | } 56 | 57 | func (b Blueprint) ToGlyph() (*Glyph, error) { 58 | g, err := New() 59 | if err != nil { 60 | return nil, err 61 | } 62 | for _, l := range b.RawLines { 63 | points, opts, err := l.Parse() 64 | if err != nil { 65 | return nil, err 66 | } 67 | if err := g.Line(points, opts...); err != nil { 68 | return nil, err 69 | } 70 | } 71 | for _, t := range b.RawTexts { 72 | text, point, opts, err := t.Parse() 73 | if err != nil { 74 | return nil, err 75 | } 76 | if err := g.Text(text, point, opts...); err != nil { 77 | return nil, err 78 | } 79 | } 80 | return g, nil 81 | } 82 | 83 | func (b Blueprint) ToGlyphAndKey() (*Glyph, string, error) { 84 | g, err := b.ToGlyph() 85 | return g, b.Key, err 86 | } 87 | 88 | // NewBlueprint create new Blueprint 89 | func NewBlueprint() *Blueprint { 90 | return &Blueprint{} 91 | } 92 | 93 | func (b *Blueprint) Lines(lines []LineAndOpts) *Blueprint { 94 | b.RawLines = lines 95 | return b 96 | } 97 | 98 | func (b *Blueprint) Texts(texts []TextAndOpts) *Blueprint { 99 | b.RawTexts = texts 100 | return b 101 | } 102 | -------------------------------------------------------------------------------- /blueprint_test.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/goccy/go-yaml" 7 | ) 8 | 9 | func TestBlueprintYAMLUnmarshal(t *testing.T) { 10 | tests := []struct { 11 | in string 12 | wantKey string 13 | wantLineLen int 14 | wantTextLen int 15 | }{ 16 | { 17 | `--- 18 | key: db 19 | lines: 20 | - b0 d0 h0 j0 j6 h8 d8 b6 b0 21 | - b0 d2 h2 j0 22 | - b2 d4 h4 j2 23 | - b4 d6 h6 j4 24 | `, 25 | "db", 26 | 4, 27 | 0, 28 | }, 29 | } 30 | for _, tt := range tests { 31 | b := NewBlueprint() 32 | yaml.Unmarshal([]byte(tt.in), b) 33 | g, key, err := b.ToGlyphAndKey() 34 | if err != nil { 35 | t.Fatal(err) 36 | } 37 | if got := key; got != tt.wantKey { 38 | t.Errorf("got %v\nwant %v", got, tt.wantKey) 39 | } 40 | if got := len(g.lines); got != tt.wantLineLen { 41 | t.Errorf("got %v\nwant %v", got, tt.wantLineLen) 42 | } 43 | if got := len(g.texts); got != tt.wantTextLen { 44 | t.Errorf("got %v\nwant %v", got, tt.wantTextLen) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /coordinates.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/elliotchance/orderedmap" 7 | ) 8 | 9 | func (g *Glyph) addCoordinateLines() error { 10 | opts := orderedmap.NewOrderedMap() 11 | opts.Set("stroke", "#DFDFDF") 12 | opts.Set("stroke-linecap", "round") 13 | opts.Set("stroke-linejoin", "round") 14 | opts.Set("stroke-width", "0.5") 15 | opts.Set("fill-opacity", "0.0") 16 | lines := []*Line{} 17 | pointSets := []string{ 18 | "a0 f0 k0 k5 fa a5 a0", 19 | "a1 g0", 20 | "a2 h0", 21 | "a3 i0", 22 | "a4 j0", 23 | "a5 k0", 24 | "a0 k5", 25 | "a1 j6", 26 | "a2 i7", 27 | "a3 h8", 28 | "a4 g9", 29 | "k1 e0", 30 | "k2 d0", 31 | "k3 c0", 32 | "k4 b0", 33 | "k1 b6", 34 | "k2 c7", 35 | "k3 d8", 36 | "k4 e9", 37 | "b0 b6", 38 | "c0 c7", 39 | "d0 d8", 40 | "e0 e9", 41 | "f0 fa", 42 | "g0 g9", 43 | "h0 h8", 44 | "i0 i7", 45 | "j0 j6", 46 | } 47 | ps := GetPoints() 48 | for _, psets := range pointSets { 49 | l := &Line{ 50 | opts: opts, 51 | } 52 | for _, k := range strings.Split(psets, " ") { 53 | p, err := ps.Get(k) 54 | if err != nil { 55 | return err 56 | } 57 | l.points = append(l.points, p) 58 | } 59 | lines = append(lines, l) 60 | } 61 | g.lines = append(lines, g.lines...) 62 | return nil 63 | } 64 | 65 | func (g *Glyph) addCoordinateTexts() error { 66 | opts := orderedmap.NewOrderedMap() 67 | opts.Set("font-size", "3") 68 | opts.Set("text-anchor", "middle") 69 | opts.Set("fill", "#333333") 70 | opts.Set("font-weight", "normal") 71 | texts := []*Text{} 72 | ps := GetPoints() 73 | for _, k := range ps.Keys() { 74 | p, err := ps.Get(k) 75 | if err != nil { 76 | return err 77 | } 78 | texts = append(texts, &Text{ 79 | point: p, 80 | text: k, 81 | opts: opts, 82 | }) 83 | } 84 | g.texts = append(g.texts, texts...) 85 | return nil 86 | } 87 | -------------------------------------------------------------------------------- /example/icons/database.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "os" 7 | "strings" 8 | 9 | "github.com/k1LoW/glyph" 10 | ) 11 | 12 | func main() { 13 | g, _ := glyph.New() 14 | _ = g.Line(strings.Split("b0 d0 h0 j0 j6 h8 d8 b6 b0", " ")) 15 | _ = g.Line(strings.Split("b0 d2 h2 j0", " ")) 16 | _ = g.Line(strings.Split("b2 d4 h4 j2", " ")) 17 | _ = g.Line(strings.Split("b4 d6 h6 j4", " ")) 18 | _ = g.Write(os.Stdout) 19 | } 20 | -------------------------------------------------------------------------------- /example/png/main.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "os" 7 | "strings" 8 | 9 | "github.com/k1LoW/glyph" 10 | ) 11 | 12 | func main() { 13 | g, _ := glyph.New(glyph.Width(500.0), glyph.Height(500.0)) 14 | _ = g.Line(strings.Split("b0 d0 h0 j0 j6 h8 d8 b6 b0", " ")) 15 | _ = g.Line(strings.Split("b0 d2 h2 j0", " ")) 16 | _ = g.Line(strings.Split("b2 d4 h4 j2", " ")) 17 | _ = g.Line(strings.Split("b4 d6 h6 j4", " ")) 18 | if err := g.WriteImage(os.Stdout); err != nil { 19 | panic(err) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /glyph.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "image" 7 | "image/color" 8 | "image/png" 9 | "io" 10 | "strconv" 11 | "strings" 12 | 13 | svgo "github.com/ajstarks/svgo/float" 14 | "github.com/beta/freetype/truetype" 15 | "github.com/elliotchance/orderedmap" 16 | "github.com/srwiley/oksvg" 17 | "github.com/srwiley/rasterx" 18 | "golang.org/x/image/font" 19 | "golang.org/x/image/font/gofont/gobold" 20 | "golang.org/x/image/math/fixed" 21 | ) 22 | 23 | const defaultColor = "#4B75B9" 24 | const defaultFillColor = "#FFFFFF" 25 | const defaultFontSize = "15.0" 26 | 27 | const BaseColorKey = "baseColor" 28 | const BaseFillColorKey = "baseFillColor" 29 | 30 | var defaultLineOpts = []string{ 31 | fmt.Sprintf("stroke:%s", defaultColor), 32 | "stroke-width:4.0", 33 | "stroke-linecap:round", 34 | "stroke-linejoin:round", 35 | fmt.Sprintf("fill:%s", defaultFillColor), 36 | } 37 | 38 | var defaultTextOpts = []string{ 39 | fmt.Sprintf("fill:%s", defaultColor), 40 | "font-anchor:middle", 41 | "font-weight:bold", 42 | "font-family:Arial,sans-serif", 43 | fmt.Sprintf("font-size:%s", defaultFontSize), 44 | } 45 | 46 | type Line struct { 47 | points []*Point 48 | opts *orderedmap.OrderedMap 49 | } 50 | 51 | type Text struct { 52 | point *Point 53 | text string 54 | opts *orderedmap.OrderedMap 55 | } 56 | 57 | type Glyph struct { 58 | w, h, minx, miny, vw, vh float64 59 | baseColor string 60 | baseFillColor string 61 | baseTextColor string 62 | lineOpts *orderedmap.OrderedMap 63 | lines []*Line 64 | texts []*Text 65 | textOpts *orderedmap.OrderedMap 66 | showCoordinates bool 67 | } 68 | 69 | type Option func(*Glyph) error 70 | 71 | // Width set SVG width 72 | func Width(w float64) Option { 73 | return func(g *Glyph) error { 74 | g.w = w 75 | return nil 76 | } 77 | } 78 | 79 | // Height set SVG height 80 | func Height(h float64) Option { 81 | return func(g *Glyph) error { 82 | g.h = h 83 | return nil 84 | } 85 | } 86 | 87 | // Color set SVG line 'stroke' 88 | func Color(c string) Option { 89 | return func(g *Glyph) error { 90 | g.baseColor = c 91 | g.lineOpts.Set("stroke", c) 92 | return nil 93 | } 94 | } 95 | 96 | // FillColor set SVG line 'fill' 97 | func FillColor(c string) Option { 98 | return func(g *Glyph) error { 99 | g.baseFillColor = c 100 | g.lineOpts.Set("fill", c) 101 | return nil 102 | } 103 | } 104 | 105 | // TextColor set SVG text 'fill' 106 | func TextColor(c string) Option { 107 | return func(g *Glyph) error { 108 | g.baseTextColor = c 109 | g.textOpts.Set("fill", c) 110 | return nil 111 | } 112 | } 113 | 114 | // LineOpt set SVG line option 115 | func LineOpt(opt string) Option { 116 | return func(g *Glyph) error { 117 | splited := strings.Split(opt, ":") 118 | g.lineOpts.Set(strings.Trim(splited[0], " ;"), strings.Trim(splited[1], " ;")) 119 | return nil 120 | } 121 | } 122 | 123 | // TextOpt set SVG text option 124 | func TextOpt(opt string) Option { 125 | return func(g *Glyph) error { 126 | splited := strings.Split(opt, ":") 127 | g.textOpts.Set(strings.Trim(splited[0], " ;"), strings.Trim(splited[1], " ;")) 128 | return nil 129 | } 130 | } 131 | 132 | // LineOpts set SVG line options 133 | func LineOpts(opts []string) Option { 134 | return func(g *Glyph) error { 135 | for _, opt := range opts { 136 | splited := strings.Split(opt, ":") 137 | g.lineOpts.Set(strings.Trim(splited[0], " ;"), strings.Trim(splited[1], " ;")) 138 | } 139 | return nil 140 | } 141 | } 142 | 143 | // TextOpts set SVG text options 144 | func TextOpts(opts []string) Option { 145 | return func(g *Glyph) error { 146 | for _, opt := range opts { 147 | splited := strings.Split(opt, ":") 148 | g.textOpts.Set(strings.Trim(splited[0], " ;"), strings.Trim(splited[1], " ;")) 149 | } 150 | return nil 151 | } 152 | } 153 | 154 | // New return *Glyph 155 | func New(opts ...Option) (*Glyph, error) { 156 | g := &Glyph{ 157 | w: 110.0, 158 | h: 110.0, 159 | minx: 0.0, 160 | miny: 0.0, 161 | vw: 110.0, 162 | vh: 110.0, 163 | baseColor: defaultColor, 164 | baseFillColor: defaultFillColor, 165 | baseTextColor: defaultColor, 166 | lineOpts: orderedmap.NewOrderedMap(), 167 | textOpts: orderedmap.NewOrderedMap(), 168 | showCoordinates: false, 169 | } 170 | for _, opt := range defaultLineOpts { 171 | splited := strings.Split(opt, ":") 172 | g.lineOpts.Set(strings.Trim(splited[0], " ;"), strings.Trim(splited[1], " ;")) 173 | } 174 | for _, opt := range defaultTextOpts { 175 | splited := strings.Split(opt, ":") 176 | g.textOpts.Set(strings.Trim(splited[0], " ;"), strings.Trim(splited[1], " ;")) 177 | } 178 | 179 | for _, opt := range opts { 180 | if err := opt(g); err != nil { 181 | return nil, err 182 | } 183 | } 184 | 185 | return g, nil 186 | } 187 | 188 | // Line draw line 189 | func (g *Glyph) Line(points []string, opts ...string) error { 190 | m := orderedmap.NewOrderedMap() 191 | l := &Line{} 192 | ps := GetPoints() 193 | for _, k := range points { 194 | p, err := ps.Get(k) 195 | if err != nil { 196 | return err 197 | } 198 | l.points = append(l.points, p) 199 | } 200 | for _, opt := range opts { 201 | splited := strings.Split(opt, ":") 202 | m.Set(strings.Trim(splited[0], " ;"), strings.Trim(splited[1], " ;")) 203 | } 204 | l.opts = m 205 | g.lines = append(g.lines, l) 206 | return nil 207 | } 208 | 209 | // Line draw text 210 | func (g *Glyph) Text(text, point string, opts ...string) error { 211 | ps := GetPoints() 212 | p, err := ps.Get(point) 213 | if err != nil { 214 | return err 215 | } 216 | m := orderedmap.NewOrderedMap() 217 | for _, opt := range opts { 218 | splited := strings.Split(opt, ":") 219 | m.Set(strings.Trim(splited[0], " ;"), strings.Trim(splited[1], " ;")) 220 | } 221 | t := &Text{ 222 | point: p, 223 | text: text, 224 | opts: m, 225 | } 226 | g.texts = append(g.texts, t) 227 | return nil 228 | } 229 | 230 | func (g *Glyph) ShowCoordinates() error { 231 | g.showCoordinates = true 232 | return nil 233 | } 234 | 235 | func (g *Glyph) HideCoordinates() error { 236 | g.showCoordinates = false 237 | return nil 238 | } 239 | 240 | func (g *Glyph) Write(w io.Writer) error { 241 | return g.writeSVG(w) 242 | } 243 | 244 | func (g *Glyph) WriteImage(w io.Writer) error { 245 | return g.writePNG(w) 246 | } 247 | 248 | func (g *Glyph) writeSVG(w io.Writer) error { 249 | svg := svgo.New(w) 250 | svg.StartviewUnit(g.w, g.h, "px", g.minx, g.miny, g.vw, g.vh) 251 | if g.showCoordinates { 252 | if err := g.addCoordinateLines(); err != nil { 253 | return err 254 | } 255 | if err := g.addCoordinateTexts(); err != nil { 256 | return err 257 | } 258 | } 259 | for _, l := range g.lines { 260 | x := []float64{} 261 | y := []float64{} 262 | for _, p := range l.points { 263 | x = append(x, p.X) 264 | y = append(y, p.Y) 265 | } 266 | m := orderedmap.NewOrderedMap() 267 | for _, k := range g.lineOpts.Keys() { 268 | v, _ := g.lineOpts.Get(k) 269 | switch v.(string) { 270 | case BaseColorKey: 271 | v = g.baseColor 272 | case BaseFillColorKey: 273 | v = g.baseFillColor 274 | } 275 | m.Set(k, v.(string)) 276 | } 277 | for _, k := range l.opts.Keys() { 278 | v, _ := l.opts.Get(k) 279 | switch v.(string) { 280 | case BaseColorKey: 281 | v = g.baseColor 282 | case BaseFillColorKey: 283 | v = g.baseFillColor 284 | } 285 | m.Set(k, v.(string)) 286 | } 287 | if l.points[0].X == l.points[len(l.points)-1].X && l.points[0].Y == l.points[len(l.points)-1].Y { 288 | // polygon 289 | if _, exist := m.Get("fill-opacity"); !exist { 290 | m.Set("fill-opacity", "1.0") 291 | } 292 | } else { 293 | // line, polyline 294 | if _, exist := m.Get("fill-opacity"); !exist { 295 | m.Set("fill-opacity", "0.0") 296 | } 297 | _ = m.Delete("fill") 298 | } 299 | 300 | // generate SVG options 301 | opts := []string{} 302 | for _, k := range m.Keys() { 303 | v, _ := m.Get(k) 304 | opts = append(opts, fmt.Sprintf("%s:%s", k, v.(string))) 305 | } 306 | 307 | if l.points[0].X == l.points[len(l.points)-1].X && l.points[0].Y == l.points[len(l.points)-1].Y { 308 | // polygon 309 | svg.Polygon(x, y, strings.Join(opts, "; ")) 310 | } else if len(l.points) == 2 { 311 | // line 312 | svg.Line(l.points[0].X, l.points[0].Y, l.points[1].X, l.points[1].Y, strings.Join(opts, "; ")) 313 | } else { 314 | // polyline 315 | svg.Polyline(x, y, strings.Join(opts, "; ")) 316 | } 317 | } 318 | for _, t := range g.texts { 319 | m := orderedmap.NewOrderedMap() 320 | for _, k := range g.textOpts.Keys() { 321 | v, _ := g.textOpts.Get(k) 322 | switch v.(string) { 323 | case BaseColorKey: 324 | v = g.baseColor 325 | case BaseFillColorKey: 326 | v = g.baseFillColor 327 | } 328 | m.Set(k, v.(string)) 329 | } 330 | for _, k := range t.opts.Keys() { 331 | v, _ := t.opts.Get(k) 332 | switch v.(string) { 333 | case BaseColorKey: 334 | v = g.baseColor 335 | case BaseFillColorKey: 336 | v = g.baseFillColor 337 | } 338 | m.Set(k, v.(string)) 339 | } 340 | opts := []string{} 341 | for _, k := range m.Keys() { 342 | v, _ := m.Get(k) 343 | opts = append(opts, fmt.Sprintf("%s:%s", k, v.(string))) 344 | } 345 | svg.Text(t.point.X, t.point.Y, t.text, strings.Join(opts, "; ")) 346 | } 347 | 348 | svg.End() 349 | return nil 350 | } 351 | 352 | func (g *Glyph) writePNG(w io.Writer) error { 353 | svgbuf := new(bytes.Buffer) 354 | 355 | // oksvg workaround: stroke-width 356 | sw, exist := g.lineOpts.Get("stroke-width") 357 | if exist { 358 | fsw, err := strconv.ParseFloat(sw.(string), 64) 359 | if err != nil { 360 | return err 361 | } 362 | g.lineOpts.Set("stroke-width", strconv.FormatFloat(fsw*(g.w/g.vw), 'f', -1, 64)) 363 | } 364 | 365 | if err := g.Write(svgbuf); err != nil { 366 | return err 367 | } 368 | 369 | // revert oksvg workaround: stroke-width 370 | if exist { 371 | g.lineOpts.Set("stroke-width", sw.(string)) 372 | } 373 | 374 | icon, err := oksvg.ReadIconStream(svgbuf) 375 | if err != nil { 376 | return err 377 | } 378 | icon.SetTarget(0, 0, g.w, g.h) 379 | rgba := image.NewRGBA(image.Rect(0, 0, round(g.w), round(g.h))) 380 | icon.Draw(rasterx.NewDasher(round(g.w), round(g.h), rasterx.NewScannerGV(round(g.w), round(g.h), rgba, rgba.Bounds())), 1) 381 | 382 | // oksvg workaround: text 383 | for _, t := range g.texts { 384 | m := orderedmap.NewOrderedMap() 385 | for _, k := range g.textOpts.Keys() { 386 | v, _ := g.textOpts.Get(k) 387 | m.Set(k, v.(string)) 388 | } 389 | for _, k := range t.opts.Keys() { 390 | v, _ := t.opts.Get(k) 391 | m.Set(k, v.(string)) 392 | } 393 | size := defaultFontSize 394 | sizei, exist := m.Get("font-size") 395 | if exist { 396 | size = sizei.(string) 397 | } 398 | clr := defaultColor 399 | clri, exist := m.Get("fill") 400 | if exist { 401 | clr = clri.(string) 402 | } 403 | if err := g.addTextToImage(rgba, t.point.X, t.point.Y, t.text, size, clr); err != nil { 404 | return err 405 | } 406 | } 407 | 408 | return png.Encode(w, rgba) 409 | } 410 | 411 | func (g *Glyph) addTextToImage(img *image.RGBA, x, y float64, text, size, clr string) error { 412 | size64, err := strconv.ParseFloat(size, 64) 413 | if err != nil { 414 | return err 415 | } 416 | 417 | c, err := parseColor(clr) 418 | if err != nil { 419 | return err 420 | } 421 | 422 | to := &truetype.Options{ 423 | Size: size64 * (g.w / g.vw), 424 | DPI: 0, 425 | Hinting: font.HintingNone, 426 | GlyphCacheEntries: 0, 427 | SubPixelsX: 0, 428 | SubPixelsY: 0, 429 | } 430 | f, err := truetype.Parse(gobold.TTF) 431 | if err != nil { 432 | return err 433 | } 434 | face := truetype.NewFace(f, to) 435 | 436 | dr := &font.Drawer{ 437 | Dst: img, 438 | Src: &image.Uniform{c}, 439 | Face: face, 440 | Dot: fixed.Point26_6{ 441 | X: fixed.I(round(x * (g.w / g.vw))), 442 | Y: fixed.I(round(y * (g.w / g.vw))), 443 | }, 444 | } 445 | 446 | dr.DrawString(text) 447 | 448 | return nil 449 | } 450 | 451 | func round(v float64) int { 452 | if v < 0 { 453 | return int(v - 0.5) 454 | } 455 | return int(v + 0.5) 456 | } 457 | 458 | func parseColor(s string) (color.RGBA, error) { 459 | c := color.RGBA{ 460 | A: 0xff, 461 | } 462 | switch len(s) { 463 | case 7: 464 | if _, err := fmt.Sscanf(s, "#%02x%02x%02x", &c.R, &c.G, &c.B); err != nil { 465 | return c, fmt.Errorf("invalid color: %s", s) 466 | } 467 | case 4: 468 | if _, err := fmt.Sscanf(s, "#%1x%1x%1x", &c.R, &c.G, &c.B); err != nil { 469 | return c, fmt.Errorf("invalid color: %s", s) 470 | } 471 | c.R *= 17 472 | c.G *= 17 473 | c.B *= 17 474 | default: 475 | return c, fmt.Errorf("invalid color: %s", s) 476 | } 477 | return c, nil 478 | } 479 | -------------------------------------------------------------------------------- /glyph_test.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strings" 7 | "testing" 8 | ) 9 | 10 | func TestNew(t *testing.T) { 11 | g, err := New() 12 | if err != nil { 13 | t.Fatal(err) 14 | } 15 | if want := 5; g.lineOpts.Len() != want { 16 | t.Errorf("got %v\nwant %v", g.lineOpts.Len(), want) 17 | } 18 | } 19 | 20 | func TestOptionWidth(t *testing.T) { 21 | g, err := New() 22 | if err != nil { 23 | t.Fatal(err) 24 | } 25 | if want := 110.0; g.w != want { 26 | t.Errorf("got %v\nwant %v", g.w, want) 27 | } 28 | opt := Width(120.0) 29 | if err := opt(g); err != nil { 30 | t.Fatal(err) 31 | } 32 | if want := 120.0; g.w != want { 33 | t.Errorf("got %v\nwant %v", g.w, want) 34 | } 35 | if want := 5; g.lineOpts.Len() != want { 36 | t.Errorf("got %v\nwant %v", g.lineOpts.Len(), want) 37 | } 38 | } 39 | 40 | func TestOptionColor(t *testing.T) { 41 | g, err := New() 42 | if err != nil { 43 | t.Fatal(err) 44 | } 45 | if err := g.Line([]string{"a0", "a1"}); err != nil { 46 | t.Fatal(err) 47 | } 48 | { 49 | want := defaultColor 50 | got, _ := g.lineOpts.Get("stroke") 51 | if got != want { 52 | t.Errorf("got %v\nwant %v", got, want) 53 | } 54 | buf := new(bytes.Buffer) 55 | if err := g.Write(buf); err != nil { 56 | t.Fatal(err) 57 | } 58 | if !strings.Contains(buf.String(), fmt.Sprintf("stroke:%s", want)) { 59 | t.Errorf("can not change color\n%v", buf.String()) 60 | } 61 | } 62 | { 63 | want := "#FFFFFF" 64 | opt := Color(want) 65 | if err := opt(g); err != nil { 66 | t.Fatal(err) 67 | } 68 | got, _ := g.lineOpts.Get("stroke") 69 | if got != want { 70 | t.Errorf("got %v\nwant %v", got, want) 71 | } 72 | buf := new(bytes.Buffer) 73 | if err := g.Write(buf); err != nil { 74 | t.Fatal(err) 75 | } 76 | if !strings.Contains(buf.String(), fmt.Sprintf("stroke:%s", want)) { 77 | t.Errorf("can not change color\n%v", buf.String()) 78 | } 79 | if want := 5; g.lineOpts.Len() != want { 80 | t.Errorf("got %v\nwant %v", g.lineOpts.Len(), want) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/k1LoW/glyph 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/ajstarks/svgo v0.0.0-20200725142600-7a3c8b57fecb 7 | github.com/beta/freetype v0.0.1 8 | github.com/elliotchance/orderedmap v1.3.0 9 | github.com/goccy/go-yaml v1.8.4 10 | github.com/google/go-cmp v0.6.0 11 | github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 12 | github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 13 | golang.org/x/image v0.18.0 14 | ) 15 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/ajstarks/svgo v0.0.0-20200725142600-7a3c8b57fecb h1:EVl3FJLQCzSbgBezKo/1A4ADnJ4mtJZ0RvnNzDJ44nY= 2 | github.com/ajstarks/svgo v0.0.0-20200725142600-7a3c8b57fecb/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= 3 | github.com/beta/freetype v0.0.1 h1:/t8b5+N9FlAMOF0d1aZPa83oufB2dU/YDqA0cq/QwyU= 4 | github.com/beta/freetype v0.0.1/go.mod h1:IwMJ63oxprtqBiFXQiJTMyGLdsap+CKsO8ZzQut194I= 5 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 6 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 7 | github.com/elliotchance/orderedmap v1.3.0 h1:k6m77/d0zCXTjsk12nX40TkEBkSICq8T4s6R6bpCqU0= 8 | github.com/elliotchance/orderedmap v1.3.0/go.mod h1:8hdSl6jmveQw8ScByd3AaNHNk51RhbTazdqtTty+NFw= 9 | github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= 10 | github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= 11 | github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= 12 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 13 | github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= 14 | github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= 15 | github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= 16 | github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= 17 | github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= 18 | github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= 19 | github.com/goccy/go-yaml v1.8.4 h1:AOEdR7aQgbgwHznGe3BLkDQVujxCPUpHOZZcQcp8Y3M= 20 | github.com/goccy/go-yaml v1.8.4/go.mod h1:U/jl18uSupI5rdI2jmuCswEA2htH9eXfferR3KfscvA= 21 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 22 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 23 | github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= 24 | github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= 25 | github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= 26 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 27 | github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= 28 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 29 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 30 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 31 | github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM= 32 | github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4= 33 | github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM= 34 | github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU= 35 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 36 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 37 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 38 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 39 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 40 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 41 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 42 | golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= 43 | golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= 44 | golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= 45 | golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= 46 | golang.org/x/image v0.0.0-20190507092727-e4e5bf290fec/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 47 | golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ= 48 | golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E= 49 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 50 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 51 | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 52 | golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 53 | golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 54 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 55 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 56 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 57 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 58 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 59 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 60 | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= 61 | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= 62 | golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= 63 | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= 64 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 65 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 66 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 67 | golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= 68 | golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 69 | golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 70 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 71 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 72 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 73 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 74 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 75 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 76 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 77 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 78 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 79 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 80 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 81 | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 82 | golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= 83 | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 84 | golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= 85 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 86 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 87 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 88 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 89 | golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= 90 | golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= 91 | golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= 92 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 93 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 94 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 95 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 96 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 97 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 98 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 99 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 100 | golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 101 | golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= 102 | golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= 103 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 104 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 105 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 106 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 107 | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= 108 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 109 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 110 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= 111 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 112 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 113 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 114 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 115 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 116 | -------------------------------------------------------------------------------- /img/included/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/.keep -------------------------------------------------------------------------------- /img/included/blocks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/blocks.png -------------------------------------------------------------------------------- /img/included/blocks.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/included/blocks2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/blocks2.png -------------------------------------------------------------------------------- /img/included/blocks2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/included/blocks2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/included/blocks_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/included/browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/browser.png -------------------------------------------------------------------------------- /img/included/browser.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/included/browser_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/included/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/clock.png -------------------------------------------------------------------------------- /img/included/clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/clock_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/cloud.png -------------------------------------------------------------------------------- /img/included/cloud.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /img/included/cloud_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /img/included/cube.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/cube.png -------------------------------------------------------------------------------- /img/included/cube.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/cube2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/cube2.png -------------------------------------------------------------------------------- /img/included/cube2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/cube2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/cube3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/cube3.png -------------------------------------------------------------------------------- /img/included/cube3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/cube3_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/cube4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/cube4.png -------------------------------------------------------------------------------- /img/included/cube4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/cube4_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/cube5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/cube5.png -------------------------------------------------------------------------------- /img/included/cube5.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/cube5_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/cube_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/cubes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/cubes.png -------------------------------------------------------------------------------- /img/included/cubes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/included/cubes2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/cubes2.png -------------------------------------------------------------------------------- /img/included/cubes2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /img/included/cubes2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /img/included/cubes3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/cubes3.png -------------------------------------------------------------------------------- /img/included/cubes3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /img/included/cubes3_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /img/included/cubes_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/included/database2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/database3_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/database4_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/database_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/db.png -------------------------------------------------------------------------------- /img/included/db.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/db2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/db2.png -------------------------------------------------------------------------------- /img/included/db2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/db2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/db3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/db3.png -------------------------------------------------------------------------------- /img/included/db3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/db3_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/db4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/db4.png -------------------------------------------------------------------------------- /img/included/db4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/db4_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/db_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/doc.png -------------------------------------------------------------------------------- /img/included/doc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/included/doc_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/included/document_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/included/fifo_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /img/included/gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/gear.png -------------------------------------------------------------------------------- /img/included/gear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/gear_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/globe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/globe.png -------------------------------------------------------------------------------- /img/included/globe.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/included/globe_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /img/included/hex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/hex.png -------------------------------------------------------------------------------- /img/included/hex.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /img/included/hex2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/hex2.png -------------------------------------------------------------------------------- /img/included/hex2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/hex2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/hex_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /img/included/hexagon2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/hexagon_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /img/included/key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/key.png -------------------------------------------------------------------------------- /img/included/key.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/key_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/included/lb-l4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/lb-l4.png -------------------------------------------------------------------------------- /img/included/lb-l4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | L4 15 | 16 | -------------------------------------------------------------------------------- /img/included/lb-l4_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | L4 15 | 16 | -------------------------------------------------------------------------------- /img/included/lb-l7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/lb-l7.png -------------------------------------------------------------------------------- /img/included/lb-l7.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | L7 15 | 16 | -------------------------------------------------------------------------------- /img/included/lb-l7_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | L7 15 | 16 | -------------------------------------------------------------------------------- /img/included/lb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/lb.png -------------------------------------------------------------------------------- /img/included/lb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/included/lb_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/included/lifo_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /img/included/lock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/lock.png -------------------------------------------------------------------------------- /img/included/lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/lock_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/metrics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/metrics.png -------------------------------------------------------------------------------- /img/included/metrics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/metrics_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/monitor.png -------------------------------------------------------------------------------- /img/included/monitor.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/monitor2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/monitor2.png -------------------------------------------------------------------------------- /img/included/monitor2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/included/monitor2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/included/monitor_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/page_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/included/pen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/pen.png -------------------------------------------------------------------------------- /img/included/pen.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/pen2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/pen2.png -------------------------------------------------------------------------------- /img/included/pen2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/included/pen2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/included/pen_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/proxy.png -------------------------------------------------------------------------------- /img/included/proxy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/included/proxy_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /img/included/queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/queue.png -------------------------------------------------------------------------------- /img/included/queue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /img/included/queue2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/queue2.png -------------------------------------------------------------------------------- /img/included/queue2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /img/included/queue2_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /img/included/queue_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /img/included/server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/server.png -------------------------------------------------------------------------------- /img/included/server.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/server_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/servers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/servers.png -------------------------------------------------------------------------------- /img/included/servers.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/included/servers_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/included/shield.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/shield.png -------------------------------------------------------------------------------- /img/included/shield.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /img/included/shield_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /img/included/terminal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/terminal.png -------------------------------------------------------------------------------- /img/included/terminal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/terminal_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/included/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/text.png -------------------------------------------------------------------------------- /img/included/text.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/included/text_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /img/included/timer_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/unlock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/unlock.png -------------------------------------------------------------------------------- /img/included/unlock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/unlock_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/k1LoW/glyph/1301a47b58d49ae7d20882aaca82b4c772a013f3/img/included/user.png -------------------------------------------------------------------------------- /img/included/user.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/user_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /img/included/write_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /included.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | var included = []struct { 9 | key string 10 | lines []string 11 | texts []string 12 | aliases []string 13 | }{ 14 | { 15 | "db", 16 | []string{ 17 | "b0 d0 h0 j0 j6 h8 d8 b6 b0", 18 | "b0 d2 h2 j0", 19 | "b2 d4 h4 j2", 20 | "b4 d6 h6 j4", 21 | }, 22 | []string{}, 23 | []string{"database"}, 24 | }, 25 | { 26 | "doc", 27 | []string{ 28 | "b0 b5 f9 f4 b0", 29 | "c0 c1 f4 f8 g8 g3 c0", 30 | "d0 d1 g3 g7 h7 h2 d0", 31 | "d0 d1 g3 g7 h7 h2 d0", 32 | "f1 f2 h2 h6 j6 j1 f1", 33 | "c2 d3", 34 | "c3 e5", 35 | "c4 e6", 36 | "d6 e7", 37 | }, 38 | []string{}, 39 | []string{"document"}, 40 | }, 41 | { 42 | "browser", 43 | []string{ 44 | "d0 d5 i7 i2 d0", 45 | "d1 i3", 46 | "e1 e2", 47 | "f2 f3", 48 | "g2 g3", 49 | }, 50 | []string{}, 51 | []string{}, 52 | }, 53 | { 54 | "cube", 55 | []string{ 56 | "f1 b1 b5 f9 j5 j1 f1", 57 | "c2 f5", 58 | "f5 f8", 59 | "g4 j1", 60 | }, 61 | []string{}, 62 | []string{}, 63 | }, 64 | { 65 | "lb", 66 | []string{ 67 | "a3 a4 c6 e6 e5 c3 a3", 68 | "f1 f2 g2 h1 h0 g0 f1", 69 | "h2 h3 i3 j2 j1 i1 h2", 70 | "i4 i5 j5 k4 k3 j3 i4", 71 | "d4 e4 e2 f2", 72 | "e5 h3", 73 | "e6 f6 h6 i5", 74 | }, 75 | []string{}, 76 | []string{}, 77 | }, 78 | { 79 | "terminal", 80 | []string{ 81 | fmt.Sprintf("d0 d5 i7 i2 d0 fill:%s", BaseColorKey), 82 | fmt.Sprintf("e2 f4 e4 stroke:%s", BaseFillColorKey), 83 | fmt.Sprintf("f5 g5 stroke:%s", BaseFillColorKey), 84 | }, 85 | []string{}, 86 | []string{}, 87 | }, 88 | { 89 | "proxy", 90 | []string{ 91 | "d3 d4 f6 h4 h3 f3 d3", 92 | "a2 a3 b4 c4 c3 b2 a2", 93 | "c5 c6 d7 e7 e6 d5 c5", 94 | "g1 g2 h2 i1 i0 h0 g1", 95 | "i2 i3 j3 k2 k1 j1 i2", 96 | "c4 d4", 97 | "d5 e5", 98 | "g3 h2", 99 | "h3 i2", 100 | }, 101 | []string{}, 102 | []string{}, 103 | }, 104 | { 105 | "cloud", 106 | []string{ 107 | "a3 a4 b5 j5 k4 k2 j2 i1 h1 f2 d3 c2 b2 b3 a3", 108 | }, 109 | []string{}, 110 | []string{}, 111 | }, 112 | { 113 | "metrics", 114 | []string{ 115 | "c0 c4 i7 i3", 116 | "c1 d4 e3 f6 g4 h1 i5 i7 c4 c1", 117 | "c2 d4 e4 f3 g6 h4 i6 i7 c4 c2", 118 | "c1 d4 e3 f6 g4 h1 i5", 119 | }, 120 | []string{}, 121 | []string{}, 122 | }, 123 | { 124 | "globe", 125 | []string{ 126 | "a1 a4 c7 e9 g9 i7 k4 k1 i0 g0 e0 c0 a1", 127 | "e0 b2 b4 d8", 128 | "e0 d2 d6 e9", 129 | "g0 h2 h6 g9", 130 | "g0 j2 j4 h8", 131 | "c0 c1 e3 g3 i1 i0", 132 | "a1 b3 d5 h5 j3 k1", 133 | "a3 b5 e8 g8 j5 k3", 134 | }, 135 | []string{}, 136 | []string{}, 137 | }, 138 | { 139 | "lb-l4", 140 | []string{ 141 | "a3 a4 c6 e6 e5 c3 a3", 142 | "f1 f2 g2 h1 h0 g0 f1", 143 | "h2 h3 i3 j2 j1 i1 h2", 144 | "i4 i5 j5 k4 k3 j3 i4", 145 | "d4 e4 e2 f2", 146 | "e5 h3", 147 | "e6 f6 h6 i5", 148 | }, 149 | []string{ 150 | "L4 a1 font-size:22.0", 151 | }, 152 | []string{}, 153 | }, 154 | { 155 | "lb-l7", 156 | []string{ 157 | "a3 a4 c6 e6 e5 c3 a3", 158 | "f1 f2 g2 h1 h0 g0 f1", 159 | "h2 h3 i3 j2 j1 i1 h2", 160 | "i4 i5 j5 k4 k3 j3 i4", 161 | "d4 e4 e2 f2", 162 | "e5 h3", 163 | "e6 f6 h6 i5", 164 | }, 165 | []string{ 166 | "L7 a1 font-size:22.0", 167 | }, 168 | []string{}, 169 | }, 170 | { 171 | "shield", 172 | []string{ 173 | "c1 c5 d7 f9 h7 i5 i1 g2 f2 e2 c1", 174 | }, 175 | []string{}, 176 | []string{}, 177 | }, 178 | { 179 | "blocks", 180 | []string{ 181 | "b1 b5 f9 j5 j1 f1 b1", 182 | "b3 f7 f9", 183 | "f7 j3", 184 | "b1 d3 d5", 185 | "d3 f3 f5", 186 | "d1 h3 h5", 187 | "h3 j1", 188 | "d5 f5 h5", 189 | }, 190 | []string{}, 191 | []string{}, 192 | }, 193 | { 194 | "cubes", 195 | []string{ 196 | "b3 b5 d7 f7 h7 j5 j3 h3 h1 f1 d1 d3 b3", 197 | "d1 f3 h1", 198 | "d3 f5 h3", 199 | "b3 d5 f5 h5 j3", 200 | "f3 f7", 201 | "d5 d7", 202 | "h5 h7", 203 | }, 204 | []string{}, 205 | []string{}, 206 | }, 207 | { 208 | "cubes2", 209 | []string{ 210 | "b1 b3 d5 d7 f9 h7 h5 j3 j1 h1 f3 d1 b1", 211 | "b1 d3 f3 h3 j1", 212 | "d3 d5 f5 h5 h3", 213 | "f3 f5", 214 | "d5 f7 h5", 215 | "f7 f9", 216 | }, 217 | []string{}, 218 | []string{}, 219 | }, 220 | { 221 | "gear", 222 | []string{ 223 | "c1 b2 c3 c4 b4 c6 d6 e7 e8 g8 g7 h6 i6 j4 i4 i3 j2 i1 h2 g2 g1 e1 e2 d2 c1", 224 | "e4 e5 f6 g5 g4 f4 e4", 225 | }, 226 | []string{}, 227 | []string{}, 228 | }, 229 | { 230 | "hex", 231 | []string{ 232 | "f1 b1 b5 f9 j5 j1 f1", 233 | }, 234 | []string{}, 235 | []string{"hexagon"}, 236 | }, 237 | { 238 | "hex2", 239 | []string{ 240 | "f1 b1 b5 f9 j5 j1 f1", 241 | fmt.Sprintf("d3 d5 f7 h5 h3 f3 d3 fill:%s", BaseColorKey), 242 | }, 243 | []string{}, 244 | []string{"hexagon2"}, 245 | }, 246 | { 247 | "cube2", 248 | []string{ 249 | "c2 c5 f8 i5 i2 f2 c2", 250 | "d3 f5 f7", 251 | "g4 i2", 252 | }, 253 | []string{}, 254 | []string{}, 255 | }, 256 | { 257 | "cube3", 258 | []string{ 259 | "d3 d5 f7 h5 h3 f3 d3", 260 | "d3 f5 h3", 261 | "f5 f7", 262 | }, 263 | []string{}, 264 | []string{}, 265 | }, 266 | { 267 | "cube4", 268 | []string{ 269 | "f1 b1 b5 f9 j5 j1 f1", 270 | "c2 c5 f8 i5 i2 f2 c2", 271 | "d3 f5 f7", 272 | "g4 i2", 273 | }, 274 | []string{}, 275 | []string{}, 276 | }, 277 | { 278 | "cube5", 279 | []string{ 280 | "f1 b1 b5 f9 j5 j1 f1", 281 | "d3 d5 f7 h5 h3 f3 d3", 282 | "d3 f5 h3", 283 | "f5 f7", 284 | }, 285 | []string{}, 286 | []string{}, 287 | }, 288 | { 289 | "text", 290 | []string{ 291 | "d1 d6 h8 h3 d1", 292 | "e3 f4", 293 | "e4 g5", 294 | "e5 g6", 295 | "f7 g7", 296 | }, 297 | []string{}, 298 | []string{"page"}, 299 | }, 300 | { 301 | "pen", 302 | []string{ 303 | "d5 d7 f7 f6 h3 i0 h0 f3 e5 d5", 304 | "e5 f6", 305 | "d7 e6", 306 | }, 307 | []string{}, 308 | []string{}, 309 | }, 310 | { 311 | "pen2", 312 | []string{ 313 | "c0 c5 g8 g3 c0", 314 | "d2 e3", 315 | "d3 f5", 316 | "d4 f6", 317 | "d5 f7", 318 | "f6 f7 g6 j0 i0 f6", 319 | "f6 g6", 320 | }, 321 | []string{}, 322 | []string{"write"}, 323 | }, 324 | { 325 | "monitor", 326 | []string{ 327 | "f5 i5 k3", 328 | "b2 c4 d5 i3 h1 c2 b2", 329 | "k0 j6 k5 k0", 330 | "c2 d5", 331 | }, 332 | []string{}, 333 | []string{}, 334 | }, 335 | { 336 | "monitor2", 337 | []string{ 338 | "c0 c4 h7 h3 c0", 339 | "f5 h8 i7 f5", 340 | "d4 e6 g6 h4 g3 e3 d4", 341 | "e6 e7 f8 f7 e6", 342 | "d6 g8", 343 | }, 344 | []string{}, 345 | []string{}, 346 | }, 347 | { 348 | "db2", 349 | []string{ 350 | "b0 b5 e8 g8 j5 j0 g0 e0 b0", 351 | "b1 b3 e6 g6 j3 j1 g4 e4 b1", 352 | }, 353 | []string{}, 354 | []string{"database2"}, 355 | }, 356 | { 357 | "db3", 358 | []string{ 359 | "b0 b5 e8 g8 j5 j0 g0 e0 b0", 360 | fmt.Sprintf("b1 b3 e6 g6 j3 j1 g4 e4 b1 fill:%s", BaseColorKey), 361 | }, 362 | []string{}, 363 | []string{"database3"}, 364 | }, 365 | { 366 | "queue", 367 | []string{ 368 | "a1 a2 b3 c3 c2 b1 a1", 369 | "d4 d5 e6 h4 h3 g3 d4", 370 | "i4 i5 j5 k4 k3 j3 i4", 371 | "a1 b2 c2", 372 | "b2 b5 c5", 373 | "i2 j1 j3", 374 | "i4 j4 k3", 375 | "j4 j5", 376 | "d4 e5 e6", 377 | "e4 f5 f6", 378 | "f4 g4 g5", 379 | "e5 h3", 380 | }, 381 | []string{}, 382 | []string{"fifo"}, 383 | }, 384 | { 385 | "queue2", 386 | []string{ 387 | "a1 a2 b3 c3 c2 b1 a1", 388 | "d4 d5 e6 h4 h3 g3 d4", 389 | "i4 i5 j5 k4 k3 j3 i4", 390 | "a1 b2 c2", 391 | "b2 b5 c5", 392 | "d6 c6 e8 i5", 393 | "i4 j4 k3", 394 | "j4 j5", 395 | "d4 e5 e6", 396 | "e4 f5 f6", 397 | "f4 g4 g5", 398 | "e5 h3", 399 | }, 400 | []string{}, 401 | []string{"lifo"}, 402 | }, 403 | { 404 | "db4", 405 | []string{ 406 | "b0 b5 e8 g8 j5 j0 g0 e0 b0", 407 | "b1 e4 g4 j1", 408 | fmt.Sprintf("b3 b5 e8 g8 j5 j3 g6 e6 b3 fill:%s", BaseColorKey), 409 | }, 410 | []string{}, 411 | []string{"database4"}, 412 | }, 413 | { 414 | "key", 415 | []string{ 416 | "c1 c2 d4 e5 e9 fa g9 g8 f8 g7 f7 g6 g5 h4 i2 i1 h0 g0 e0 d0 c1", 417 | "e1 e2 g2 g1 e1", 418 | }, 419 | []string{}, 420 | []string{}, 421 | }, 422 | { 423 | "lock", 424 | []string{ 425 | "d1 d3 e4 e2 g2 g4 h3 h1 g1 e1 d1", 426 | "c3 c7 d8 h8 i7 i3 h3 d3 c3", 427 | fmt.Sprintf("e5 e6 f7 g6 g5 f5 e5 fill:%s", BaseColorKey), 428 | "f7 f8", 429 | }, 430 | []string{}, 431 | []string{}, 432 | }, 433 | { 434 | "unlock", 435 | []string{ 436 | "d0 d2 e2 e1 g1 g4 h3 h0 g0 e0 d0", 437 | "c3 c7 d8 h8 i7 i3 h3 d3 c3", 438 | fmt.Sprintf("e5 e6 f7 g6 g5 f5 e5 fill:%s", BaseColorKey), 439 | "f7 f8", 440 | }, 441 | []string{}, 442 | []string{}, 443 | }, 444 | { 445 | "clock", 446 | []string{ 447 | "f2 f3", 448 | "c3 c4 d6 e7 g7 h6 i4 i3 h2 g2 e2 d2 c3", 449 | "e1 g1", 450 | "f3 f5 h3", 451 | }, 452 | []string{}, 453 | []string{"timer"}, 454 | }, 455 | { 456 | "server", 457 | []string{ 458 | "a1 a3 g8 g7 k3 k1 g1 b2 a1", 459 | "b2 g6 g7", 460 | "f6 k1", 461 | "b3 e6", 462 | }, 463 | []string{}, 464 | []string{}, 465 | }, 466 | { 467 | "servers", 468 | []string{ 469 | "a0 a4 g9 g8 k4 k0 g0 b1 a0", 470 | "b1 g5 g8", 471 | "f5 k0", 472 | "g6 k2", 473 | "b2 e5", 474 | "a2 g7", 475 | "b4 e7", 476 | }, 477 | []string{}, 478 | []string{}, 479 | }, 480 | { 481 | "blocks2", 482 | []string{ 483 | "b1 b5 f9 j5 j1 f1 b1", 484 | "b3 f7 f9", 485 | "f7 j3", 486 | "b1 d3 d7", 487 | "d3 f3 f5", 488 | "d1 h3 h7", 489 | "h3 j1", 490 | "d5 f5 h5", 491 | "f3 h1", 492 | }, 493 | []string{}, 494 | []string{}, 495 | }, 496 | { 497 | "cubes3", 498 | []string{ 499 | "b0 b2 d4 f4 h4 j2 j0 h0 f2 d0 b0", 500 | "b0 d2 f2 h2 j0", 501 | "d2 d4", 502 | "f2 f4", 503 | "h2 h4", 504 | "b4 b6 d8 f8 h8 j6 j4 h4 f6 d4 b4", 505 | "b4 d6 f6 h6 j4", 506 | "d6 d8", 507 | "f6 f8", 508 | "h6 h8", 509 | }, 510 | []string{}, 511 | []string{}, 512 | }, 513 | { 514 | "user", 515 | []string{ 516 | "c7 i7 h8 d8 c7", 517 | "d0 d2 f4 h2 h0 f0 d0", 518 | "b5 d7 h7 j5 i4 g4 e4 c4 b5", 519 | "d5 d8 h8 h5 d5", 520 | }, 521 | []string{}, 522 | []string{}, 523 | }, 524 | } 525 | 526 | var cSet Set 527 | 528 | type Set map[string]*Blueprint 529 | 530 | func (s Set) Get(k string) (*Glyph, error) { 531 | sg, ok := s[k] 532 | if !ok { 533 | return nil, fmt.Errorf("invalid key: %s", k) 534 | } 535 | return sg.ToGlyph() 536 | } 537 | 538 | func (s Set) Keys() []string { 539 | keys := []string{} 540 | for k := range s { 541 | keys = append(keys, k) 542 | } 543 | sort.Strings(keys) 544 | return keys 545 | } 546 | 547 | // Included return included icon set 548 | func Included() Set { 549 | if len(cSet) > 0 { 550 | return cSet 551 | } 552 | s := Set{} 553 | for _, g := range included { 554 | lo := []LineAndOpts{} 555 | for _, l := range g.lines { 556 | lo = append(lo, LineAndOpts(l)) 557 | } 558 | to := []TextAndOpts{} 559 | for _, t := range g.texts { 560 | to = append(to, TextAndOpts(t)) 561 | } 562 | sg := NewBlueprint().Lines(lo).Texts(to) 563 | s[g.key] = sg 564 | for _, a := range g.aliases { 565 | s[a] = sg 566 | } 567 | } 568 | cSet = s 569 | return s 570 | } 571 | 572 | // IncludedAliases return included icon aliases 573 | func IncludedAliases() map[string][]string { 574 | aliases := map[string][]string{} 575 | for _, g := range included { 576 | aliases[g.key] = g.aliases 577 | } 578 | return aliases 579 | } 580 | -------------------------------------------------------------------------------- /included.md: -------------------------------------------------------------------------------- 1 | # Included Icon Set 2 | 3 | | Name | Icon (SVG) | Icon (PNG) | Icon (Custom color) | 4 | | ---- | ---- | ---- | ---- | 5 | | blocks | ![blocks](img/included/blocks.svg) | ![blocks](img/included/blocks.png) | ![blocks](img/included/blocks_cc.svg) | 6 | | blocks2 | ![blocks2](img/included/blocks2.svg) | ![blocks2](img/included/blocks2.png) | ![blocks2](img/included/blocks2_cc.svg) | 7 | | browser | ![browser](img/included/browser.svg) | ![browser](img/included/browser.png) | ![browser](img/included/browser_cc.svg) | 8 | | clock ( img/included/clock_cc.svg ) | ![clock](img/included/clock.svg) | ![clock](img/included/clock.png) | ![clock](img/included/clock_cc.svg) | 9 | | cloud | ![cloud](img/included/cloud.svg) | ![cloud](img/included/cloud.png) | ![cloud](img/included/cloud_cc.svg) | 10 | | cube | ![cube](img/included/cube.svg) | ![cube](img/included/cube.png) | ![cube](img/included/cube_cc.svg) | 11 | | cube2 | ![cube2](img/included/cube2.svg) | ![cube2](img/included/cube2.png) | ![cube2](img/included/cube2_cc.svg) | 12 | | cube3 | ![cube3](img/included/cube3.svg) | ![cube3](img/included/cube3.png) | ![cube3](img/included/cube3_cc.svg) | 13 | | cube4 | ![cube4](img/included/cube4.svg) | ![cube4](img/included/cube4.png) | ![cube4](img/included/cube4_cc.svg) | 14 | | cube5 | ![cube5](img/included/cube5.svg) | ![cube5](img/included/cube5.png) | ![cube5](img/included/cube5_cc.svg) | 15 | | cubes | ![cubes](img/included/cubes.svg) | ![cubes](img/included/cubes.png) | ![cubes](img/included/cubes_cc.svg) | 16 | | cubes2 | ![cubes2](img/included/cubes2.svg) | ![cubes2](img/included/cubes2.png) | ![cubes2](img/included/cubes2_cc.svg) | 17 | | cubes3 | ![cubes3](img/included/cubes3.svg) | ![cubes3](img/included/cubes3.png) | ![cubes3](img/included/cubes3_cc.svg) | 18 | | db ( img/included/db_cc.svg ) | ![db](img/included/db.svg) | ![db](img/included/db.png) | ![db](img/included/db_cc.svg) | 19 | | db2 ( img/included/db2_cc.svg ) | ![db2](img/included/db2.svg) | ![db2](img/included/db2.png) | ![db2](img/included/db2_cc.svg) | 20 | | db3 ( img/included/db3_cc.svg ) | ![db3](img/included/db3.svg) | ![db3](img/included/db3.png) | ![db3](img/included/db3_cc.svg) | 21 | | db4 ( img/included/db4_cc.svg ) | ![db4](img/included/db4.svg) | ![db4](img/included/db4.png) | ![db4](img/included/db4_cc.svg) | 22 | | doc ( img/included/doc_cc.svg ) | ![doc](img/included/doc.svg) | ![doc](img/included/doc.png) | ![doc](img/included/doc_cc.svg) | 23 | | gear | ![gear](img/included/gear.svg) | ![gear](img/included/gear.png) | ![gear](img/included/gear_cc.svg) | 24 | | globe | ![globe](img/included/globe.svg) | ![globe](img/included/globe.png) | ![globe](img/included/globe_cc.svg) | 25 | | hex ( img/included/hex_cc.svg ) | ![hex](img/included/hex.svg) | ![hex](img/included/hex.png) | ![hex](img/included/hex_cc.svg) | 26 | | hex2 ( img/included/hex2_cc.svg ) | ![hex2](img/included/hex2.svg) | ![hex2](img/included/hex2.png) | ![hex2](img/included/hex2_cc.svg) | 27 | | key | ![key](img/included/key.svg) | ![key](img/included/key.png) | ![key](img/included/key_cc.svg) | 28 | | lb | ![lb](img/included/lb.svg) | ![lb](img/included/lb.png) | ![lb](img/included/lb_cc.svg) | 29 | | lb-l4 | ![lb-l4](img/included/lb-l4.svg) | ![lb-l4](img/included/lb-l4.png) | ![lb-l4](img/included/lb-l4_cc.svg) | 30 | | lb-l7 | ![lb-l7](img/included/lb-l7.svg) | ![lb-l7](img/included/lb-l7.png) | ![lb-l7](img/included/lb-l7_cc.svg) | 31 | | lock | ![lock](img/included/lock.svg) | ![lock](img/included/lock.png) | ![lock](img/included/lock_cc.svg) | 32 | | metrics | ![metrics](img/included/metrics.svg) | ![metrics](img/included/metrics.png) | ![metrics](img/included/metrics_cc.svg) | 33 | | monitor | ![monitor](img/included/monitor.svg) | ![monitor](img/included/monitor.png) | ![monitor](img/included/monitor_cc.svg) | 34 | | monitor2 | ![monitor2](img/included/monitor2.svg) | ![monitor2](img/included/monitor2.png) | ![monitor2](img/included/monitor2_cc.svg) | 35 | | pen | ![pen](img/included/pen.svg) | ![pen](img/included/pen.png) | ![pen](img/included/pen_cc.svg) | 36 | | pen2 ( img/included/pen2_cc.svg ) | ![pen2](img/included/pen2.svg) | ![pen2](img/included/pen2.png) | ![pen2](img/included/pen2_cc.svg) | 37 | | proxy | ![proxy](img/included/proxy.svg) | ![proxy](img/included/proxy.png) | ![proxy](img/included/proxy_cc.svg) | 38 | | queue ( img/included/queue_cc.svg ) | ![queue](img/included/queue.svg) | ![queue](img/included/queue.png) | ![queue](img/included/queue_cc.svg) | 39 | | queue2 ( img/included/queue2_cc.svg ) | ![queue2](img/included/queue2.svg) | ![queue2](img/included/queue2.png) | ![queue2](img/included/queue2_cc.svg) | 40 | | server | ![server](img/included/server.svg) | ![server](img/included/server.png) | ![server](img/included/server_cc.svg) | 41 | | servers | ![servers](img/included/servers.svg) | ![servers](img/included/servers.png) | ![servers](img/included/servers_cc.svg) | 42 | | shield | ![shield](img/included/shield.svg) | ![shield](img/included/shield.png) | ![shield](img/included/shield_cc.svg) | 43 | | terminal | ![terminal](img/included/terminal.svg) | ![terminal](img/included/terminal.png) | ![terminal](img/included/terminal_cc.svg) | 44 | | text ( img/included/text_cc.svg ) | ![text](img/included/text.svg) | ![text](img/included/text.png) | ![text](img/included/text_cc.svg) | 45 | | unlock | ![unlock](img/included/unlock.svg) | ![unlock](img/included/unlock.png) | ![unlock](img/included/unlock_cc.svg) | 46 | | user | ![user](img/included/user.svg) | ![user](img/included/user.png) | ![user](img/included/user_cc.svg) | 47 | -------------------------------------------------------------------------------- /map.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | // Map is icon (glyph) map 9 | type Map struct { 10 | opts []Option 11 | glyphs map[string]*Glyph 12 | } 13 | 14 | func (m *Map) Keys() []string { 15 | keys := []string{} 16 | for k := range m.glyphs { 17 | keys = append(keys, k) 18 | } 19 | sort.Strings(keys) 20 | return keys 21 | } 22 | 23 | func (m *Map) Get(k string) (*Glyph, error) { 24 | g, ok := m.glyphs[k] 25 | if !ok { 26 | return nil, fmt.Errorf("invalid key: %s", k) 27 | } 28 | for _, opt := range m.opts { 29 | if err := opt(g); err != nil { 30 | return nil, err 31 | } 32 | } 33 | return g, nil 34 | } 35 | 36 | func (m *Map) Set(k string, g *Glyph) { 37 | m.glyphs[k] = g 38 | } 39 | 40 | func (m *Map) Delete(k string) { 41 | delete(m.glyphs, k) 42 | } 43 | 44 | // NewMap return *Map 45 | func NewMap(opts ...Option) *Map { 46 | return &Map{ 47 | opts: opts, 48 | glyphs: make(map[string]*Glyph), 49 | } 50 | } 51 | 52 | // NewMapWithIncluded *Map with Included icons 53 | func NewMapWithIncluded(opts ...Option) *Map { 54 | m := NewMap(opts...) 55 | for k, sg := range Included() { 56 | g, err := sg.ToGlyph() 57 | if err != nil { 58 | panic(err) 59 | } 60 | m.glyphs[k] = g 61 | } 62 | return m 63 | } 64 | -------------------------------------------------------------------------------- /map_test.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "strings" 7 | "testing" 8 | ) 9 | 10 | func TestMap(t *testing.T) { 11 | { 12 | m := NewMap() 13 | got := len(m.Keys()) 14 | want := 0 15 | if got != want { 16 | t.Errorf("got %v\nwant %v", got, want) 17 | } 18 | } 19 | 20 | { 21 | m := NewMapWithIncluded() 22 | got := len(m.Keys()) 23 | want := len(Included()) 24 | if got != want { 25 | t.Errorf("got %v\nwant %v", got, want) 26 | } 27 | } 28 | 29 | { 30 | m := NewMapWithIncluded() 31 | g, _ := New() 32 | m.Set("additional-glyph", g) 33 | got := len(m.Keys()) 34 | want := len(Included()) + 1 35 | if got != want { 36 | t.Errorf("got %v\nwant %v", got, want) 37 | } 38 | } 39 | 40 | { 41 | m := NewMapWithIncluded() 42 | m.Delete("db") 43 | got := len(m.Keys()) 44 | want := len(Included()) - 1 45 | if got != want { 46 | t.Errorf("got %v\nwant %v", got, want) 47 | } 48 | } 49 | } 50 | 51 | func TestMapOption(t *testing.T) { 52 | want := "#FFFFFF" 53 | m := NewMapWithIncluded(Color(want)) 54 | g, _ := m.Get("db") 55 | got, _ := g.lineOpts.Get("stroke") 56 | if got != want { 57 | t.Errorf("got %v\nwant %v", got, want) 58 | } 59 | buf := new(bytes.Buffer) 60 | if err := g.Write(buf); err != nil { 61 | t.Fatal(err) 62 | } 63 | if !strings.Contains(buf.String(), fmt.Sprintf("stroke:%s", want)) { 64 | t.Errorf("can not change color\n%v", buf.String()) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /misc/coordinates/main.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "os" 7 | 8 | "github.com/k1LoW/glyph" 9 | ) 10 | 11 | func main() { 12 | g, _ := glyph.New(glyph.Width(400.0), glyph.Height(400.0)) 13 | _ = g.ShowCoordinates() 14 | if err := g.Write(os.Stdout); err != nil { 15 | panic(err) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /misc/database_with_c/main.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "os" 7 | 8 | "github.com/k1LoW/glyph" 9 | ) 10 | 11 | func main() { 12 | g, _ := glyph.Included().Get("database") 13 | _ = glyph.Width(400.0)(g) 14 | _ = glyph.Height(400.0)(g) 15 | _ = g.ShowCoordinates() 16 | if err := g.Write(os.Stdout); err != nil { 17 | panic(err) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /misc/included/main.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "path/filepath" 9 | "strings" 10 | "text/template" 11 | 12 | "github.com/k1LoW/glyph" 13 | ) 14 | 15 | const ts = `# Included Icon Set 16 | 17 | | Name | Icon (SVG) | Icon (PNG) | Icon (Custom color) | 18 | | ---- | ---- | ---- | ---- | 19 | {{- range $_, $p := .Included }} 20 | | {{ index $p 0 }}{{ if ne (index $p 4) "" }} ( {{ index $p 3 }} ){{ end }} | ![{{ index $p 0 }}]({{ index $p 1 }}) | ![{{ index $p 0 }}]({{ index $p 2 }}) | ![{{ index $p 0 }}]({{ index $p 3 }}) | 21 | {{- end }} 22 | ` 23 | 24 | func main() { 25 | m := glyph.NewMapWithIncluded() 26 | included := [][]string{} 27 | aliases := glyph.IncludedAliases() 28 | for _, k := range m.Keys() { 29 | a, ok := aliases[k] 30 | if !ok { 31 | continue 32 | } 33 | g, err := m.Get(k) 34 | if err != nil { 35 | panic(err) 36 | } 37 | p := filepath.Join("img", "included", fmt.Sprintf("%s.svg", k)) 38 | _, _ = fmt.Fprintf(os.Stderr, "create %s\n", p) 39 | i, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) // #nosec 40 | if err != nil { 41 | panic(err) 42 | } 43 | if err := g.Write(i); err != nil { 44 | _ = i.Close() 45 | panic(err) 46 | } 47 | _ = i.Close() 48 | 49 | pp := filepath.Join("img", "included", fmt.Sprintf("%s.png", k)) 50 | _, _ = fmt.Fprintf(os.Stderr, "create %s\n", pp) 51 | ip, err := os.OpenFile(pp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) // #nosec 52 | if err != nil { 53 | panic(err) 54 | } 55 | if err := g.WriteImage(ip); err != nil { 56 | _ = ip.Close() 57 | panic(err) 58 | } 59 | _ = ip.Close() 60 | 61 | cp := filepath.Join("img", "included", fmt.Sprintf("%s_cc.svg", k)) 62 | 63 | included = append(included, []string{k, p, pp, cp, strings.Join(a, ", ")}) 64 | } 65 | 66 | ccm := glyph.NewMapWithIncluded(glyph.Color("#C8EFEA"), glyph.FillColor("#1DAF9E"), glyph.TextColor("#1DAF9E")) 67 | for _, k := range ccm.Keys() { 68 | g, err := ccm.Get(k) 69 | if err != nil { 70 | panic(err) 71 | } 72 | p := filepath.Join("img", "included", fmt.Sprintf("%s_cc.svg", k)) 73 | _, _ = fmt.Fprintf(os.Stderr, "create %s\n", p) 74 | i, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) // #nosec 75 | if err != nil { 76 | panic(err) 77 | } 78 | if err := g.Write(i); err != nil { 79 | _ = i.Close() 80 | panic(err) 81 | } 82 | _ = i.Close() 83 | } 84 | 85 | tmpl := template.Must(template.New("included").Parse(ts)) 86 | tmplData := map[string]interface{}{ 87 | "Included": included, 88 | } 89 | _, _ = fmt.Fprintf(os.Stderr, "create %s\n", "included.md") 90 | md, err := os.OpenFile("included.md", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) // #nosec 91 | if err != nil { 92 | panic(err) 93 | } 94 | if err := tmpl.Execute(md, tmplData); err != nil { 95 | _ = md.Close() 96 | panic(err) 97 | } 98 | _ = md.Close() 99 | } 100 | -------------------------------------------------------------------------------- /misc/logo/main.go: -------------------------------------------------------------------------------- 1 | // +build ignore 2 | 3 | package main 4 | 5 | import ( 6 | "os" 7 | "strings" 8 | 9 | "github.com/k1LoW/glyph" 10 | ) 11 | 12 | func main() { 13 | g, _ := glyph.New(glyph.Width(400.0), glyph.Height(400.0)) 14 | _ = g.Line(strings.Split("j1 h1 f2 b2 d3", " ")) 15 | _ = g.Line(strings.Split("c6 g4", " ")) 16 | _ = g.Line(strings.Split("g4 h7 h4 g4", " ")) 17 | _ = g.Line(strings.Split("d3 g2 j2 g4 d3", " ")) 18 | _ = g.Line(strings.Split("f3 f4 g4 h3 h2 g2 f3", " ")) 19 | _ = g.Line(strings.Split("c5 b4 b5 c6", " ")) 20 | _ = g.Write(os.Stdout) 21 | } 22 | -------------------------------------------------------------------------------- /points.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | "strconv" 7 | ) 8 | 9 | type Point struct { 10 | X float64 11 | Y float64 12 | } 13 | 14 | type Points map[string]*Point 15 | 16 | func (p Points) Get(key string) (*Point, error) { 17 | v, ok := p[key] 18 | if !ok { 19 | return nil, fmt.Errorf("invalid key: %s", key) 20 | } 21 | return v, nil 22 | } 23 | 24 | func (p Points) Keys() []string { 25 | keys := []string{} 26 | for k := range p { 27 | keys = append(keys, k) 28 | } 29 | sort.Strings(keys) 30 | return keys 31 | } 32 | 33 | const dx = 8.660254 34 | const dy = 5.0 35 | 36 | var cPoints = Points{} 37 | 38 | func GetPoints() Points { 39 | if len(cPoints) > 0 { 40 | return cPoints 41 | } 42 | points := Points{} 43 | px := 0xf 44 | py := 0x0 45 | f0x := 55.0 46 | f0y := 5.0 47 | maxy := 10 48 | 49 | // f,e,d,c,b,a 50 | for i := 0; i <= 5; i++ { 51 | max := maxy - i 52 | for j := 0; j <= max; j++ { 53 | key := fmt.Sprintf("%s%x", strconv.FormatInt(int64(px-i), 21), py+j) 54 | points[key] = &Point{ 55 | X: f0x - float64(i)*dx, 56 | Y: f0y + float64(i)*dy + float64(j)*dy*2, 57 | } 58 | } 59 | } 60 | 61 | // g,h,i,j,k 62 | for i := 1; i <= 5; i++ { 63 | max := maxy - i 64 | for j := 0; j <= max; j++ { 65 | key := fmt.Sprintf("%s%x", strconv.FormatInt(int64(px+i), 21), py+j) 66 | points[key] = &Point{ 67 | X: f0x + float64(i)*dx, 68 | Y: f0y + float64(i)*dy + float64(j)*dy*2, 69 | } 70 | } 71 | } 72 | cPoints = points 73 | 74 | return points 75 | } 76 | -------------------------------------------------------------------------------- /points_test.go: -------------------------------------------------------------------------------- 1 | package glyph 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/google/go-cmp/cmp" 7 | ) 8 | 9 | func TestPoints(t *testing.T) { 10 | got := GetPoints() 11 | if diff := cmp.Diff(got["a0"], &Point{X: 55.0 - float64(5)*dx, Y: 30.0}, nil); diff != "" { 12 | t.Errorf("%s", diff) 13 | } 14 | 15 | if diff := cmp.Diff(got["a5"], &Point{X: 55.0 - float64(5)*dx, Y: 80.0}, nil); diff != "" { 16 | t.Errorf("%s", diff) 17 | } 18 | 19 | if _, ok := got["a6"]; ok { 20 | t.Errorf("%v", got["a6"]) 21 | } 22 | 23 | if diff := cmp.Diff(got["f0"], &Point{X: 55.0, Y: 5.0}, nil); diff != "" { 24 | t.Errorf("%s", diff) 25 | } 26 | 27 | if diff := cmp.Diff(got["fa"], &Point{X: 55.0, Y: 105.0}, nil); diff != "" { 28 | t.Errorf("%s", diff) 29 | } 30 | 31 | if _, ok := got["fb"]; ok { 32 | t.Errorf("%v", got["fb"]) 33 | } 34 | 35 | if diff := cmp.Diff(got["k0"], &Point{X: 55.0 + float64(5)*dx, Y: 30.0}, nil); diff != "" { 36 | t.Errorf("%s", diff) 37 | } 38 | 39 | if diff := cmp.Diff(got["k5"], &Point{X: 55.0 + float64(5)*dx, Y: 80.0}, nil); diff != "" { 40 | t.Errorf("%s", diff) 41 | } 42 | 43 | if _, ok := got["k6"]; ok { 44 | t.Errorf("%v", got["k6"]) 45 | } 46 | 47 | if want := 91; len(got) != want { 48 | t.Errorf("len(got) %v\nwant %v", len(got), want) 49 | } 50 | } 51 | --------------------------------------------------------------------------------