From a28e0dafc317ae4f938357013804dac889abc26d Mon Sep 17 00:00:00 2001 From: "Jan D. Behrens" Date: Wed, 29 Aug 2012 16:39:59 +0200 Subject: [PATCH] A collection of smaller improvements to the badges generator - Fixed a bug in the commandline parser - Finally fixed the "win/loss" bug (new query, also a bit faster) - Split up "render" and "data" parts of the code (skin.py & playerdata.py) - Reworked overlay images for classic/minimal skin (source .xcf files included) --- .gitignore | 6 +- xonstat/batch/badges/clean.sh | 3 + xonstat/batch/badges/gen_badges.py | 19 +- xonstat/batch/badges/img/overlay_classic.png | Bin 0 -> 2327 bytes xonstat/batch/badges/img/overlay_classic.xcf | Bin 0 -> 143024 bytes xonstat/batch/badges/img/overlay_minimal.png | Bin 0 -> 314 bytes xonstat/batch/badges/img/overlay_minimal.xcf | Bin 0 -> 22855 bytes xonstat/batch/badges/playerdata.py | 111 +++++ xonstat/batch/badges/skin.py | 446 +++++++++++++++++++ 9 files changed, 576 insertions(+), 9 deletions(-) create mode 100644 xonstat/batch/badges/clean.sh create mode 100644 xonstat/batch/badges/img/overlay_classic.png create mode 100644 xonstat/batch/badges/img/overlay_classic.xcf create mode 100644 xonstat/batch/badges/img/overlay_minimal.png create mode 100644 xonstat/batch/badges/img/overlay_minimal.xcf create mode 100644 xonstat/batch/badges/playerdata.py create mode 100644 xonstat/batch/badges/skin.py diff --git a/.gitignore b/.gitignore index 72723e5..8e48bc7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -*pyc +*.pyc +*~ +*.bak +xonstat/batch/badges/output/*.png +xonstat/batch/badges/output/*/*.png diff --git a/xonstat/batch/badges/clean.sh b/xonstat/batch/badges/clean.sh new file mode 100644 index 0000000..c8fd6aa --- /dev/null +++ b/xonstat/batch/badges/clean.sh @@ -0,0 +1,3 @@ +#!/bin/sh +find output -name "*.png" -exec rm {} \; + diff --git a/xonstat/batch/badges/gen_badges.py b/xonstat/batch/badges/gen_badges.py index dcb6a1e..3dfc196 100644 --- a/xonstat/batch/badges/gen_badges.py +++ b/xonstat/batch/badges/gen_badges.py @@ -8,10 +8,11 @@ from sqlalchemy import distinct from pyramid.paster import bootstrap from xonstat.models import * -from render import PlayerData, Skin +from skin import Skin +from playerdata import PlayerData -# maximal number of query results (for testing, set to 0 to get all) +# maximal number of query results (for testing, set to None to get all) NUM_PLAYERS = None # we look for players who have activity within the past DELTA hours @@ -21,12 +22,13 @@ DELTA = 6 # classic skin WITHOUT NAME - writes PNGs into "output//###.png" skin_classic = Skin( "", bg = "asfalt", + overlay = "overlay_classic", ) # more fancy skin [** WIP **]- writes PNGs into "output/archer/###.png" skin_archer = Skin( "archer", bg = "background_archer-v1", - overlay = "", + overlay = None, ) # minimal skin - writes PNGs into "output/minimal/###.png" @@ -36,10 +38,10 @@ skin_minimal = Skin( "minimal", overlay = "overlay_minimal", width = 560, height = 40, - num_gametypes = 4, + num_gametypes = 3, gametype_pos = (25,30), gametype_text = "%s :", - gametype_width = 120, + gametype_width = 115, gametype_fontsize = 10, elo_pos = (75,30), elo_text = "Elo %.0f", @@ -59,6 +61,7 @@ skin_minimal = Skin( "minimal", ptime_color = (0.8, 0.8, 0.9), ) + # parse cmdline parameters (for testing) skins = [] @@ -68,12 +71,12 @@ for arg in sys.argv[1:]: if arg == "force": DELTA = 2**24 # large enough to enforce update, and doesn't result in errors elif arg == "test": - NUM_PLAYERS = 200 + NUM_PLAYERS = 100 else: print """Usage: gen_badges.py [options] [skin list] Options: -force Force updating all badges (delta = 2^24) - -testing Limit number of players to 200 (for testing) + -test Limit number of players to 100 (for testing) -help Show this help text Skin list: Space-separated list of skins to use when creating badges. @@ -81,7 +84,7 @@ for arg in sys.argv[1:]: If no skins are given, classic and minmal will be used by default. NOTE: Output directories must exists before running the program! """ - sys.exit(-1) + sys.exit(-1) else: if arg == "classic": skins.append(skin_classic) diff --git a/xonstat/batch/badges/img/overlay_classic.png b/xonstat/batch/badges/img/overlay_classic.png new file mode 100644 index 0000000000000000000000000000000000000000..fdc58d895b61ca79a2ff86859de71261193ef481 GIT binary patch literal 2327 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

