├── examples ├── nounfont.eot ├── nounfont │ ├── plant-tree.svg │ ├── happines.svg │ ├── riots.svg │ ├── energy.svg │ ├── trade.svg │ ├── rockets.svg │ ├── economics.svg │ ├── survalance.svg │ ├── soft-tree.svg │ ├── spy.svg │ ├── aircaft.svg │ ├── energy2.svg │ ├── applied-science.svg │ ├── peace.svg │ ├── factory.svg │ ├── old-library.svg │ ├── wind-energy.svg │ ├── diomand-science.svg │ ├── global-map.svg │ ├── city-planning.svg │ ├── monument.svg │ ├── code-of-laws.svg │ ├── radiation.svg │ ├── economics2.svg │ ├── police.svg │ ├── scientific-method.svg │ ├── naval-tech.svg │ ├── electro-fuels.svg │ ├── gps.svg │ ├── child-care.svg │ ├── ecology.svg │ ├── fossle-fuel.svg │ ├── engenearing.svg │ ├── nuclear.svg │ ├── monetary.svg │ ├── bio-fuels.svg │ ├── idea.svg │ ├── monetary-ethics.svg │ ├── holo-theater.svg │ ├── fingerprint.svg │ ├── resycle.svg │ ├── basic-mecanics.svg │ ├── bio-mecanics.svg │ ├── mine.svg │ ├── advanced-mecanics.svg │ ├── communication-tower.svg │ ├── comunity.svg │ ├── solar-energy.svg │ ├── bio-tree.svg │ ├── brain-agumentation.svg │ ├── social-services.svg │ ├── rail-building.svg │ ├── protest.svg │ ├── genetics.svg │ └── human-brain.svg ├── nounfont.html ├── nounfont.css └── nounfont.svg ├── .gitignore ├── README.md └── icons2font.py /examples/nounfont.eot: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[co] 2 | 3 | # Packages 4 | *.egg 5 | *.egg-info 6 | dist 7 | build 8 | eggs 9 | parts 10 | bin 11 | var 12 | sdist 13 | develop-eggs 14 | .installed.cfg 15 | 16 | # Installer logs 17 | pip-log.txt 18 | 19 | # Unit test / coverage reports 20 | .coverage 21 | .tox 22 | 23 | #Translations 24 | *.mo 25 | 26 | #Mr Developer 27 | .mr.developer.cfg 28 | -------------------------------------------------------------------------------- /examples/nounfont/plant-tree.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/nounfont/happines.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/nounfont/riots.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/nounfont/energy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/nounfont/trade.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/nounfont/rockets.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | -------------------------------------------------------------------------------- /examples/nounfont/economics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/nounfont/survalance.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/nounfont/soft-tree.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/nounfont/spy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/nounfont/aircaft.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /examples/nounfont/energy2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | icons2font 2 | ========== 3 | 4 | This utility takes vector icons in svg format and convert them to icon fonts (svg,ttf,waff,eot) to be display in all browsers. 5 | 6 | 7 | Usage 8 | ===== 9 | 10 | 11 | icons2font.py [-h] [--baseline BASELINE] name src [dest] 12 | 13 | This utility takes vector icons in svg format and converts them to icon fonts 14 | (svg,ttf,waff,eot) to be display in all browsers. 15 | 16 | positional arguments: 17 | name name of the icon font you want 18 | src folder wher the svg glyphs are 19 | dest folder to output the stuff 20 | 21 | optional arguments: 22 | -h, --help show this help message and exit 23 | --baseline BASELINE adjust generated chars up or down 24 | 25 | example 26 | ------- 27 | python icons2font.py my_awesome_font ~/some_svgs ~/i2f_output --baseline 2 28 | 29 | 30 | 31 | Requirements 32 | ============ 33 | 34 | * fontforge (with python library) 35 | * ttf2eot 36 | 37 | 38 | Mac installation 39 | ---------------- 40 | brew install fontforge ttf2eot 41 | -------------------------------------------------------------------------------- /examples/nounfont/applied-science.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /examples/nounfont/peace.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /examples/nounfont/factory.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /examples/nounfont/old-library.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/nounfont/wind-energy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 11 | 13 | 14 | -------------------------------------------------------------------------------- /examples/nounfont/diomand-science.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/nounfont/global-map.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /examples/nounfont/city-planning.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/nounfont/monument.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/nounfont/code-of-laws.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/nounfont/radiation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 10 | 12 | 14 | 15 | -------------------------------------------------------------------------------- /examples/nounfont/economics2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/nounfont/police.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/nounfont/scientific-method.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /examples/nounfont/naval-tech.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 14 | 15 | -------------------------------------------------------------------------------- /examples/nounfont/electro-fuels.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 14 | 15 | -------------------------------------------------------------------------------- /examples/nounfont/gps.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 9 | 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /examples/nounfont/child-care.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 12 | 14 | 16 | 17 | -------------------------------------------------------------------------------- /examples/nounfont/ecology.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /examples/nounfont/fossle-fuel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 15 | 16 | -------------------------------------------------------------------------------- /examples/nounfont/engenearing.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/nounfont/nuclear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 13 | 17 | 21 | 22 | -------------------------------------------------------------------------------- /examples/nounfont/monetary.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 12 | 17 | 18 | -------------------------------------------------------------------------------- /examples/nounfont/bio-fuels.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 17 | 18 | -------------------------------------------------------------------------------- /examples/nounfont/idea.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/nounfont/monetary-ethics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 10 | 19 | 20 | -------------------------------------------------------------------------------- /examples/nounfont/holo-theater.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/nounfont/fingerprint.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /examples/nounfont/resycle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 10 | 12 | 14 | 18 | 22 | 24 | 25 | -------------------------------------------------------------------------------- /examples/nounfont/basic-mecanics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 15 | 25 | 26 | -------------------------------------------------------------------------------- /examples/nounfont/bio-mecanics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/nounfont/mine.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 26 | 27 | -------------------------------------------------------------------------------- /examples/nounfont/advanced-mecanics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/nounfont/communication-tower.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /examples/nounfont/comunity.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /examples/nounfont/solar-energy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 | 33 | 34 | -------------------------------------------------------------------------------- /examples/nounfont/bio-tree.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /examples/nounfont.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 17 | 18 |

