diff options
Diffstat (limited to 'chat/smilies.py')
-rw-r--r-- | chat/smilies.py | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/chat/smilies.py b/chat/smilies.py new file mode 100644 index 0000000..c3cc244 --- /dev/null +++ b/chat/smilies.py @@ -0,0 +1,152 @@ +# Copyright 2010, Mukesh Gupta +# Copyright 2010, Aleksey Lim +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +import os +from os.path import join, exists +from gettext import gettext as _ + +import gtk +import cairo + +from sugar.graphics import style +from sugar.activity.activity import get_activity_root, get_bundle_path + + +THEME = [ + ('smile', _('Smile'), [':-)', ':)']), + ('wink', _('Winking'), [';-)', ';)']), + ('confused', _('Confused'), [':-/', ':/']), + ('sad', _('Sad'), [':-(', ':(']), + ('grin', _('Grin'), [':-D', ':D']), + ('neutral', _('Neutral'), (':-|', ':|')), + ('shock', _('Shock'), [':-O', ':O', '=-O', '=O']), + ('cool', _('Cool'), ['B-)', 'B)', '8-)', '8)']), + ('tongue', _('Tongue'), [':-P', ':P']), + ('blush', _('Blushing'), [':">']), + ('weep', _('Weeping'), [":'-(", ":'("]), + ('angel', _('Angel'), ['O-)', 'O)', 'O:-)', 'O:)']), + ('shutup', _("Don't tell anyone"), (':-$', ':-$')), + ('angry', _('Angry'), ('x-(', 'x(', 'X-(', 'x-(')), + ('devil', _('Devil'), ('>:>', '>:)')), + ('nerd', _('Nerd'), (':-B', ':B')), + ('kiss', _('Kiss'), (':-*', ':*')), + ('laugh', _('Laughing'), [':))']), + ('sleep', _('Sleepy'), ['I-)']), + ('sick', _('Sick'), [':-&']), + ('eyebrow', _('Raised eyebrows'), ['/:)']), + ] + +SMILIES_SIZE = int(style.STANDARD_ICON_SIZE * 0.75) + +_catalog = None + + +def init(): + """Initialise smilies data.""" + global _catalog + + if _catalog is not None: + return + _catalog = {} + + png_dir = join(get_activity_root(), 'data', 'icons', 'smilies') + svg_dir = join(get_bundle_path(), 'icons', 'smilies') + + if not exists(png_dir): + os.makedirs(png_dir) + + for index, (name, hint, codes) in enumerate(THEME): + png_path = join(png_dir, name + '.png') + + for i in codes: + _catalog[i] = png_path + THEME[index] = (png_path, hint, codes) + + if not exists(png_path): + pixbuf = _from_svg_at_size( + join(svg_dir, name + '.svg'), + SMILIES_SIZE, SMILIES_SIZE, None, True) + pixbuf.save(png_path, 'png') + + +def parse(text): + """Initialise smilies data. + + :param text: + string to parse for smilies + :returns: + array of string parts and ciaro surfaces + + """ + result = [text] + + for smiley in sorted(_catalog.keys(), lambda x, y: cmp(len(y), len(x))): + smiley_surface = cairo.ImageSurface.create_from_png(_catalog[smiley]) + new_result = [] + + for word in result: + if isinstance(word, cairo.ImageSurface): + new_result.append(word) + else: + parts = word.split(smiley) + for i in parts[:-1]: + new_result.append(i) + new_result.append(smiley_surface) + new_result.append(parts[-1]) + + result = new_result + + return result + + +def _from_svg_at_size(filename=None, width=None, height=None, handle=None, + keep_ratio=True): + """Scale and load SVG into pixbuf.""" + import rsvg + + if not handle: + handle = rsvg.Handle(filename) + + dimensions = handle.get_dimension_data() + icon_width = dimensions[0] + icon_height = dimensions[1] + if icon_width != width or icon_height != height: + ratio_width = float(width) / icon_width + ratio_height = float(height) / icon_height + + if keep_ratio: + ratio = min(ratio_width, ratio_height) + if ratio_width != ratio: + ratio_width = ratio + width = int(icon_width * ratio) + elif ratio_height != ratio: + ratio_height = ratio + height = int(icon_height * ratio) + else: + ratio_width = 1 + ratio_height = 1 + + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + context = cairo.Context(surface) + context.scale(ratio_width, ratio_height) + handle.render_cairo(context) + + loader = gtk.gdk.pixbuf_loader_new_with_mime_type('image/png') + surface.write_to_png(loader) + loader.close() + + return loader.get_pixbuf() |