├── screenshot.png ├── iconfont_sample.ttf ├── .gitignore ├── iconfont_sample.fontd ├── LICENSE ├── tests.py ├── __init__.py ├── README.md ├── iconfont_sample.css └── iconfonts.py /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy-garden/garden.iconfonts/HEAD/screenshot.png -------------------------------------------------------------------------------- /iconfont_sample.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kivy-garden/garden.iconfonts/HEAD/iconfont_sample.ttf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.swp 3 | *.py~ 4 | *.zip 5 | *.rar 6 | *.html~ 7 | *.htm~ 8 | *.css~ 9 | !.gitignore 10 | *.profile 11 | -------------------------------------------------------------------------------- /iconfont_sample.fontd: -------------------------------------------------------------------------------- 1 | {"icon-plus-circled": 59395, "icon-spin6": 59393, "icon-doc-text-inv": 59396, "icon-emo-happy": 59392, "icon-comment": 59397, "icon-users": 59394} -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2015 Kivy Team and other contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /tests.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import iconfonts 3 | 4 | 5 | class Tests(unittest.TestCase): 6 | 7 | def test_create_fontdict_file(self): 8 | res = iconfonts.create_fontdict_file("iconfont_sample.css", 9 | 'iconfont_sample.fontd') 10 | self.assertEqual(res, {'icon-plus-circled': 59395, 'icon-spin6': 59393, 11 | 'icon-doc-text-inv': 59396, 12 | 'icon-emo-happy': 59392, 13 | 'icon-comment': 59397, 'icon-users': 59394}) 14 | 15 | def test_register(self): 16 | iconfonts.register('name', 'iconfont_sample.ttf', 17 | 'iconfont_sample.fontd') 18 | self.assertEqual(iconfonts._register['name'][0], 'iconfont_sample.ttf') 19 | 20 | def test_icon(self): 21 | iconfonts.register('name', 'iconfont_sample.ttf', 22 | 'iconfont_sample.fontd') 23 | r = iconfonts.icon('icon-comment') 24 | self.assertEqual( 25 | "[font=iconfont_sample.ttf]%s[/font]" % (unichr(59397)), r) 26 | r = iconfonts.icon('icon-comment', 20) 27 | self.assertEqual( 28 | "[size=20][font=iconfont_sample.ttf]%s[/font][/size]" % 29 | (unichr(59397)), r) 30 | 31 | 32 | if __name__ == '__main__': 33 | unittest.main() 34 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Kivy-iconfonts 3 | ============== 4 | 5 | Simple helper functions to make easier to use icon fonts in Labels and derived 6 | widgets. 7 | """ 8 | from .iconfonts import * 9 | 10 | 11 | if __name__ == '__main__': 12 | from kivy.lang import Builder 13 | from kivy.base import runTouchApp 14 | from kivy.animation import Animation 15 | from os.path import join, dirname 16 | 17 | kv = """ 18 | #: import icon iconfonts.icon 19 | BoxLayout: 20 | Button: 21 | markup: True 22 | text: "%s"%(icon('icon-comment', 32)) 23 | Button: 24 | markup: True 25 | text: "%s"%(icon('icon-emo-happy', 64)) 26 | 27 | Button: 28 | markup: True 29 | text: "%s Text"%(icon('icon-plus-circled', 24)) 30 | 31 | Button: 32 | markup: True 33 | text: "%s"%(icon('icon-doc-text-inv', 64, 'ff3333')) 34 | 35 | Label: 36 | id: _anim 37 | markup: True 38 | text: "%s"%(icon('icon-spin6', 32)) 39 | font_color: 1, 0, 0, 1 40 | p: 0 41 | canvas: 42 | Clear 43 | PushMatrix 44 | Rotate: 45 | angle: -self.p 46 | origin: self.center_x , self.center_y 47 | Rectangle: 48 | size: (32, 32) 49 | pos: self.center_x - 16, self.center_y - 16 50 | texture: self.texture 51 | PopMatrix 52 | """ 53 | 54 | register('default_font', 'iconfont_sample.ttf', 55 | join(dirname(__file__), 'iconfont_sample.fontd')) 56 | 57 | root = Builder.load_string(kv) 58 | an = Animation(p=360, duration=2) + Animation(p=0, duration=0) 59 | an.repeat = True 60 | an.start(root.ids['_anim']) 61 | runTouchApp(root) 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Screenshot](https://github.com/jeysonmc/garden.iconfonts/blob/master/screenshot.png "Scrennshot") 2 | 3 | 4 | Kivy-iconfonts 5 | ============== 6 | 7 | Simple helper functions to make easier to use icon fonts in Labels and derived widgets 8 | 9 | Usage 10 | ===== 11 | 12 | Once you have a .fontd file (see below) for your ttf iconfont generated you can use it like this: 13 | 14 | In your main.py register your font: 15 | ```python 16 | iconfonts.register('default_font', 'iconfont_sample.ttf', 'iconfont_sample.fontd') 17 | ``` 18 | 19 | In your kv file or string: 20 | ```yaml 21 | #: import icon kivy.garden.iconfonts.icon 22 | Button: 23 | markup: True # Always turn markup on 24 | text: "%s"%(icon('icon-comment')) 25 | ``` 26 | See __init__.py for another example. 27 | 28 | Generating a fontd file 29 | ===================== 30 | 31 | A .fontd file is just a python dictionary filled with icon_code: unicode_value entries. This information is extracted from a css file (all iconfonts packages I've seen have one). 32 | 33 | **Example with Font-Awesome** 34 | 35 | 1. Download Font-Awesome (http://fortawesome.github.io/Font-Awesome/) 36 | 2. Copy both the TTF and CSS files (fonts/fontawesome-webfont.ttf and css/font-awesome.css) to your project 37 | 3. Create and execute a python script to generate your fontd file: 38 | ```python 39 | iconfonts.create_fontdict_file('font-awesome.css', 'font-awesome.fontd') 40 | ``` 41 | 4. If everything went well your font dictionary file exists. You can delete the css file (font-awesome.css) 42 | 43 | 44 | More IconFonts 45 | ============== 46 | - http://fortawesome.github.io/Font-Awesome/ 47 | - http://fontello.com/ 48 | - https://icomoon.io 49 | 50 | LICENSE 51 | ======= 52 | 53 | MIT (except sample font that I got from http://fontello.com) 54 | 55 | 56 | Credits 57 | ======= 58 | 59 | Author: Jeyson Molina 60 | -------------------------------------------------------------------------------- /iconfont_sample.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'iconfont_sample'; 3 | src: url('../font/iconfont_sample.eot?73553284'); 4 | src: url('../font/iconfont_sample.eot?73553284#iefix') format('embedded-opentype'), 5 | url('../font/iconfont_sample.woff?73553284') format('woff'), 6 | url('../font/iconfont_sample.ttf?73553284') format('truetype'), 7 | url('../font/iconfont_sample.svg?73553284#iconfont_sample') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | /* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ 12 | /* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ 13 | /* 14 | @media screen and (-webkit-min-device-pixel-ratio:0) { 15 | @font-face { 16 | font-family: 'iconfont_sample'; 17 | src: url('../font/iconfont_sample.svg?73553284#iconfont_sample') format('svg'); 18 | } 19 | } 20 | */ 21 | 22 | [class^="icon-"]:before, [class*=" icon-"]:before { 23 | font-family: "iconfont_sample"; 24 | font-style: normal; 25 | font-weight: normal; 26 | speak: none; 27 | 28 | display: inline-block; 29 | text-decoration: inherit; 30 | width: 1em; 31 | margin-right: .2em; 32 | text-align: center; 33 | /* opacity: .8; */ 34 | 35 | /* For safety - reset parent styles, that can break glyph codes*/ 36 | font-variant: normal; 37 | text-transform: none; 38 | 39 | /* fix buttons height, for twitter bootstrap */ 40 | line-height: 1em; 41 | 42 | /* Animation center compensation - margins should be symmetric */ 43 | /* remove if not needed */ 44 | margin-left: .2em; 45 | 46 | /* you can be more comfortable with increased icons size */ 47 | /* font-size: 120%; */ 48 | 49 | /* Uncomment for 3D effect */ 50 | /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ 51 | } 52 | 53 | .icon-emo-happy:before { content: '\e800'; } /* '' */ 54 | .icon-spin6:before { content: '\e801'; } /* '' */ 55 | .icon-users:before { content: '\e802'; } /* '' */ 56 | .icon-plus-circled:before { content: '\e803'; } /* '' */ 57 | .icon-doc-text-inv:before { content: '\e804'; } /* '' */ 58 | .icon-comment:before { content: '\e805'; } /* '' */ -------------------------------------------------------------------------------- /iconfonts.py: -------------------------------------------------------------------------------- 1 | import re 2 | import json 3 | from collections import OrderedDict 4 | from kivy.compat import PY2 5 | 6 | _register = OrderedDict() 7 | 8 | if not PY2: 9 | unichr = chr 10 | 11 | 12 | def register(name, ttf_fname, fontd_fname): 13 | """Register an Iconfont 14 | :param name: font name identifier. 15 | :param ttf_fname: ttf filename (path) 16 | :param fontd_fname: fontdic filename. (See create_fontdic) 17 | """ 18 | with open(fontd_fname, 'r') as f: 19 | fontd = json.loads(f.read()) 20 | _register[name] = ttf_fname, fontd_fname, fontd 21 | 22 | 23 | def icon(code, size=None, color=None, font_name=None): 24 | """ Gets an icon from iconfont. 25 | :param code: Icon codename (ex: 'icon-name') 26 | :param size: Icon size 27 | :param color: Icon color 28 | :param font_name: Registered font name. If None first one is used. 29 | :returns: icon text (with markups) 30 | """ 31 | font = list(_register.keys())[0] if font_name is None else font_name 32 | font_data = _register[font] 33 | s = "[font=%s]%s[/font]" % (font_data[0], unichr(font_data[2][code])) 34 | if size is not None: 35 | s = "[size=%s]%s[/size]" % (size, s) 36 | if color is not None: 37 | s = "[color=%s]%s[/color]" % (color, s) 38 | 39 | return s 40 | 41 | 42 | def create_fontdict_file(css_fname, output_fname): 43 | """Creates a font dictionary file. Basically creates a dictionary filled 44 | with icon_code: unicode_value entries 45 | obtained from a CSS file. 46 | :param css_fname: CSS filename where font's rules are declared. 47 | :param output_fname: Fontd file destination 48 | """ 49 | with open(css_fname, 'r') as f: 50 | data = f.read() 51 | res = _parse(data) 52 | with open(output_fname, 'w') as o: 53 | o.write(json.dumps(res)) 54 | return res 55 | 56 | 57 | def _parse(data): 58 | # find start index where icons rules start 59 | pat_start = re.compile('}.+content:', re.DOTALL) 60 | rules_start = [x for x in re.finditer(pat_start, data)][0].start() 61 | data = data[rules_start:] # crop data 62 | data = data.replace("\\", '0x') # replace unicodes 63 | data = data.replace("'", '"') # replace quotes 64 | # iterate rule indices and extract value 65 | pat_keys = re.compile('[a-zA-Z0-9_-]+:before') 66 | res = dict() 67 | for i in re.finditer(pat_keys, data): 68 | start = i.start() 69 | end = data.find('}', start) 70 | key = i.group().replace(':before', '') 71 | try: 72 | value = int(data[start:end].split('"')[1], 0) 73 | except (IndexError, ValueError): 74 | continue 75 | res[key] = value 76 | return res 77 | 78 | --------------------------------------------------------------------------------