Font: nounfont

19 | 20 | icon-advanced-mecanics
21 | icon-aircaft
22 | icon-applied-science
23 | icon-basic-mecanics
24 | icon-bio-fuels
25 | icon-bio-mecanics
26 | icon-bio-tree
27 | icon-brain-agumentation
28 | icon-child-care
29 | icon-city-planning
30 | icon-code-of-laws
31 | icon-communication-tower
32 | icon-comunity
33 | icon-diomand-science
34 | icon-ecology
35 | icon-economics
36 | icon-economics2
37 | icon-electro-fuels
38 | icon-energy
39 | icon-energy2
40 | icon-engenearing
41 | icon-factory
42 | icon-fingerprint
43 | icon-fossle-fuel
44 | icon-genetics
45 | icon-global-map
46 | icon-gps
47 | icon-happines
48 | icon-holo-theater
49 | icon-human-brain
50 | icon-idea
51 | icon-mine
52 | icon-monetary-ethics
53 | icon-monetary
54 | icon-monument
55 | icon-naval-tech
56 | icon-nuclear
57 | icon-old-library
58 | icon-peace
59 | icon-plant-tree
60 | icon-police
61 | icon-protest
62 | icon-radiation
63 | icon-rail-building
64 | icon-resycle
65 | icon-riots
66 | icon-rockets
67 | icon-scientific-method
68 | icon-social-services
69 | icon-soft-tree
70 | icon-solar-energy
71 | icon-spy
72 | icon-survalance
73 | icon-trade
74 | icon-wind-energy
75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /examples/nounfont/brain-agumentation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 10 | 12 | 35 | 36 | -------------------------------------------------------------------------------- /examples/nounfont/social-services.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 26 | 28 | 30 | 31 | 32 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /examples/nounfont.css: -------------------------------------------------------------------------------- 1 | 2 | @font-face { 3 | font-family: "nounfont"; 4 | src: url('nounfont.svg') format('svg'); 5 | font-weight: normal; 6 | font-style: normal; 7 | } 8 | 9 | 10 | [class^="icon-"]:before, [class*=" icon-"]:before { 11 | font-family: nounfont; 12 | font-weight: normal; 13 | font-style: normal; 14 | display: inline-block; 15 | text-decoration: inherit; 16 | } 17 | .icon-advanced-mecanics::before { 18 | content: "\f000"; 19 | } 20 | .icon-aircaft::before { 21 | content: "\f001"; 22 | } 23 | .icon-applied-science::before { 24 | content: "\f002"; 25 | } 26 | .icon-basic-mecanics::before { 27 | content: "\f003"; 28 | } 29 | .icon-bio-fuels::before { 30 | content: "\f004"; 31 | } 32 | .icon-bio-mecanics::before { 33 | content: "\f005"; 34 | } 35 | .icon-bio-tree::before { 36 | content: "\f006"; 37 | } 38 | .icon-brain-agumentation::before { 39 | content: "\f007"; 40 | } 41 | .icon-child-care::before { 42 | content: "\f008"; 43 | } 44 | .icon-city-planning::before { 45 | content: "\f009"; 46 | } 47 | .icon-code-of-laws::before { 48 | content: "\f00a"; 49 | } 50 | .icon-communication-tower::before { 51 | content: "\f00b"; 52 | } 53 | .icon-comunity::before { 54 | content: "\f00c"; 55 | } 56 | .icon-diomand-science::before { 57 | content: "\f00d"; 58 | } 59 | .icon-ecology::before { 60 | content: "\f00e"; 61 | } 62 | .icon-economics::before { 63 | content: "\f00f"; 64 | } 65 | .icon-economics2::before { 66 | content: "\f010"; 67 | } 68 | .icon-electro-fuels::before { 69 | content: "\f011"; 70 | } 71 | .icon-energy::before { 72 | content: "\f012"; 73 | } 74 | .icon-energy2::before { 75 | content: "\f013"; 76 | } 77 | .icon-engenearing::before { 78 | content: "\f014"; 79 | } 80 | .icon-factory::before { 81 | content: "\f015"; 82 | } 83 | .icon-fingerprint::before { 84 | content: "\f016"; 85 | } 86 | .icon-fossle-fuel::before { 87 | content: "\f017"; 88 | } 89 | .icon-genetics::before { 90 | content: "\f018"; 91 | } 92 | .icon-global-map::before { 93 | content: "\f019"; 94 | } 95 | .icon-gps::before { 96 | content: "\f01a"; 97 | } 98 | .icon-happines::before { 99 | content: "\f01b"; 100 | } 101 | .icon-holo-theater::before { 102 | content: "\f01c"; 103 | } 104 | .icon-human-brain::before { 105 | content: "\f01d"; 106 | } 107 | .icon-idea::before { 108 | content: "\f01e"; 109 | } 110 | .icon-mine::before { 111 | content: "\f01f"; 112 | } 113 | .icon-monetary-ethics::before { 114 | content: "\f020"; 115 | } 116 | .icon-monetary::before { 117 | content: "\f021"; 118 | } 119 | .icon-monument::before { 120 | content: "\f022"; 121 | } 122 | .icon-naval-tech::before { 123 | content: "\f023"; 124 | } 125 | .icon-nuclear::before { 126 | content: "\f024"; 127 | } 128 | .icon-old-library::before { 129 | content: "\f025"; 130 | } 131 | .icon-peace::before { 132 | content: "\f026"; 133 | } 134 | .icon-plant-tree::before { 135 | content: "\f027"; 136 | } 137 | .icon-police::before { 138 | content: "\f028"; 139 | } 140 | .icon-protest::before { 141 | content: "\f029"; 142 | } 143 | .icon-radiation::before { 144 | content: "\f02a"; 145 | } 146 | .icon-rail-building::before { 147 | content: "\f02b"; 148 | } 149 | .icon-resycle::before { 150 | content: "\f02c"; 151 | } 152 | .icon-riots::before { 153 | content: "\f02d"; 154 | } 155 | .icon-rockets::before { 156 | content: "\f02e"; 157 | } 158 | .icon-scientific-method::before { 159 | content: "\f02f"; 160 | } 161 | .icon-social-services::before { 162 | content: "\f030"; 163 | } 164 | .icon-soft-tree::before { 165 | content: "\f031"; 166 | } 167 | .icon-solar-energy::before { 168 | content: "\f032"; 169 | } 170 | .icon-spy::before { 171 | content: "\f033"; 172 | } 173 | .icon-survalance::before { 174 | content: "\f034"; 175 | } 176 | .icon-trade::before { 177 | content: "\f035"; 178 | } 179 | .icon-wind-energy::before { 180 | content: "\f036"; 181 | } 182 | -------------------------------------------------------------------------------- /examples/nounfont/rail-building.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /examples/nounfont/protest.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 13 | 19 | 22 | 23 | 24 | 25 | 26 | 41 | 42 | -------------------------------------------------------------------------------- /examples/nounfont/genetics.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 10 | 11 | 25 | 31 | 35 | 38 | 46 | 47 | -------------------------------------------------------------------------------- /examples/nounfont/human-brain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 45 | 46 | -------------------------------------------------------------------------------- /icons2font.py: -------------------------------------------------------------------------------- 1 | """ 2 | This utility takes vector icons in svg format and converts 3 | them to icon fonts (svg,ttf,waff,eot) to be display in all browsers. 4 | 5 | requires python-fontforge 6 | """ 7 | import sys 8 | import os 9 | import argparse 10 | from xml.dom import minidom 11 | import md5 12 | 13 | DESIGNER_FONT_START_CHAR = "A" 14 | GSIZE = 1400 15 | 16 | 17 | HEADER = """ 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | """ 27 | 28 | GLYPH = """\n\n""" 29 | 30 | FOOTER = """ 31 | 32 | 33 | 34 | 35 | """ 36 | 37 | DOC_HEADER = """ 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 67 | 68 | 69 |

Font: {0}

70 | """ 71 | DOC_FOOTER = """ 72 |
73 | try out and download desinger font 74 | 75 | 76 | 77 | """ 78 | 79 | # src: url('{0}.eot'); 80 | # src: url('{0}.eot#iefix') format('embedded-opentype'), 81 | # url('{0}.ttf') format('truetype'), 82 | # url('{0}.woff') format('woff'), 83 | # url('{0}.svg') format('svg'), 84 | # url('{0}.otf') format("opentype"); 85 | 86 | 87 | CSS_HEADER = """@font-face {{ 88 | font-family: "{0}"; 89 | src: url('{0}.eot?h={2}'); 90 | src: url('{0}.eot?h={2}#iefix') format('embedded-opentype'), 91 | url('{0}.ttf?h={2}') format('truetype'), 92 | url('{0}.woff?h={2}') format('woff'), 93 | url('{0}.svg?h={2}') format('svg'), 94 | url('{0}.otf?h={2}') format("opentype"); 95 | font-weight: normal; 96 | font-style: normal; 97 | font-feature-settings: "calt=0,liga=0" 98 | }} 99 | [class^="{1}-"], [class*=" {1}-"] {{ 100 | font-family: {0}; 101 | font-weight: normal; 102 | font-style: normal; 103 | display: inline-block; 104 | text-decoration: inherit; 105 | vertical-align: baseline; 106 | -webkit-font-smoothing: antialiased; 107 | }} 108 | """ 109 | 110 | USER_AREA = 0xf000 111 | 112 | COMMANDS_ABS = "MZLHVCSQTA" 113 | COMMANDS_REL = COMMANDS_ABS.lower() 114 | COMMANDS = COMMANDS_ABS + COMMANDS_REL 115 | 116 | def between(a, b, s): 117 | first = s.find(a) 118 | first += len(a) 119 | last = s.find(b, first) 120 | return s[first:last] 121 | 122 | def htmlhex(n): 123 | return hex(n).replace("0x","&#x") + ";" 124 | 125 | def svg_paths(svg): 126 | xmldoc = minidom.parseString(svg) 127 | paths = [] 128 | 129 | # view box 130 | for s in xmldoc.getElementsByTagName('svg'): 131 | try: 132 | viewBox = map(float, s.attributes['viewBox'].value.split()) 133 | except: 134 | 135 | viewBox = [0,0, 136 | float(s.attributes['width'].value), 137 | float(s.attributes['height'].value)] 138 | # width="100" height="100" 139 | 140 | for s in xmldoc.getElementsByTagName('path'): 141 | d = s.attributes['d'].value 142 | paths.append(d) 143 | 144 | 145 | for s in xmldoc.getElementsByTagName('polygon'): 146 | d = s.attributes['points'].value 147 | paths.append("M"+d) 148 | 149 | for s in xmldoc.getElementsByTagName('rect'): 150 | try: x = float(s.attributes['x'].value) 151 | except: x = 0 152 | try: y = float(s.attributes['y'].value) 153 | except: y = 0 154 | 155 | w = float(s.attributes['width'].value) 156 | h = float(s.attributes['height'].value) 157 | p = ["M",x,y, x+w,y, x+w,y+h, x,y+h, x,y, "Z"] 158 | paths.append(" ".join(map(str,p))) 159 | 160 | for s in xmldoc.getElementsByTagName('circle'): 161 | cx = float(s.attributes['cx'].value) 162 | cy = float(s.attributes['cy'].value) 163 | r = float(s.attributes['r'].value) 164 | p =["M", cx-r, cy, 165 | "a", r,r, 0, 1,0, (r*2),0, 166 | "a", r,r, 0, 1,0, -(r*2),0, 167 | "Z"] 168 | paths.append(" ".join(map(str,p))) 169 | 170 | x = cx-r 171 | y = cy-r 172 | w = 2*r 173 | h = 2*r 174 | 175 | p = ["M",x,y, x+w,y, x+w,y+h, x,y+h, x,y, "Z"] 176 | #paths.append(" ".join(map(str,p))) 177 | 178 | 179 | return viewBox, paths 180 | 181 | def parse_path(path): 182 | commands = [] 183 | command = [] 184 | word = [] 185 | for c in path: 186 | if c in COMMANDS: 187 | if word: 188 | command.append(float("".join(word))) 189 | word = [] 190 | if command: 191 | commands.append(command) 192 | command = [c] 193 | elif c in " ,": 194 | if word: 195 | command.append(float("".join(word))) 196 | word = [] 197 | elif c in "+-": 198 | if word: 199 | command.append(float("".join(word))) 200 | word = [] 201 | word.append(c) 202 | else: 203 | word.append(c) 204 | if word: 205 | command.append(float("".join(word))) 206 | word = [] 207 | if command: 208 | commands.append(command) 209 | return commands 210 | 211 | def compile_path(commands): 212 | buf = [] 213 | for command in commands: 214 | buf.append(command[0]) 215 | for n in command[1:]: 216 | buf.append(str(n)) 217 | return " ".join(buf) 218 | 219 | def compute_minrec(): 220 | minx, miny, maxx, maxy = None, None, None, None 221 | pen = [0,0] 222 | rec = [None, None, None, None] 223 | def min_rec(): 224 | # min rec calculate 225 | if rec[0] is None or rec[0] > pen[0]: rec[0] = pen[0] 226 | if rec[1] is None or rec[1] > pen[1]: rec[1] = pen[1] 227 | if rec[2] is None or rec[2] < pen[0]: rec[2] = pen[0] 228 | if rec[3] is None or rec[3] < pen[1]: rec[3] = pen[1] 229 | 230 | for command in commands: 231 | op = command[0] 232 | print command 233 | if op in "VvHhAa": 234 | # account for the stupid direction commands 235 | for n in command[1:]: 236 | if op == "V": 237 | pen[0] = n 238 | elif op == "v": 239 | pen[0] += n 240 | if op == "H": 241 | pen[1] = n 242 | elif op == "h": 243 | pen[1] += n 244 | if op == "A": 245 | # arc command is insane 246 | pass 247 | elif op == "a": 248 | # arc command is insane 249 | pass 250 | 251 | min_rec() 252 | else: 253 | # all other commands 254 | for p in range((len(command)-1)/2): 255 | x = command[1+p*2] 256 | y = command[2+p*2] 257 | # move the pen 258 | if op in COMMANDS_REL: 259 | pen[0] += x 260 | pen[1] += y 261 | else: 262 | pen[0] = x 263 | pen[1] = y 264 | 265 | min_rec() 266 | print "min rectangle", rec 267 | minx, miny, maxx, maxy = rec 268 | tranx = -minx 269 | trany = -miny 270 | sizex = maxx - minx 271 | sizey = maxy - miny 272 | 273 | 274 | def do_glyph(data, glyphname, svg, baseline): 275 | """ converts a file into a svg glyph """ 276 | 277 | 278 | viewBox, paths = svg_paths(data) 279 | # font needs to be of one path 280 | path = " ".join(paths) 281 | commands = parse_path(path) 282 | 283 | tranx, trany, sizex, sizey = viewBox 284 | tranx = -tranx 285 | trany = -trany 286 | 287 | trany -= baseline 288 | 289 | size = max(sizex, sizey) 290 | scale = GSIZE/size 291 | 292 | if size - sizey > 0: 293 | trany += (size - sizey)/2 294 | if size - sizex > 0: 295 | tranx += (size - sizex)/2 296 | 297 | #print "translate", tranx, trany, "scale", scale 298 | 299 | prev_op = None 300 | for command in commands: 301 | op = command[0] 302 | 303 | if op in "Aa": 304 | # arcs require special fancy scaling 305 | command[1] *= scale 306 | command[2] *= scale 307 | # presurve flags 308 | command[4] = int(command[4]) 309 | command[5] = int(command[5]) 310 | # scale the radii 311 | command[6] *= scale 312 | command[7] *= scale 313 | else: 314 | for i,num in enumerate(command): 315 | if num == op: continue 316 | if op in COMMANDS_ABS: 317 | if op == "H": 318 | command[i] *= scale 319 | command[i] += tranx * scale 320 | elif op == "V": 321 | command[i] *= -scale 322 | command[i] += -trany * scale + GSIZE 323 | else: 324 | if i % 2 == 1: 325 | command[i] *= scale 326 | command[i] += tranx * scale 327 | else: 328 | command[i] *= -scale 329 | command[i] += -trany * scale + GSIZE 330 | else: 331 | if op in "h": 332 | command[i] *= scale 333 | elif op in "v": 334 | command[i] *= -scale 335 | else: 336 | if i % 2 == 1: 337 | command[i] *= scale 338 | else: 339 | command[i] *= -scale 340 | # special case for first relative m (its just like abs M) 341 | if op == "m" and prev_op == None: 342 | command[1] += tranx * scale 343 | command[2] += -trany * scale + GSIZE 344 | prev_op = op 345 | 346 | #commands.insert(0, ['M', tranx*scale, -trany*scale]) 347 | 348 | path = compile_path(commands) 349 | #print "final path", path 350 | svg.write(GLYPH.format(glyphname, path)) 351 | 352 | 353 | #svg.write(GLYPH.format(glyphname, path)) 354 | 355 | def gen_svg_font(glyph_files, output_dir, font_name, glyph_name, args): 356 | 357 | svg = open(output_dir + font_name + ".svg",'w') 358 | svg.write(HEADER.format(font_name, args.scale, args.ascent, args.descent)) 359 | 360 | # use the special unicode user area for char encoding 361 | index = 0 362 | #current = ord("a") 363 | for f in glyph_files: 364 | #glyphname = font_name + "-" + f.replace(".svg","").replace("_","-").replace(" ","-").lower() 365 | glyphname = htmlhex(index) 366 | 367 | data = open(f).read() 368 | #artname = chr(current) 369 | do_glyph(data, glyph_name(index), svg, args.baseline) 370 | 371 | index += 1 372 | 373 | svg.write(FOOTER) 374 | svg.flush() 375 | svg.close() 376 | 377 | 378 | def gen_css_for_font(glyph_files, output_dir, font_name, prefix, hash): 379 | css = open(output_dir + font_name + ".css",'w') 380 | css.write(CSS_HEADER.format(font_name, prefix, hash)) 381 | 382 | for index, f in enumerate(glyph_files): 383 | glyph_name = prefix + "-" + f.split("/")[-1].replace(".svg", "") 384 | css.write( 385 | '.{0}:before {{\n content: "\{1:04x}";\n}}\n'.format( 386 | glyph_name, 387 | USER_AREA + index)) 388 | 389 | 390 | def gen_html_for_font(glyph_files, output_dir, font_name, prefix): 391 | doc = open(output_dir + font_name + ".html",'w') 392 | doc.write(DOC_HEADER.format(font_name)) 393 | 394 | art_names = [] 395 | for index, f in enumerate(glyph_files): 396 | glyph_name = prefix + "-" + f.split("/")[-1].replace(".svg", "") 397 | art_name = chr(ord(DESIGNER_FONT_START_CHAR) + index) 398 | art_names.append(art_name) 399 | doc.write(" {0} ({1})
\n".format( 400 | glyph_name, art_name)) 401 | 402 | 403 | doc.write(DOC_FOOTER.format(font_name, " ".join(art_names))) 404 | 405 | 406 | def main(): 407 | parser = argparse.ArgumentParser(description=__doc__) 408 | 409 | parser.add_argument('name', type=str, help="name of the icon font you want") 410 | parser.add_argument('src', type=str, help="folder wher the svg glyphs are") 411 | parser.add_argument('dest', type=str, help="folder to output the stuff", nargs="?") 412 | parser.add_argument('--prefix', type=str, help="prefix for the css class names") 413 | 414 | parser.add_argument('--scale', type=int, help="size of chars", default=2048) 415 | parser.add_argument('--ascent', type=int, help="ascent", default=1536) 416 | parser.add_argument('--descent', type=int, help="descent", default=512) 417 | parser.add_argument('--baseline', type=int, help="adjust chars up or down", default=512) 418 | 419 | 420 | 421 | args = parser.parse_args() 422 | 423 | 424 | font_name = args.name 425 | input_dir = args.src 426 | output_dir = args.dest 427 | if not output_dir: 428 | output_dir = font_name + "/" 429 | prefix = args.prefix 430 | if not prefix: 431 | prefix = font_name 432 | 433 | # make sure output dir exists 434 | try: 435 | os.makedirs(output_dir) 436 | except: 437 | pass 438 | 439 | glyph_files = [] 440 | for f in sorted(os.listdir(input_dir)): 441 | if not f.endswith(".svg"): 442 | continue 443 | glyph_files.append(input_dir+"/"+f) 444 | 445 | # generate browser svg font 446 | gen_svg_font( 447 | glyph_files, 448 | output_dir, 449 | font_name, 450 | glyph_name=lambda i:htmlhex(i + USER_AREA), 451 | args=args, 452 | ) 453 | 454 | # generate designer svg font 455 | gen_svg_font( 456 | glyph_files, 457 | output_dir, 458 | font_name+"-designer", 459 | glyph_name=lambda i:chr(i+ord(DESIGNER_FONT_START_CHAR)), 460 | args=args 461 | ) 462 | 463 | # get file hash 464 | hash = md5.new(open(output_dir+font_name+".svg").read()).hexdigest()[:5] 465 | 466 | # generate css 467 | gen_css_for_font( 468 | glyph_files, 469 | output_dir, 470 | font_name, 471 | prefix, 472 | hash 473 | ) 474 | 475 | # generate sample html 476 | gen_html_for_font( 477 | glyph_files, 478 | output_dir, 479 | font_name, 480 | prefix 481 | ) 482 | 483 | # make ttf, woff, off, and eot browser fonts 484 | import fontforge 485 | font = fontforge.open(output_dir + font_name + ".svg") 486 | font.generate(output_dir + font_name + ".ttf") 487 | font.generate(output_dir + font_name + ".woff") 488 | font.generate(output_dir + font_name + ".otf") 489 | os.system("ttf2eot {0}.ttf > {0}.eot".format(output_dir + font_name)) 490 | 491 | # make designer ttf 492 | font = fontforge.open(output_dir + font_name + "-designer.svg") 493 | font.generate(output_dir + font_name + "-designer.ttf") 494 | 495 | 496 | if __name__ == "__main__": 497 | main() 498 | -------------------------------------------------------------------------------- /examples/nounfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | --------------------------------------------------------------------------------