diff options
author | florent <florent.pigout@gmail.com> | 2011-02-24 02:09:07 (GMT) |
---|---|---|
committer | florent <florent.pigout@gmail.com> | 2011-02-24 02:09:07 (GMT) |
commit | 1bca40986ceccc80afb2c314fe70d6cb71d1e415 (patch) | |
tree | 40361b8f042f52ae2b3a97a476450c4af63a886b | |
parent | 1229ea068cba7a91b1459cc4ebd0cb638b33b68a (diff) |
play with the graphics in default resolution 1024x468
-rw-r--r-- | activity.py | 6 | ||||
-rw-r--r-- | atoidepoc/storage/__init__.py | 0 | ||||
-rw-r--r-- | atoidepoc/storage/utils.py | 90 | ||||
-rw-r--r-- | atoidepoc/tools/image.py | 69 | ||||
-rw-r--r-- | atoidepoc/ui/screens.py | 155 | ||||
-rw-r--r-- | static/graphics/CHIEN.png | bin | 0 -> 7632 bytes | |||
-rw-r--r-- | static/graphics/CIEL.png | bin | 0 -> 150866 bytes | |||
-rw-r--r-- | static/graphics/MAISONS.png | bin | 0 -> 840816 bytes | |||
-rw-r--r-- | static/graphics/OVERLAY.png | bin | 0 -> 79574 bytes | |||
-rw-r--r-- | static/graphics/PROMENEUR.png | bin | 0 -> 26558 bytes | |||
-rw-r--r-- | static/graphics/ROUTE.png | bin | 0 -> 518733 bytes | |||
-rw-r--r-- | static/graphics/demo.png | bin | 1196 -> 0 bytes | |||
-rw-r--r-- | static/graphics/demo.svg | 232 | ||||
-rw-r--r-- | static/graphics/mask_default.png | bin | 0 -> 10747 bytes |
14 files changed, 212 insertions, 340 deletions
diff --git a/activity.py b/activity.py index ec0dacd..de710d9 100644 --- a/activity.py +++ b/activity.py @@ -3,6 +3,11 @@ import logging from gettext import gettext as _ +# gtk import +import gobject +# ... +gobject.threads_init() + # sugar import from sugar.activity import activity @@ -13,6 +18,7 @@ from atoidepoc.ui import screens, toolbar logger = logging.getLogger('atoidepoc') logger.setLevel(logging.DEBUG) + class AToiDePocActivity(activity.Activity): def __init__(self, handle): diff --git a/atoidepoc/storage/__init__.py b/atoidepoc/storage/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/atoidepoc/storage/__init__.py +++ /dev/null diff --git a/atoidepoc/storage/utils.py b/atoidepoc/storage/utils.py deleted file mode 100644 index f37b192..0000000 --- a/atoidepoc/storage/utils.py +++ /dev/null @@ -1,90 +0,0 @@ - -# python import -import logging, os - -# gtk import -import gtk - -# sugar import -from sugar.datastore import datastore - -# get application logger -logger = logging.getLogger('atoidepoc') - -ACTIVITY_NAMES = { - 'paint': 'org.laptop.Oficina' - } - - -def get_pixbuf_from_data(data, image_type=None, size=None): - # load it - if image_type: - _loader = gtk.gdk.PixbufLoader(image_type=image_type) - else: - _loader = gtk.gdk.PixbufLoader() - # size check - if size is None: - pass - else: - # parse size - _w, _h = size - # set loader size - _loader.set_size(_w, _h) - # load date - _loader.write(data) - # close loader - _loader.close() - # pix it - return _loader.get_pixbuf() - - -def get_journal_objects(activity_name): - # prepare query - _query = {'activity': ACTIVITY_NAMES[activity_name]} - # find in ds - _results, _count = datastore.find(_query, sorting='timestamp') - # return it - return _results - - -def list_info_from_journal(activity_name): - # get objects first - _objs = get_journal_objects(activity_name) - # make unique titles - _titles = {} - # return infos - for _o in _objs: - # get meta - _m = _o.get_metadata() - # get title - _t = _m['title'] - # little check - if _t in _titles: - # udpate reg - _titles[_t] += 1 - # update value to show - _t = '%s (%s)' % (_t, _titles[_t]) - # init title reg - else: - _titles[_t] = 1 - # ensure info - yield { - 'description' : _m['description'], - 'activity_id' : _m['activity_id'], - 'timestamp' : _m['timestamp'], - 'preview' : _m['preview'], - 'title' : _t, - } - - -def list_files_from_journal(activity_name): - # get objects first - _objs = get_journal_objects(activity_name) - # return paths - for _o in _objs: - # TODO open the files - yield _o.get_file_path() - - -def open_file_from_journal(activity_name, file_id): - pass diff --git a/atoidepoc/tools/image.py b/atoidepoc/tools/image.py new file mode 100644 index 0000000..f995506 --- /dev/null +++ b/atoidepoc/tools/image.py @@ -0,0 +1,69 @@ + +# python import +import struct, StringIO + +def get_image_info(path): + """Tricky method found on Internet that returns the image info from a given + raw image data. + """ + # read file + _f = open(path) + _data = _f.read() + _f.close() + # + size = len(_data) + height = None + width = None + content_type = None + + # handle GIFs + if (size >= 10) and _data[:6] in ('GIF87a', 'GIF89a'): + # Check to see if content_type is correct + content_type = 'image/gif' + w, h = struct.unpack("<HH", _data[6:10]) + width = int(w) + height = int(h) + + # See PNG 2. Edition spec (http://www.w3.org/TR/PNG/) + # Bytes 0-7 are below, 4-byte chunk length, then 'IHDR' + # and finally the 4-byte width, height + elif ((size >= 24) and _data.startswith('\211PNG\r\n\032\n') + and (_data[12:16] == 'IHDR')): + content_type = 'image/png' + w, h = struct.unpack(">LL", _data[16:24]) + width = int(w) + height = int(h) + + # Maybe this is for an older PNG version. + elif (size >= 16) and _data.startswith('\211PNG\r\n\032\n'): + # Check to see if we have the right content type + content_type = 'image/png' + w, h = struct.unpack(">LL", _data[8:16]) + width = int(w) + height = int(h) + + # handle JPEGs + elif (size >= 2) and _data.startswith('\377\330'): + content_type = 'image/jpeg' + jpeg = StringIO.StringIO(_data) + jpeg.read(2) + b = jpeg.read(1) + try: + while (b and ord(b) != 0xDA): + while (ord(b) != 0xFF): b = jpeg.read(1) + while (ord(b) == 0xFF): b = jpeg.read(1) + if (ord(b) >= 0xC0 and ord(b) <= 0xC3): + jpeg.read(3) + h, w = struct.unpack(">HH", jpeg.read(4)) + break + else: + jpeg.read(int(struct.unpack(">H", jpeg.read(2))[0])-2) + b = jpeg.read(1) + width = int(w) + height = int(h) + except struct.error: + pass + except ValueError: + pass + + return content_type, width, height diff --git a/atoidepoc/ui/screens.py b/atoidepoc/ui/screens.py index 2db1f99..0371c45 100644 --- a/atoidepoc/ui/screens.py +++ b/atoidepoc/ui/screens.py @@ -1,6 +1,6 @@ # python import -import logging, os +import logging, os, threading, time from gettext import gettext as _ # gtk import @@ -11,7 +11,7 @@ from sugar.activity import activity from sugar.graphics import style # atoidepoc import -from atoidepoc.tools import sound, storage +from atoidepoc.tools import image, sound, storage # get application logger logger = logging.getLogger('atoidepoc') @@ -105,6 +105,64 @@ class ScreenBrowserSounds(ScreenBrowser): ScreenBrowser.__init__(self, toolbar, title=_('Sounds'), _type='sound') +PROMENEUR_KEYS = [(20, 12), (40, 12), (60, 12), (80, 12), (100, 12), (80, 12), + (100, 12), (120, 12), (100, 12), (80, 12), (60, 12), (80, 12), + (100, 12), (120, 12), (140, 12), (160, 12), (120, 12), (200, 12), + (120, 12), (200, 12), (220, 12), (220, 12), (220, 12), (220, 12)] + +CHIEN_KEYS = [(80, 54), (100, 32), (80, 54), (100, 32), (120, 54), (140, 32), + (140, 54), (160, 32), (200, 54), (200, 32), (220, 54), (240, 32), + (260, 54), (240, 32), (220, 54), (200, 32), (180, 54), (160, 32), + (200, 54), (200, 32), (220, 54), (240, 32), (160, 54), (280, 32)] + +MAISONS_KEYS = [(0, 0), (0, 2), (2, 4), (0, 2), (2, 0), (2, 2), + (0, 4), (0, 6), (-2, 8), (0, 6), (-2, 4), (0, 2), + (0, 2), (2, 2), (0, 0), (-2, 2), (0, 4), (2, 6), + (0, 8), (0, 6), (0, 4), (-2, 2), (-2, 2), (0, 0)] + +CIEL_KEYS = [(0, -9) for _i in range(24)] + +BOTTOM_KEYS = [(0, 16) for _i in range(24)] + +DEFAULT_KEYS = [(0, 0) for _i in range(24)] + +ALL_KEYS = { + 'CIEL': CIEL_KEYS, + 'MAISONS': MAISONS_KEYS, + 'ROUTE': DEFAULT_KEYS, + 'PROMENEUR': PROMENEUR_KEYS, + 'CHIEN': CHIEN_KEYS, + 'OVERLAY': DEFAULT_KEYS, + 'mask_default': DEFAULT_KEYS, + } + +NAMES = [ + 'CIEL', + 'MAISONS', + 'ROUTE', + 'PROMENEUR', + 'CHIEN', + 'OVERLAY', + 'mask_default', + ] + + +class ThreadMove(threading.Thread): + + def __init__(self, fixed, filename): + # init parent + threading.Thread.__init__(self) + # ... + self._fixed = fixed + self._filename = filename + + def run(self): + for _align in ALL_KEYS[self._filename]: + # ... + self._fixed._move_image(self._filename, align=_align) + # ... + time.sleep(1) + class ScreenStory(gtk.Fixed): @@ -113,36 +171,79 @@ class ScreenStory(gtk.Fixed): gtk.Fixed.__init__(self) # keep toolbar self.toolbar = toolbar + # init image dict + self.__graphics = dict() + self.__sizes = dict() + self.__positions = dict() + # keep some info + self._screen_height = gtk.gdk.screen_height() + self._screen_width = gtk.gdk.screen_width() # render self._render() # and show self._show() + # do anim + for _n in NAMES: + self._anim(_n) + + def _anim(self, filename): + # init thread + _t = ThreadMove(self, filename) + # start it + _t.start() def _render(self): # png check - self._add_image('demo.png', align=(0,0)) - self._add_image('demo.png', align=(200, 0), size=(100, 100)) - # png check - self._add_image('demo.svg', align=(0, 200)) - self._add_image('demo.svg', align=(200, 200), size=(100, 100)) + self._add_image('CIEL', align=(0, -10)) + self._add_image('MAISONS', align=(0, 0)) + self._add_image('ROUTE', align=(0, 16)) + self._add_image('PROMENEUR', align=(0, 16)) + self._add_image('CHIEN', align=(0, 16)) + self._add_image('OVERLAY', align=(0, 0)) + # add border + self._add_image('mask_default', align=(0, 0)) + + def _get_image_path(self, filename): + return os.path.join(activity.get_bundle_path(), + 'static', 'graphics', '%s.png' % filename) + + def _update_x_y(self, width, height, x, y): + # update x + x = ((gtk.gdk.screen_width() - width) / 2) + x + # update y + y = ((gtk.gdk.screen_height() - height - + 88) / 2) + y + # return it + return x, y - def _add_image(self, filename, align=None, size=None): - # get graphics path - _path = os.path.join(activity.get_bundle_path(), - 'static', 'graphics', filename) - # add a picture here - _image = gtk.Image() + def _move_image(self, filename, align=None): + # get graphic from dict + _image = self.__graphics[filename] # set alignment if align is None: - _x = 0 - _y = 0 + # use current position by default + _x , _y = self.__positions[filename] else: # parse align value _x, _y = align + # get image size + _w, _h = self.__sizes[filename] + # update x, y + _x, _y = self._update_x_y(_w, _h, _x, _y) + self.__positions[filename] = (_x, _y) + # move + self.move(_image, _x, _y) + + def _add_image(self, filename, align=None, size=None): + # get graphics path + _path = self._get_image_path(filename) + # add a picture here + _image = gtk.Image() # set size if size is None: # set file _image.set_from_file(_path) + # get file size + _c, _w, _h = image.get_image_info(_path) else: # parse size value _w, _h = size @@ -151,16 +252,34 @@ class ScreenStory(gtk.Fixed): # do resize and set image _image.set_from_pixbuf( _pixbuf.scale_simple(_w, _h, gtk.gdk.INTERP_BILINEAR)) - # TODO manage cb for dnd + # set alignment + if align is None: + _x = 0 + _y = 0 + else: + # parse align value + _x, _y = align + # TODO manage cb for click or dnd # ... # show _image.show() + # update graphic dict + self.__graphics[filename] = _image + self.__sizes[filename] = (_w, _h) + # update x, y + _x, _y = self._update_x_y(_w, _h, _x, _y) + self.__positions[filename] = (_x, _y) # add self.put(_image, _x, _y) def _show(self): # show self self.show() + + # DEBUG + logger.debug('[screen_story] _show - width: %s' % gtk.gdk.screen_width()) + # DEBUG + # update toolbar self.toolbar.activity.set_canvas(self) @@ -202,8 +321,8 @@ class ScreenPlayerSounds(ScreenPlayer): def render(self): # init 2 players - _s_player_1 = sound.Player(soundfile='/home/florent/shared/demo1.ogg') - _s_player_2 = sound.Player(soundfile='/home/florent/shared/demo2.ogg') + _s_player_1 = sound.Player(soundfile='/home/sugar/shared/demo1.ogg') + _s_player_2 = sound.Player(soundfile='/home/sugar/shared/demo2.ogg') # get duration _d1 = _s_player_1.get_duration() diff --git a/static/graphics/CHIEN.png b/static/graphics/CHIEN.png Binary files differnew file mode 100644 index 0000000..ebe9d02 --- /dev/null +++ b/static/graphics/CHIEN.png diff --git a/static/graphics/CIEL.png b/static/graphics/CIEL.png Binary files differnew file mode 100644 index 0000000..6a2958f --- /dev/null +++ b/static/graphics/CIEL.png diff --git a/static/graphics/MAISONS.png b/static/graphics/MAISONS.png Binary files differnew file mode 100644 index 0000000..64a9dd0 --- /dev/null +++ b/static/graphics/MAISONS.png diff --git a/static/graphics/OVERLAY.png b/static/graphics/OVERLAY.png Binary files differnew file mode 100644 index 0000000..d539424 --- /dev/null +++ b/static/graphics/OVERLAY.png diff --git a/static/graphics/PROMENEUR.png b/static/graphics/PROMENEUR.png Binary files differnew file mode 100644 index 0000000..f3a8788 --- /dev/null +++ b/static/graphics/PROMENEUR.png diff --git a/static/graphics/ROUTE.png b/static/graphics/ROUTE.png Binary files differnew file mode 100644 index 0000000..3442fbd --- /dev/null +++ b/static/graphics/ROUTE.png diff --git a/static/graphics/demo.png b/static/graphics/demo.png Binary files differdeleted file mode 100644 index af96edc..0000000 --- a/static/graphics/demo.png +++ /dev/null diff --git a/static/graphics/demo.svg b/static/graphics/demo.svg deleted file mode 100644 index bdfad6f..0000000 --- a/static/graphics/demo.svg +++ /dev/null @@ -1,232 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> - -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - version="1.0" - id="svg2" - sodipodi:version="0.32" - inkscape:version="0.47 r22583" - sodipodi:docname="activity-atoidepoc.svg" - width="55" - height="55" - inkscape:output_extension="org.inkscape.output.svg.inkscape"> - <metadata - id="metadata371"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <sodipodi:namedview - inkscape:window-height="882" - inkscape:window-width="1233" - inkscape:pageshadow="2" - inkscape:pageopacity="0.0" - guidetolerance="10.0" - gridtolerance="10.0" - objecttolerance="10.0" - borderopacity="1.0" - bordercolor="#666666" - pagecolor="#ffffff" - id="base" - inkscape:zoom="4.2923284" - inkscape:cx="63.342591" - inkscape:cy="51.710699" - inkscape:window-x="168" - inkscape:window-y="24" - inkscape:current-layer="svg2" - width="210mm" - height="40mm" - units="mm" - showgrid="false" - inkscape:window-maximized="0" /> - <defs - id="defs4"> - <inkscape:perspective - sodipodi:type="inkscape:persp3d" - inkscape:vp_x="0 : 71.887497 : 1" - inkscape:vp_y="0 : 1000 : 0" - inkscape:vp_z="486.04999 : 71.887497 : 1" - inkscape:persp3d-origin="243.02499 : 47.924998 : 1" - id="perspective46" /> - <linearGradient - id="linearGradient2795"> - <stop - style="stop-color: rgb(184, 184, 184); stop-opacity: 0.498039;" - offset="0" - id="stop2797" /> - <stop - style="stop-color: rgb(127, 127, 127); stop-opacity: 0;" - offset="1" - id="stop2799" /> - </linearGradient> - <linearGradient - id="linearGradient2787"> - <stop - style="stop-color: rgb(127, 127, 127); stop-opacity: 0.5;" - offset="0" - id="stop2789" /> - <stop - style="stop-color: rgb(127, 127, 127); stop-opacity: 0;" - offset="1" - id="stop2791" /> - </linearGradient> - <linearGradient - id="linearGradient3676"> - <stop - style="stop-color: rgb(178, 178, 178); stop-opacity: 0.5;" - offset="0" - id="stop3678" /> - <stop - style="stop-color: rgb(179, 179, 179); stop-opacity: 0;" - offset="1" - id="stop3680" /> - </linearGradient> - <linearGradient - id="linearGradient3236"> - <stop - style="stop-color: rgb(244, 244, 244); stop-opacity: 1;" - offset="0" - id="stop3244" /> - <stop - style="stop-color: white; stop-opacity: 1;" - offset="1" - id="stop3240" /> - </linearGradient> - <linearGradient - id="linearGradient4671"> - <stop - style="stop-color: rgb(255, 212, 59); stop-opacity: 1;" - offset="0" - id="stop4673" /> - <stop - style="stop-color: rgb(255, 232, 115); stop-opacity: 1;" - offset="1" - id="stop4675" /> - </linearGradient> - <linearGradient - id="linearGradient4689"> - <stop - style="stop-color: rgb(90, 159, 212); stop-opacity: 1;" - offset="0" - id="stop4691" /> - <stop - style="stop-color: rgb(48, 105, 152); stop-opacity: 1;" - offset="1" - id="stop4693" /> - </linearGradient> - <linearGradient - x1="224.23996" - y1="144.75717" - x2="-65.308502" - y2="144.75717" - id="linearGradient2987" - xlink:href="#linearGradient4671" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(100.27,99.6112)" /> - <linearGradient - x1="172.94208" - y1="77.475983" - x2="26.670298" - y2="76.313133" - id="linearGradient2990" - xlink:href="#linearGradient4689" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(100.27,99.6112)" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4689" - id="linearGradient2587" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(100.27,99.6112)" - x1="172.94208" - y1="77.475983" - x2="26.670298" - y2="76.313133" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4671" - id="linearGradient2589" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(100.27,99.6112)" - x1="224.23996" - y1="144.75717" - x2="-65.308502" - y2="144.75717" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4689" - id="linearGradient2248" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(100.27,99.6112)" - x1="172.94208" - y1="77.475983" - x2="26.670298" - y2="76.313133" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4671" - id="linearGradient2250" - gradientUnits="userSpaceOnUse" - gradientTransform="translate(100.27,99.6112)" - x1="224.23996" - y1="144.75717" - x2="-65.308502" - y2="144.75717" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4671" - id="linearGradient2255" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.562541,0,0,0.567972,-11.5974,-7.60954)" - x1="224.23996" - y1="144.75717" - x2="-65.308502" - y2="144.75717" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4689" - id="linearGradient2258" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.562541,0,0,0.567972,-11.5974,-7.60954)" - x1="172.94208" - y1="76.176224" - x2="26.670298" - y2="76.313133" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient2795" - id="radialGradient2801" - cx="61.518883" - cy="132.28575" - fx="61.518883" - fy="132.28575" - r="29.036913" - gradientTransform="matrix(1,0,0,0.177966,0,108.743)" - gradientUnits="userSpaceOnUse" /> - </defs> - <g - id="g2847" - transform="matrix(0.46766264,0,0,0.46766264,-1.1078811,-1.5517981)"> - <path - id="path1948" - d="m 60.510156,6.3979729 c -4.583653,0.021298 -8.960939,0.4122177 -12.8125,1.09375 C 36.35144,9.4962267 34.291407,13.691825 34.291406,21.429223 l 0,10.21875 26.8125,0 0,3.40625 -26.8125,0 -10.0625,0 c -7.792459,0 -14.6157592,4.683717 -16.7500002,13.59375 -2.46182,10.212966 -2.5710151,16.586023 0,27.25 1.9059283,7.937852 6.4575432,13.593748 14.2500002,13.59375 l 9.21875,0 0,-12.25 c 0,-8.849902 7.657144,-16.656248 16.75,-16.65625 l 26.78125,0 c 7.454951,0 13.406253,-6.138164 13.40625,-13.625 l 0,-25.53125 c 0,-7.266339 -6.12998,-12.7247775 -13.40625,-13.9375001 -4.605987,-0.7667253 -9.385097,-1.1150483 -13.96875,-1.09375 z m -14.5,8.2187501 c 2.769547,0 5.03125,2.298646 5.03125,5.125 -2e-6,2.816336 -2.261703,5.09375 -5.03125,5.09375 -2.779476,-1e-6 -5.03125,-2.277415 -5.03125,-5.09375 -1e-6,-2.826353 2.251774,-5.125 5.03125,-5.125 z" - style="fill:#000000;fill-opacity:1" /> - <path - id="path1950" - d="m 91.228906,35.054223 0,11.90625 c 0,9.230755 -7.825895,16.999999 -16.75,17 l -26.78125,0 c -7.335833,0 -13.406249,6.278483 -13.40625,13.625 l 0,25.531247 c 0,7.26634 6.318588,11.54032 13.40625,13.625 8.487331,2.49561 16.626237,2.94663 26.78125,0 6.750155,-1.95439 13.406253,-5.88761 13.40625,-13.625 l 0,-10.218747 -26.78125,0 0,-3.40625 26.78125,0 13.406254,0 c 7.79246,0 10.69625,-5.435408 13.40624,-13.59375 2.79933,-8.398886 2.68022,-16.475776 0,-27.25 -1.92578,-7.757441 -5.60387,-13.59375 -13.40624,-13.59375 l -10.062504,0 z m -15.0625,64.65625 c 2.779478,3e-6 5.03125,2.277417 5.03125,5.093747 -2e-6,2.82635 -2.251775,5.125 -5.03125,5.125 -2.76955,0 -5.03125,-2.29865 -5.03125,-5.125 2e-6,-2.81633 2.261697,-5.093747 5.03125,-5.093747 z" - style="fill:#000000;fill-opacity:1" /> - </g> -</svg> diff --git a/static/graphics/mask_default.png b/static/graphics/mask_default.png Binary files differnew file mode 100644 index 0000000..5e9c1d1 --- /dev/null +++ b/static/graphics/mask_default.png |