XabXgW##OX(JMy`bsp9b{99Y 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

DyS`^R4S#a|`d2+Sjg#3`FYs(vyRPqA|D(yZ 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 literal 0 HcmV?d00001 diff --git a/xonstat/batch/badges/img/overlay_minimal.png b/xonstat/batch/badges/img/overlay_minimal.png new file mode 100644 index 0000000000000000000000000000000000000000..d91b5b2f461d3bb4a45f76d0e8476fc5e8ced3e5 GIT binary patch literal 314 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 Wj)YIqX47|!X&z{-8&Cg(vH5RERFa|q literal 0 HcmV?d00001 diff --git a/xonstat/batch/badges/playerdata.py b/xonstat/batch/badges/playerdata.py new file mode 100644 index 0000000..0990208 --- /dev/null +++ b/xonstat/batch/badges/playerdata.py @@ -0,0 +1,111 @@ +import sqlalchemy as sa +import sqlalchemy.sql.functions as func +from xonstat.models import * + + +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()).\ + all() + + 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'], total_stats['losses']) = DBSession.\ + query("wins", "losses").\ + from_statement( + "SELECT SUM(win) wins, SUM(loss) losses " + "FROM (SELECT g.game_id, " + " CASE " + " WHEN g.winner = pgs.team THEN 1 " + " WHEN pgs.rank = 1 THEN 1 " + " ELSE 0 " + " END win, " + " CASE " + " WHEN g.winner = pgs.team THEN 0 " + " WHEN pgs.rank = 1 THEN 0 " + " ELSE 1 " + " END loss " + " FROM games g, " + " player_game_stats pgs " + " WHERE g.game_id = pgs.game_id " + " AND pgs.player_id = :player_id) win_loss").\ + 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, + } + diff --git a/xonstat/batch/badges/skin.py b/xonstat/batch/badges/skin.py new file mode 100644 index 0000000..5c832c9 --- /dev/null +++ b/xonstat/batch/badges/skin.py @@ -0,0 +1,446 @@ +import math +import re +import zlib, struct +import cairo as C +from colorsys import rgb_to_hls, hls_to_rgb +from xonstat.util import strip_colors, 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 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': None, # 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_color': (0.9, 0.9, 0.9), + '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_color': (0.8, 0.8, 0.8), + '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_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 + elos = data.elos + ranks = data.ranks + #games = data.total_stats['games'] + wins, losses = data.total_stats['wins'], data.total_stats['losses'] + games = wins + losses + kills, deaths = data.total_stats['kills'], data.total_stats['deaths'] + alivetime = data.total_stats['alivetime'] + + + 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 data.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) + + 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: + 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) + + txt = "???" + try: + ratio = float(wins)/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: + 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) + + 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: + 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(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) + -- 2.39.2