From 5e5bade88013f5881147918de59f050eac9cb562 Mon Sep 17 00:00:00 2001 From: "Jan D. Behrens" Date: Wed, 29 Aug 2012 18:19:33 +0200 Subject: [PATCH] More fine-tuning to the "minimal" skin; added options to enable/disable centering of some elements --- xonstat/batch/badges/gen_badges.py | 25 +- xonstat/batch/badges/img/overlay_minimal.png | Bin 314 -> 330 bytes xonstat/batch/badges/img/overlay_minimal.xcf | Bin 22855 -> 24089 bytes xonstat/batch/badges/render.py | 587 ------------------- xonstat/batch/badges/skin.py | 59 +- 5 files changed, 63 insertions(+), 608 deletions(-) delete mode 100644 xonstat/batch/badges/render.py diff --git a/xonstat/batch/badges/gen_badges.py b/xonstat/batch/badges/gen_badges.py index 3dfc196..4465ead 100644 --- a/xonstat/batch/badges/gen_badges.py +++ b/xonstat/batch/badges/gen_badges.py @@ -39,26 +39,37 @@ skin_minimal = Skin( "minimal", width = 560, height = 40, num_gametypes = 3, - gametype_pos = (25,30), - gametype_text = "%s :", - gametype_width = 115, + gametype_pos = (8,30), + gametype_color = (0.8, 0.8, 0.8), + gametype_text = "%s:", + gametype_width = 112, gametype_fontsize = 10, + gametype_center = False, elo_pos = (75,30), elo_text = "Elo %.0f", - elo_color = (1.0, 1.0, 0.6), + elo_color = (0.9, 0.9, 0.7), + elo_center = True, rank_pos = None, - nostats_pos = (80,30), + nostats_pos = (75,30), nostats_fontsize = 10, nostats_angle = 0, nostats_text = "no stats!", + nostats_color = (0.8, 0.3, 0.3), + nostats_center = True, kdr_pos = (392,15), + kdr_colortop = (0.1, 0.8, 0.1), + kdr_colormid = (0.6, 0.6, 0.1), + kdr_colorbot = (0.8, 0.1, 0.1), kills_pos = None, deaths_pos = None, winp_pos = (508,15), wins_pos = None, + winp_colortop = (0.1, 0.6, 0.6), + winp_colormid = (0.2, 0.6, 0.2), + winp_colorbot = (0.6, 0.6, 0.1), loss_pos = None, - ptime_pos = (458,30), - ptime_color = (0.8, 0.8, 0.9), + ptime_pos = (451,30), + ptime_color = (0.7, 0.7, 0.9), ) diff --git a/xonstat/batch/badges/img/overlay_minimal.png b/xonstat/batch/badges/img/overlay_minimal.png index d91b5b2f461d3bb4a45f76d0e8476fc5e8ced3e5..1f39a7128078f0d1c3e100abd2de0c7ca005ec8b 100644 GIT binary patch delta 153 zcmdnRbc$(0BD;W~_0jvcjVESks4ew$aSW-r_4b;fXoCZf%R%cHS4SH~2LF|YMOs0R zndA(V6Sx0Np19FGmf?f1u~Jx?+_H-Gt8Uf4aGv*f{ceBn1GQ$t3=B+c3=Rhv7&s(g o6aynOhzFt+65tdI55os_amP=BJ{qUi>o5R;r>mdKI;Vst01I?3g#Z8m delta 140 zcmX@bw2Ns%B0Haoa*`GQ%83~oic>vZ978H@y}f2A$e_T(u(3)1&4R^!SsRshBsaJm z@|S0vcu;rZ1+Jh2v)$72BpJ?yTn%D;H&cj#fsKvfzySsZ2?-d*z|0KdfvAK8IK{)m b@L@8W#X%OIP4D=u8Gyjk)z4*}Q$iB}+iNMZ diff --git a/xonstat/batch/badges/img/overlay_minimal.xcf b/xonstat/batch/badges/img/overlay_minimal.xcf index bed5ef22a5466fec330b52b7aa958a01b6e0816f..fefa526d855e10ee2c67dc021aaa68fe3353e7fd 100644 GIT binary patch literal 24089 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 Wj)YIqX47|!X&z{-8&Cg(vH5RERFa|q diff --git a/xonstat/batch/badges/render.py b/xonstat/batch/badges/render.py deleted file mode 100644 index 685e649..0000000 --- a/xonstat/batch/badges/render.py +++ /dev/null @@ -1,587 +0,0 @@ -import re -import zlib, struct -import cairo as C -from colorsys import rgb_to_hls, hls_to_rgb -import sqlalchemy as sa -import sqlalchemy.sql.functions as func -from xonstat.models import * -from xonstat.util import qfont_decode, _all_colors - -# similar to html_colors() from util.py -_contrast_threshold = 0.5 - -_dec_colors = [ (0.5,0.5,0.5), - (1.0,0.0,0.0), - (0.2,1.0,0.0), - (1.0,1.0,0.0), - (0.2,0.4,1.0), - (0.2,1.0,1.0), - (1.0,0.2,102), - (1.0,1.0,1.0), - (0.6,0.6,0.6), - (0.5,0.5,0.5) - ] - - -def writepng(filename, buf, width, height): - width_byte_4 = width * 4 - # fix color ordering (BGR -> RGB) - for byte in xrange(width*height): - pos = byte * 4 - buf[pos:pos+4] = buf[pos+2] + buf[pos+1] + buf[pos+0] + buf[pos+3] - # merge lines - #raw_data = b"".join(b'\x00' + buf[span:span + width_byte_4] for span in xrange((height - 1) * width * 4, -1, - width_byte_4)) - raw_data = b"".join(b'\x00' + buf[span:span + width_byte_4] for span in range(0, (height-1) * width * 4 + 1, width_byte_4)) - def png_pack(png_tag, data): - chunk_head = png_tag + data - return struct.pack("!I", len(data)) + chunk_head + struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head)) - data = b"".join([ - b'\x89PNG\r\n\x1a\n', - png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)), - png_pack(b'IDAT', zlib.compress(raw_data, 9)), - png_pack(b'IEND', b'')]) - f = open(filename, "wb") - try: - f.write(data) - finally: - f.close() - - -class PlayerData: - - # player data, will be filled by get_data() - data = {} - - def __init__(self): - self.data = {} - - def __getattr__(self, key): - if self.data.has_key(key): - return self.data[key] - return None - - def get_data(self, player_id): - """Return player data as dict. - - This function is similar to the function in player.py but more optimized - for this purpose. - """ - # total games - # wins/losses - # kills/deaths - # duel/dm/tdm/ctf elo + rank - - player = DBSession.query(Player).filter(Player.player_id == player_id).one() - - games_played = DBSession.query( - Game.game_type_cd, func.count(), func.sum(PlayerGameStat.alivetime)).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(PlayerGameStat.player_id == player_id).\ - group_by(Game.game_type_cd).\ - order_by(func.count().desc()).\ - limit(3).all() # limit to 3 gametypes! - - total_stats = {} - total_stats['games'] = 0 - total_stats['games_breakdown'] = {} # this is a dictionary inside a dictionary .. dictception? - total_stats['games_alivetime'] = {} - total_stats['gametypes'] = [] - for (game_type_cd, games, alivetime) in games_played: - total_stats['games'] += games - total_stats['gametypes'].append(game_type_cd) - total_stats['games_breakdown'][game_type_cd] = games - total_stats['games_alivetime'][game_type_cd] = alivetime - - (total_stats['kills'], total_stats['deaths'], total_stats['alivetime'],) = DBSession.query( - func.sum(PlayerGameStat.kills), - func.sum(PlayerGameStat.deaths), - func.sum(PlayerGameStat.alivetime)).\ - filter(PlayerGameStat.player_id == player_id).\ - one() - - # (total_stats['wins'],) = DBSession.query( - # func.count("*")).\ - # filter(Game.game_id == PlayerGameStat.game_id).\ - # filter(PlayerGameStat.player_id == player_id).\ - # filter(Game.winner == PlayerGameStat.team or PlayerGameStat.rank == 1).\ - # one() - - (total_stats['wins'],) = DBSession.\ - query("total_wins").\ - from_statement( - "select count(*) total_wins " - "from games g, player_game_stats pgs " - "where g.game_id = pgs.game_id " - "and player_id=:player_id " - "and (g.winner = pgs.team or pgs.rank = 1)" - ).params(player_id=player_id).one() - - ranks = DBSession.query("game_type_cd", "rank", "max_rank").\ - from_statement( - "select pr.game_type_cd, pr.rank, overall.max_rank " - "from player_ranks pr, " - "(select game_type_cd, max(rank) max_rank " - "from player_ranks " - "group by game_type_cd) overall " - "where pr.game_type_cd = overall.game_type_cd " - "and player_id = :player_id " - "order by rank").\ - params(player_id=player_id).all() - - ranks_dict = {} - for gtc,rank,max_rank in ranks: - ranks_dict[gtc] = (rank, max_rank) - - elos = DBSession.query(PlayerElo).\ - filter_by(player_id=player_id).\ - order_by(PlayerElo.elo.desc()).\ - all() - - elos_dict = {} - for elo in elos: - if elo.games > 32: - elos_dict[elo.game_type_cd] = elo.elo - - self.data = { - 'player':player, - 'total_stats':total_stats, - 'ranks':ranks_dict, - 'elos':elos_dict, - } - - - -class Skin: - - # skin parameters, can be overriden by init - params = {} - - # skin name - name = "" - - def __init__(self, name, **params): - # default parameters - self.name = name - self.params = { - 'bg': "dark_wall", # None - plain; otherwise use given texture - 'bgcolor': None, # transparent bg when bgcolor==None - 'overlay': None, # add overlay graphic on top of bg - 'font': "Xolonium", - 'width': 560, - 'height': 70, - 'nick_fontsize': 20, - 'nick_pos': (5,18), - 'nick_maxwidth': 330, - 'gametype_fontsize':12, - 'gametype_pos': (60,31), - 'gametype_width': 110, - 'gametype_height': 22, - 'gametype_color': (1.0, 1.0, 1.0), - 'gametype_text': "[ %s ]", - 'num_gametypes': 3, - 'nostats_fontsize': 12, - 'nostats_pos': (60,59), - 'nostats_color': (0.8, 0.2, 0.2), - 'nostats_angle': -10, - 'nostats_text': "no stats yet!", - 'elo_pos': (60,47), - 'elo_fontsize': 10, - 'elo_color': (1.0, 1.0, 0.5), - 'elo_text': "Elo %.0f", - 'rank_fontsize': 8, - 'rank_pos': (60,57), - 'rank_color': (0.8, 0.8, 1.0), - 'rank_text': "Rank %d of %d", - 'wintext_fontsize': 10, - 'wintext_pos': (508,3), - 'wintext_width': 102, - 'wintext_color': (0.8, 0.8, 0.8), - 'wintext_bg': (0.8, 0.8, 0.8, 0.1), - 'wintext_text': "Win Percentage", - 'winp_fontsize': 12, - 'winp_pos': (508,19), - 'winp_colortop': (0.2, 1.0, 1.0), - 'winp_colorbot': (1.0, 1.0, 0.2), - 'wins_fontsize': 8, - 'wins_pos': (508,33), - 'wins_color': (0.6, 0.8, 0.8), - 'loss_fontsize': 8, - 'loss_pos': (508,43), - 'loss_color': (0.8, 0.8, 0.6), - 'kdtext_fontsize': 10, - 'kdtext_pos': (390,3), - 'kdtext_width': 102, - 'kdtext_color': (0.8, 0.8, 0.8), - 'kdtext_bg': (0.8, 0.8, 0.8, 0.1), - 'kdtext_text': "Kill Ratio", - 'kdr_fontsize': 12, - 'kdr_pos': (392,19), - 'kdr_colortop': (0.2, 1.0, 0.2), - 'kdr_colorbot': (1.0, 0.2, 0.2), - 'kills_fontsize': 8, - 'kills_pos': (392,46), - 'kills_color': (0.6, 0.8, 0.6), - 'deaths_fontsize': 8, - 'deaths_pos': (392,56), - 'deaths_color': (0.8, 0.6, 0.6), - 'ptime_fontsize': 10, - 'ptime_pos': (451,60), - 'ptime_width': 222, - 'ptime_bg': (0.8, 0.8, 0.8, 0.5), - 'ptime_color': (0.1, 0.1, 0.1), - 'ptime_text': "Playing Time: %s", - } - - for k,v in params.items(): - if self.params.has_key(k): - self.params[k] = v - - def __str__(self): - return self.name - - def __getattr__(self, key): - if self.params.has_key(key): - return self.params[key] - return None - - def render_image(self, data, output_filename): - """Render an image for the given player id.""" - - # setup variables - - player = data.player - total_stats = data.total_stats - elos = data.elos - ranks = data.ranks - - font = "Xolonium" - if self.font == 1: - font = "DejaVu Sans" - - - # build image - - surf = C.ImageSurface(C.FORMAT_ARGB32, self.width, self.height) - ctx = C.Context(surf) - ctx.set_antialias(C.ANTIALIAS_GRAY) - - # draw background - if self.bg == None: - if self.bgcolor != None: - # plain fillcolor, full transparency possible with (1,1,1,0) - ctx.save() - ctx.set_operator(C.OPERATOR_SOURCE) - ctx.rectangle(0, 0, self.width, self.height) - ctx.set_source_rgba(self.bgcolor[0], self.bgcolor[1], self.bgcolor[2], self.bgcolor[3]) - ctx.fill() - ctx.restore() - else: - try: - # background texture - bg = C.ImageSurface.create_from_png("img/%s.png" % self.bg) - - # tile image - if bg: - bg_w, bg_h = bg.get_width(), bg.get_height() - bg_xoff = 0 - while bg_xoff < self.width: - bg_yoff = 0 - while bg_yoff < self.height: - ctx.set_source_surface(bg, bg_xoff, bg_yoff) - #ctx.mask_surface(bg) - ctx.paint() - bg_yoff += bg_h - bg_xoff += bg_w - except: - #print "Error: Can't load background texture: %s" % self.bg - pass - - # draw overlay graphic - if self.overlay != None: - try: - overlay = C.ImageSurface.create_from_png("img/%s.png" % self.overlay) - ctx.set_source_surface(overlay, 0, 0) - #ctx.mask_surface(overlay) - ctx.paint() - except: - #print "Error: Can't load overlay texture: %s" % self.overlay - pass - - - ## draw player's nickname with fancy colors - - # deocde nick, strip all weird-looking characters - qstr = qfont_decode(player.nick).replace('^^', '^').replace(u'\x00', '') - chars = [] - for c in qstr: - # replace weird characters that make problems - TODO - if ord(c) < 128: - chars.append(c) - qstr = ''.join(chars) - stripped_nick = strip_colors(qstr.replace(' ', '_')) - - # fontsize is reduced if width gets too large - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) - shrinknick = 0 - while shrinknick < 10: - ctx.set_font_size(self.nick_fontsize - shrinknick) - xoff, yoff, tw, th = ctx.text_extents(stripped_nick)[:4] - if tw > self.nick_maxwidth: - shrinknick += 2 - continue - break - - # determine width of single whitespace for later use - xoff, yoff, tw, th = ctx.text_extents("_")[:4] - space_w = tw - - # split nick into colored segments - xoffset = 0 - _all_colors = re.compile(r'(\^\d|\^x[\dA-Fa-f]{3})') - parts = _all_colors.split(qstr) - while len(parts) > 0: - tag = None - txt = parts[0] - if _all_colors.match(txt): - tag = txt[1:] # strip leading '^' - if len(parts) < 2: - break - txt = parts[1] - del parts[1] - del parts[0] - - if not txt or len(txt) == 0: - # only colorcode and no real text, skip this - continue - - if tag: - if tag.startswith('x'): - r = int(tag[1] * 2, 16) / 255.0 - g = int(tag[2] * 2, 16) / 255.0 - b = int(tag[3] * 2, 16) / 255.0 - hue, light, satur = rgb_to_hls(r, g, b) - if light < _contrast_threshold: - light = _contrast_threshold - r, g, b = hls_to_rgb(hue, light, satur) - else: - r,g,b = _dec_colors[int(tag[0])] - else: - r,g,b = _dec_colors[7] - - ctx.set_source_rgb(r, g, b) - ctx.move_to(self.nick_pos[0] + xoffset, self.nick_pos[1]) - ctx.show_text(txt) - - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - tw += (len(txt)-len(txt.strip())) * space_w # account for lost whitespaces - xoffset += tw + 2 - - ## print elos and ranks - - # show up to three gametypes the player has participated in - xoffset = 0 - for gt in total_stats['gametypes'][:self.num_gametypes]: - if self.gametype_pos: - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_BOLD) - ctx.set_font_size(self.gametype_fontsize) - ctx.set_source_rgb(self.gametype_color[0],self.gametype_color[1],self.gametype_color[2]) - txt = self.gametype_text % gt.upper() - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.gametype_pos[0]+xoffset-xoff-tw/2, self.gametype_pos[1]-yoff) - ctx.show_text(txt) - - # draw lines - TODO put this in overlay graphic - if self.overlay == None: - old_aa = ctx.get_antialias() - ctx.set_antialias(C.ANTIALIAS_NONE) - ctx.set_source_rgb(0.8, 0.8, 0.8) - ctx.set_line_width(1) - ctx.move_to(self.gametype_pos[0]+xoffset-self.gametype_width/2+5, self.gametype_pos[1]+14) - ctx.line_to(self.gametype_pos[0]+xoffset+self.gametype_width/2-5, self.gametype_pos[1]+14) - ctx.stroke() - ctx.move_to(self.gametype_pos[0]+xoffset-self.gametype_width/2+5, self.gametype_pos[1]+self.gametype_height+14) - ctx.line_to(self.gametype_pos[0]+xoffset+self.gametype_width/2-5, self.gametype_pos[1]+self.gametype_height+14) - ctx.stroke() - ctx.set_antialias(old_aa) - - if not elos.has_key(gt) or not ranks.has_key(gt): - if self.nostats_pos: - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_BOLD) - ctx.set_font_size(self.nostats_fontsize) - ctx.set_source_rgb(self.nostats_color[0],self.nostats_color[1],self.nostats_color[2]) - txt = self.nostats_text - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.nostats_pos[0]+xoffset-xoff-tw/2, self.nostats_pos[1]-yoff) - ctx.save() - ctx.rotate(math.radians(self.nostats_angle)) - ctx.show_text(txt) - ctx.restore() - else: - if self.elo_pos: - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) - ctx.set_font_size(self.elo_fontsize) - ctx.set_source_rgb(self.elo_color[0], self.elo_color[1], self.elo_color[2]) - txt = self.elo_text % round(elos[gt], 0) - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.elo_pos[0]+xoffset-xoff-tw/2, self.elo_pos[1]-yoff) - ctx.show_text(txt) - if self.rank_pos: - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) - ctx.set_font_size(self.rank_fontsize) - ctx.set_source_rgb(self.rank_color[0], self.rank_color[1], self.rank_color[2]) - txt = self.rank_text % ranks[gt] - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.rank_pos[0]+xoffset-xoff-tw/2, self.rank_pos[1]-yoff) - ctx.show_text(txt) - - xoffset += self.gametype_width - - - # print win percentage - - if self.wintext_pos: - if self.overlay == None: - ctx.rectangle(self.wintext_pos[0]-self.wintext_width/2, self.wintext_pos[1]-self.wintext_fontsize/2+1, - self.wintext_width, self.wintext_fontsize+4) - ctx.set_source_rgba(self.wintext_bg[0], self.wintext_bg[1], self.wintext_bg[2], self.wintext_bg[3]) - ctx.fill() - - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) - ctx.set_font_size(self.wintext_fontsize) - ctx.set_source_rgb(self.wintext_color[0], self.wintext_color[1], self.wintext_color[2]) - txt = self.wintext_text - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.wintext_pos[0]-xoff-tw/2, self.wintext_pos[1]-yoff) - ctx.show_text(txt) - - total_games = total_stats['games'] - wins, losses = total_stats['wins'], total_games-total_stats['wins'] - txt = "???" - try: - ratio = float(wins)/total_games - txt = "%.2f%%" % round(ratio * 100, 2) - except: - ratio = 0 - - if self.winp_pos: - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_BOLD) - ctx.set_font_size(self.winp_fontsize) - r = ratio*self.winp_colortop[0] + (1-ratio)*self.winp_colorbot[0] - g = ratio*self.winp_colortop[1] + (1-ratio)*self.winp_colorbot[1] - b = ratio*self.winp_colortop[2] + (1-ratio)*self.winp_colorbot[2] - ctx.set_source_rgb(r, g, b) - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.winp_pos[0]-xoff-tw/2, self.winp_pos[1]-yoff) - ctx.show_text(txt) - - if self.wins_pos: - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) - ctx.set_font_size(self.wins_fontsize) - ctx.set_source_rgb(self.wins_color[0], self.wins_color[1], self.wins_color[2]) - txt = "%d win" % wins - if wins != 1: - txt += "s" - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.wins_pos[0]-xoff-tw/2, self.wins_pos[1]-yoff) - ctx.show_text(txt) - - if self.loss_pos: - ctx.set_font_size(self.loss_fontsize) - ctx.set_source_rgb(self.loss_color[0], self.loss_color[1], self.loss_color[2]) - txt = "%d loss" % losses - if losses != 1: - txt += "es" - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.loss_pos[0]-xoff-tw/2, self.loss_pos[1]-yoff) - ctx.show_text(txt) - - - # print kill/death ratio - - if self.kdtext_pos: - if self.overlay == None: - ctx.rectangle(self.kdtext_pos[0]-self.kdtext_width/2, self.kdtext_pos[1]-self.kdtext_fontsize/2+1, - self.kdtext_width, self.kdtext_fontsize+4) - ctx.set_source_rgba(self.kdtext_bg[0], self.kdtext_bg[1], self.kdtext_bg[2], self.kdtext_bg[3]) - ctx.fill() - - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) - ctx.set_font_size(self.kdtext_fontsize) - ctx.set_source_rgb(self.kdtext_color[0], self.kdtext_color[1], self.kdtext_color[2]) - txt = self.kdtext_text - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.kdtext_pos[0]-xoff-tw/2, self.kdtext_pos[1]-yoff) - ctx.show_text(txt) - - kills, deaths = total_stats['kills'] , total_stats['deaths'] - txt = "???" - try: - ratio = float(kills)/deaths - txt = "%.3f" % round(ratio, 3) - except: - ratio = 0 - - if self.kdr_pos: - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_BOLD) - ctx.set_font_size(self.kdr_fontsize) - nr = ratio / 2.0 - if nr > 1: - nr = 1 - r = nr*self.kdr_colortop[0] + (1-nr)*self.kdr_colorbot[0] - g = nr*self.kdr_colortop[1] + (1-nr)*self.kdr_colorbot[1] - b = nr*self.kdr_colortop[2] + (1-nr)*self.kdr_colorbot[2] - ctx.set_source_rgb(r, g, b) - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.kdr_pos[0]-xoff-tw/2, self.kdr_pos[1]-yoff) - ctx.show_text(txt) - - if self.kills_pos: - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) - ctx.set_font_size(self.kills_fontsize) - ctx.set_source_rgb(self.kills_color[0], self.kills_color[1], self.kills_color[2]) - txt = "%d kill" % kills - if kills != 1: - txt += "s" - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.kills_pos[0]-xoff-tw/2, self.kills_pos[1]+yoff) - ctx.show_text(txt) - - if self.deaths_pos: - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) - ctx.set_font_size(self.deaths_fontsize) - ctx.set_source_rgb(self.deaths_color[0], self.deaths_color[1], self.deaths_color[2]) - if deaths is not None: - txt = "%d death" % deaths - if deaths != 1: - txt += "s" - else: - txt = "" - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.deaths_pos[0]-xoff-tw/2, self.deaths_pos[1]+yoff) - ctx.show_text(txt) - - - # print playing time - - if self.ptime_pos: - if self.overlay == None: - ctx.rectangle( self.ptime_pos[0]-self.ptime_width/2, self.ptime_pos[1]-self.ptime_fontsize/2+1, - self.ptime_width, self.ptime_fontsize+4) - ctx.set_source_rgba(self.ptime_bg[0], self.ptime_bg[1], self.ptime_bg[2], self.ptime_bg[2]) - ctx.fill() - - ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) - ctx.set_font_size(self.ptime_fontsize) - ctx.set_source_rgb(self.ptime_color[0], self.ptime_color[1], self.ptime_color[2]) - txt = self.ptime_text % str(total_stats['alivetime']) - xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.ptime_pos[0]-xoff-tw/2, self.ptime_pos[1]-yoff) - ctx.show_text(txt) - - - # save to PNG - #surf.write_to_png(output_filename) - surf.flush() - imgdata = surf.get_data() - writepng(output_filename, imgdata, self.width, self.height) - diff --git a/xonstat/batch/badges/skin.py b/xonstat/batch/badges/skin.py index 5c832c9..0af57d8 100644 --- a/xonstat/batch/badges/skin.py +++ b/xonstat/batch/badges/skin.py @@ -71,20 +71,24 @@ class Skin: 'gametype_width': 110, 'gametype_color': (0.9, 0.9, 0.9), 'gametype_text': "[ %s ]", + 'gametype_center': True, 'num_gametypes': 3, 'nostats_fontsize': 12, 'nostats_pos': (60,59), - 'nostats_color': (0.8, 0.2, 0.2), + 'nostats_color': (0.8, 0.2, 0.1), 'nostats_angle': -10, 'nostats_text': "no stats yet!", + 'nostats_center': False, 'elo_pos': (60,47), 'elo_fontsize': 10, 'elo_color': (1.0, 1.0, 0.5), 'elo_text': "Elo %.0f", + 'elo_center': False, 'rank_fontsize': 8, 'rank_pos': (60,57), 'rank_color': (0.8, 0.8, 1.0), 'rank_text': "Rank %d of %d", + 'rank_center': False, 'wintext_fontsize': 10, 'wintext_pos': (508,3), 'wintext_color': (0.8, 0.8, 0.8), @@ -92,6 +96,7 @@ class Skin: 'winp_fontsize': 12, 'winp_pos': (508,19), 'winp_colortop': (0.2, 1.0, 1.0), + 'winp_colormid': (0.4, 0.8, 0.4), 'winp_colorbot': (1.0, 1.0, 0.2), 'wins_fontsize': 8, 'wins_pos': (508,33), @@ -108,6 +113,7 @@ class Skin: 'kdr_fontsize': 12, 'kdr_pos': (392,19), 'kdr_colortop': (0.2, 1.0, 0.2), + 'kdr_colormid': (0.8, 0.8, 0.4), 'kdr_colorbot': (1.0, 0.2, 0.2), 'kills_fontsize': 8, 'kills_pos': (392,46), @@ -281,7 +287,10 @@ class Skin: ctx.set_source_rgb(self.gametype_color[0],self.gametype_color[1],self.gametype_color[2]) txt = self.gametype_text % gt.upper() xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.gametype_pos[0]+xoffset-xoff-tw/2, self.gametype_pos[1]-yoff) + if self.gametype_center: + ctx.move_to(self.gametype_pos[0]+xoffset-xoff-tw/2, self.gametype_pos[1]-yoff) + else: + ctx.move_to(self.gametype_pos[0]+xoffset-xoff, self.gametype_pos[1]-yoff) ctx.show_text(txt) if not elos.has_key(gt) or not ranks.has_key(gt): @@ -291,7 +300,10 @@ class Skin: ctx.set_source_rgb(self.nostats_color[0],self.nostats_color[1],self.nostats_color[2]) txt = self.nostats_text xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.nostats_pos[0]+xoffset-xoff-tw/2, self.nostats_pos[1]-yoff) + if self.nostats_center: + ctx.move_to(self.nostats_pos[0]+xoffset-xoff-tw/2, self.nostats_pos[1]-yoff) + else: + ctx.move_to(self.nostats_pos[0]+xoffset-xoff, self.nostats_pos[1]-yoff) ctx.save() ctx.rotate(math.radians(self.nostats_angle)) ctx.show_text(txt) @@ -303,7 +315,10 @@ class Skin: ctx.set_source_rgb(self.elo_color[0], self.elo_color[1], self.elo_color[2]) txt = self.elo_text % round(elos[gt], 0) xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.elo_pos[0]+xoffset-xoff-tw/2, self.elo_pos[1]-yoff) + if self.elo_center: + ctx.move_to(self.elo_pos[0]+xoffset-xoff-tw/2, self.elo_pos[1]-yoff) + else: + ctx.move_to(self.elo_pos[0]+xoffset-xoff, self.elo_pos[1]-yoff) ctx.show_text(txt) if self.rank_pos: ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL) @@ -311,7 +326,10 @@ class Skin: ctx.set_source_rgb(self.rank_color[0], self.rank_color[1], self.rank_color[2]) txt = self.rank_text % ranks[gt] xoff, yoff, tw, th = ctx.text_extents(txt)[:4] - ctx.move_to(self.rank_pos[0]+xoffset-xoff-tw/2, self.rank_pos[1]-yoff) + if self.rank_center: + ctx.move_to(self.rank_pos[0]+xoffset-xoff-tw/2, self.rank_pos[1]-yoff) + else: + ctx.move_to(self.rank_pos[0]+xoffset-xoff, self.rank_pos[1]-yoff) ctx.show_text(txt) xoffset += self.gametype_width @@ -338,9 +356,16 @@ class Skin: if self.winp_pos: ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_BOLD) ctx.set_font_size(self.winp_fontsize) - r = ratio*self.winp_colortop[0] + (1-ratio)*self.winp_colorbot[0] - g = ratio*self.winp_colortop[1] + (1-ratio)*self.winp_colorbot[1] - b = ratio*self.winp_colortop[2] + (1-ratio)*self.winp_colorbot[2] + if ratio >= 0.5: + nr = 2*(ratio-0.5) + r = nr*self.winp_colortop[0] + (1-nr)*self.winp_colormid[0] + g = nr*self.winp_colortop[1] + (1-nr)*self.winp_colormid[1] + b = nr*self.winp_colortop[2] + (1-nr)*self.winp_colormid[2] + else: + nr = 2*ratio + r = nr*self.winp_colormid[0] + (1-nr)*self.winp_colorbot[0] + g = nr*self.winp_colormid[1] + (1-nr)*self.winp_colorbot[1] + b = nr*self.winp_colormid[2] + (1-nr)*self.winp_colorbot[2] ctx.set_source_rgb(r, g, b) xoff, yoff, tw, th = ctx.text_extents(txt)[:4] ctx.move_to(self.winp_pos[0]-xoff-tw/2, self.winp_pos[1]-yoff) @@ -389,12 +414,18 @@ class Skin: if self.kdr_pos: ctx.select_font_face(font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_BOLD) ctx.set_font_size(self.kdr_fontsize) - nr = ratio / 2.0 - if nr > 1: - nr = 1 - r = nr*self.kdr_colortop[0] + (1-nr)*self.kdr_colorbot[0] - g = nr*self.kdr_colortop[1] + (1-nr)*self.kdr_colorbot[1] - b = nr*self.kdr_colortop[2] + (1-nr)*self.kdr_colorbot[2] + if ratio >= 1.0: + nr = ratio-1.0 + if nr > 1: + nr = 1 + r = nr*self.kdr_colortop[0] + (1-nr)*self.kdr_colormid[0] + g = nr*self.kdr_colortop[1] + (1-nr)*self.kdr_colormid[1] + b = nr*self.kdr_colortop[2] + (1-nr)*self.kdr_colormid[2] + else: + nr = ratio + r = nr*self.kdr_colormid[0] + (1-nr)*self.kdr_colorbot[0] + g = nr*self.kdr_colormid[1] + (1-nr)*self.kdr_colorbot[1] + b = nr*self.kdr_colormid[2] + (1-nr)*self.kdr_colorbot[2] ctx.set_source_rgb(r, g, b) xoff, yoff, tw, th = ctx.text_extents(txt)[:4] ctx.move_to(self.kdr_pos[0]-xoff-tw/2, self.kdr_pos[1]-yoff) -- 2.39.2