mirror of
https://github.com/oDinZu/callirhoe.git
synced 2025-02-22 00:04:52 -05:00
first import
git-svn-id: https://callirhoe.googlecode.com/svn/trunk@5 81c8bb96-aa45-f2e2-0eef-c4fa4a15c6df
This commit is contained in:
parent
ec2b26784f
commit
21c3f79c9f
170
callirhoe.py
Executable file
170
callirhoe.py
Executable file
@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
_version = "0.1"
|
||||
|
||||
import calendar
|
||||
import sys
|
||||
import time
|
||||
import os.path
|
||||
import optparse
|
||||
import glob
|
||||
|
||||
from lib.xcairo import *
|
||||
from lib.render import *
|
||||
|
||||
plugin_path = [ os.path.expanduser("~/.callirhoe"), sys.path[0] if sys.path[0] else "." ]
|
||||
|
||||
def available_files(parent, dir, fmatch = ""):
|
||||
good = False
|
||||
res = []
|
||||
pattern = parent + "/" + dir + "/*.py"
|
||||
# TODO: improve matching with __init__ when lang known
|
||||
for x in glob.glob(pattern):
|
||||
basex = os.path.basename(x)
|
||||
if basex == "__init__.py": good = True
|
||||
else:
|
||||
base = os.path.splitext(basex)[0]
|
||||
if base and ((not fmatch) or (fmatch == base)): res.append((base,parent))
|
||||
return res if good else []
|
||||
|
||||
# cat = lang (category)
|
||||
# longcat = language
|
||||
# longcat2 = languages
|
||||
# listopt = --list-lang
|
||||
# preset = "EN"
|
||||
def import_plugin(cat, longcat, longcat2, listopt, preset):
|
||||
try:
|
||||
found = available_files(plugin_path[0], cat, preset) + available_files(plugin_path[1], cat, preset)
|
||||
if len(found) == 0: raise ImportError
|
||||
old = sys.path[0];
|
||||
sys.path[0] = found[0][1]
|
||||
m = __import__("%s.%s" % (cat,preset), globals(), locals(), [ "*" ])
|
||||
sys.path[0] = old
|
||||
return m
|
||||
except ImportError:
|
||||
print >> sys.stderr, "%s definition `%s' not found, use %s to see available %s" % (longcat,preset,listopt,longcat2)
|
||||
sys.exit(1)
|
||||
|
||||
parser = optparse.OptionParser(usage="usage: %prog [options] FILE",
|
||||
description="High quality calendar rendering with vector graphics.\n"
|
||||
"By default, a pdf calendar of the current year will be written to FILE. Program version: " + _version)
|
||||
parser.add_option("-y", "--year", dest="year", type="int", default=-1,
|
||||
help="select YEAR instead of current one")
|
||||
parser.add_option("-l", "--lang", dest="lang", default="EN",
|
||||
help="choose language [EN]")
|
||||
parser.add_option("-s", "--style", dest="style", default="default",
|
||||
help="choose style [default]")
|
||||
parser.add_option("-g", "--geometry", dest="geom", default="default",
|
||||
help="choose geometry [default]")
|
||||
parser.add_option("--landscape", action="store_true", dest="landscape", default=False,
|
||||
help="landscape mode")
|
||||
parser.add_option("--list-languages", action="store_true", dest="list_languages", default=False,
|
||||
help="list available languages")
|
||||
parser.add_option("--list-styles", action="store_true", dest="list_styles", default=False,
|
||||
help="list available styles")
|
||||
parser.add_option("--list-geometries", action="store_true", dest="list_geometries", default=False,
|
||||
help="list available geometries")
|
||||
parser.add_option("--lang-var", action="append", dest="lang_assign",
|
||||
help="modify a language variable")
|
||||
parser.add_option("--style-var", action="append", dest="style_assign",
|
||||
help="modify a style variable, e.g. dom.frame_thickness=0")
|
||||
parser.add_option("--geom-var", action="append", dest="geom_assign",
|
||||
help="modify a geometry variable")
|
||||
|
||||
#for x in sys.argv:
|
||||
# if x[0] == '-' and not parser.has_option(x):
|
||||
# print "possibly bad option", x
|
||||
# ./callirhoe --lang fr year=2010 months=1-6 foo.pdf
|
||||
|
||||
(options,args) = parser.parse_args()
|
||||
|
||||
def plugin_list(cat):
|
||||
return available_files(plugin_path[0], cat) + available_files(plugin_path[1], cat)
|
||||
if options.list_languages:
|
||||
for x in plugin_list("lang"): print x[0],
|
||||
print
|
||||
if options.list_styles:
|
||||
for x in plugin_list("style"): print x[0],
|
||||
print
|
||||
if options.list_geometries:
|
||||
for x in plugin_list("geom"): print x[0],
|
||||
print
|
||||
if options.list_languages or options.list_styles or options.list_geometries: sys.exit(0)
|
||||
|
||||
if len(args)==0:
|
||||
parser.print_help()
|
||||
sys.exit(0)
|
||||
|
||||
cal_lang = import_plugin("lang", "language", "languages", "--list-languages", options.lang)
|
||||
cal_style = import_plugin("style", "style", "styles", "--list-styles", options.style)
|
||||
cal_geom = import_plugin("geom", "geometry", "geometries", "--list-geometries", options.geom)
|
||||
|
||||
if options.lang_assign:
|
||||
for x in options.lang_assign: exec "cal_lang.%s" % x
|
||||
if options.style_assign:
|
||||
for x in options.style_assign: exec "cal_style.%s" % x
|
||||
if options.geom_assign:
|
||||
for x in options.geom_assign: exec "cal_geom.%s" % x
|
||||
|
||||
calendar.month_name = cal_lang.month_name
|
||||
calendar.day_name = cal_lang.day_name
|
||||
|
||||
def get_orthodox_easter(y):
|
||||
y1, y2, y3 = y - y//4 * 4, y - y//7 * 7, y - y//19 * 19
|
||||
a = 19*y3 + 15
|
||||
y4 = a - a//30 * 30
|
||||
b = 2*y1 + 4*y2 + 6*(y4 + 1)
|
||||
y5 = b - b/7 * 7
|
||||
r = 1 + 3 + y4 + y5;
|
||||
return (5, r - 30) if r > 30 else (4,r)
|
||||
|
||||
year = options.year if options.year >= 0 else time.localtime()[0]
|
||||
|
||||
p = PDFPage(args[0], options.landscape)
|
||||
|
||||
R0,R1 = rect_vsplit(p.Text_rect, 0.05)
|
||||
Rcal,Rc = rect_vsplit(R1,0.97)
|
||||
if options.landscape:
|
||||
rows,cols = 3,4
|
||||
else:
|
||||
rows,cols = 4,3
|
||||
foo = GLayout(Rcal, rows, cols, pad = (p.Text_rect[2]*0.02,)*4)
|
||||
shad = p.Size[0]*0.01 if cal_style.month.box_shadow else 0
|
||||
for i in range(min(foo.count(),12),0,-1):
|
||||
draw_month(p.cr, foo.item_seq(i-1), month=i, year=year,
|
||||
style = cal_style, geom = cal_geom, box_shadow = shad)
|
||||
# render.draw_box(render.cr,*foo.item_seq(i))
|
||||
#draw_str(p.cr, str(year), R0, stroke_rgba = (0,0,0,0.3), align=1)
|
||||
draw_str(p.cr, str(year), R0, stroke_rgba = (0,0,0,0.3), align=2)
|
||||
#draw_str(p.cr, str(year), R0, stroke_rgba = (0,0,0,0.3), align=3)
|
||||
draw_str(p.cr, "created by Callirhoe ver.0.1 © 2012 GeoTz", Rc, stroke_rgba = (0,0,0,0.5), stretch=0, align=2, slant=cairo.FONT_SLANT_ITALIC)
|
||||
|
||||
#render.cr.move_to(render.Page.Text_pos[0],render.Page.Text_pos[1])
|
||||
#render.cr.line_to(render.Page.Text_size[0]+render.Page.Text_pos[0], render.Page.Text_size[1]+render.Page.Text_pos[1])
|
||||
#render.cr.stroke()
|
||||
|
||||
#draw_month(cr, *foo.item(2), m=9)
|
||||
|
||||
#bw, bh = 40,40
|
||||
#draw_day_cell(cr, 30, 50, bw, bh, '24', 'Παραμονή Χριστουγ.', 'Ευγενία', default_style)
|
||||
#draw_day_cell(cr, 30+bw, 50, bw, bh, '25', 'ΧΡΙΣΤΟΥΓΕΝΝΑ', 'Χρήστος, Χριστίνα', weekend_holiday_style)
|
||||
#draw_day_cell(cr, 30+2*bw, 50, bw, bh, '26', '2η μέρα Χριστουγ.', 'Εμμανουήλ', weekend_style)
|
||||
#draw_day_cell(cr, 30+3*bw, 50, bw, bh, '27', '', 'Στέφανος', default_style)
|
||||
#draw_day_page(cr, 30+2*bw, 50, bw, bh, '26', 'Κυριακή', 'Δεκεμβρίου', [1,1,1], [.3,.3,.3])
|
0
geom/__init__.py
Normal file
0
geom/__init__.py
Normal file
27
geom/default.py
Normal file
27
geom/default.py
Normal file
@ -0,0 +1,27 @@
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
# --- geom.default ---
|
||||
|
||||
class dom:
|
||||
num_size = (0.5,0.5)
|
||||
header_size = footer_size = (0.8,0.1)
|
||||
top_margin = bottom_margin = 0.05
|
||||
|
||||
class month:
|
||||
fuzzy_rot = 0
|
||||
fuzzy_dx = 0
|
||||
fuzzy_dy = 0
|
27
geom/fuzzy.py
Normal file
27
geom/fuzzy.py
Normal file
@ -0,0 +1,27 @@
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
# --- geom.default ---
|
||||
|
||||
class dom:
|
||||
num_size = (0.5,0.5)
|
||||
header_size = footer_size = (0.8,0.1)
|
||||
top_margin = bottom_margin = 0.05
|
||||
|
||||
class month:
|
||||
fuzzy_rot = 0.25
|
||||
fuzzy_dx = 0
|
||||
fuzzy_dy = 0
|
29
lang/EL.py
Normal file
29
lang/EL.py
Normal file
@ -0,0 +1,29 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
day_name = [ u'Δευτέρα', u'Τρίτη', u'Τετάρτη',
|
||||
u'Πέμπτη', u'Παρασκευή', u'Σάββατο', u'Κυριακή' ]
|
||||
|
||||
short_day_name = [ u'Δευ', u'Τρι', u'Τετ', u'Πεμ', u'Παρ', u'Σαβ', u'Κυρ' ]
|
||||
|
||||
month_name = [ '', u'Ιανουάριος', u'Φεβρουάριος', u'Μάρτιος', u'Απρίλιος',
|
||||
u'Μάιος', u'Ιούνιος', u'Ιούλιος', u'Αύγουστος',
|
||||
u'Σεπτέμβριος', u'Οκτώβριος', u'Νοέμβριος', u'Δεκέμβριος' ]
|
||||
|
||||
short_month_name = [ '', u'Ιαν', u'Φεβ', u'Μαρ', u'Απρ', u'Μαϊ', u'Ιον', u'Ιολ',
|
||||
u'Αυγ', u'Σεπ', u'Οκτ', u'Νοε', u'Δεκ' ]
|
31
lang/EN.py
Normal file
31
lang/EN.py
Normal file
@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
day_name = [ u'Monday', u'Tuesday', u'Wednesday',
|
||||
u'Thursday', u'Friday', u'Saturday', u'Sunday' ]
|
||||
|
||||
short_day_name = [ u'Mon', u'Tue', u'Wed', u'Thu', u'Fri', u'Sat', u'Sun' ]
|
||||
|
||||
month_name = [ '',
|
||||
u'January', u'February', u'March', u'April',
|
||||
u'May', u'June', u'July', u'August',
|
||||
u'September', u'October', u'November', u'December' ]
|
||||
|
||||
short_month_name = [ '',
|
||||
u'Jan', u'Feb', u'Mar', u'Apr', u'May', u'Jun',
|
||||
u'Jul', u'Aug', u'Sep', u'Oct', u'Nov', u'Dec' ]
|
30
lang/FR.py
Normal file
30
lang/FR.py
Normal file
@ -0,0 +1,30 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
day_name = [ u'Lundi', u'Mardi', u'Mercredi',
|
||||
u'Jeudi', u'Vendredi', u'Samedi', u'Dimanche' ]
|
||||
|
||||
short_day_name = [ u'Lun', u'Mar', u'Mer', u'Jeu', u'Ven', u'Sam', u'Dim' ]
|
||||
|
||||
month_name = [ '',
|
||||
u'Janvier', u'Février', u'Mars', u'Avril',
|
||||
u'Mai', u'Juin', u'Juillet', u'Août',
|
||||
u'Septembre', u'Octobre', u'Novembre', u'Décembre' ]
|
||||
|
||||
short_month_name = [ '', u'Jan', u'Fév', u'Mar', u'Avr', u'Mai', u'Jun', u'Jul',
|
||||
u'Aoû', u'Sep', u'Oct', u'Nov', u'Déc' ]
|
0
lang/__init__.py
Normal file
0
lang/__init__.py
Normal file
0
lib/__init__.py
Normal file
0
lib/__init__.py
Normal file
158
lib/geom.py
Normal file
158
lib/geom.py
Normal file
@ -0,0 +1,158 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
# *****************************************
|
||||
# #
|
||||
# general-purpose geometry routines #
|
||||
# #
|
||||
# *****************************************
|
||||
|
||||
def rect_rel_scale(r, fw, fh):
|
||||
x, y, w, h = r
|
||||
return (x + w*(1 - fw)/2.0, y + h*(1 - fh)/2.0, w*fw, h*fh)
|
||||
|
||||
def rect_to_abs(r):
|
||||
x, y, w, h = r
|
||||
return (x, y, x + w, y + h)
|
||||
|
||||
def abs_to_rect(a):
|
||||
x1, y1, x2, y2 = a
|
||||
return (x1, y1, x2 - x1, y2 - y1)
|
||||
|
||||
def rect_hull(r1,r2):
|
||||
x1, y1, x2, y2 = rect_to_abs(r1)
|
||||
x3, y3, x4, y4 = rect_to_abs(r2)
|
||||
return abs_to_rect((min(x1,x3), min(y1,y3), max(x2,x4), max(y2,y4)))
|
||||
|
||||
def rect_hsplit(r, f = 0.5):
|
||||
x, y, w, h = r
|
||||
r1 = (x, y, w*f, h)
|
||||
r2 =(x + w*f, y, w*(1 - f), h)
|
||||
return (r1, r2)
|
||||
|
||||
def rect_vsplit(r, f = 0.5):
|
||||
x, y, w, h = r
|
||||
r1 = (x, y, w, h*f)
|
||||
r2 = (x, y + h*f, w, h*(1 - f))
|
||||
return (r1, r2)
|
||||
|
||||
def rect_qsplit(r, fv = 0.5, fh = 0.5):
|
||||
x, y, w, h = r
|
||||
rv = rect_vsplit(r, fv)
|
||||
return rect_hsplit(rv[0], fh) + rect_hsplit(rv[1], fh)
|
||||
|
||||
def color_mix(a, b, frac):
|
||||
k = min(len(a), len(b))
|
||||
return map(lambda (x,y): x*frac + y*(1 - frac), zip(a,b))
|
||||
|
||||
def color_auto_fg(bg, light = (1,1,1), dark = (0,0,0)):
|
||||
return light if bg[0] + bg[1] + bg[2] < 1.5 else dark
|
||||
|
||||
# ********* layout managers ***********
|
||||
|
||||
class VLayout:
|
||||
def __init__(self, rect, nitems = 1, pad = (0.0,0.0,0.0,0.0)): # TLBR
|
||||
self.pos = (rect[0], rect[1])
|
||||
self.size = (rect[2], rect[3])
|
||||
self.items = nitems
|
||||
self.pad = pad
|
||||
|
||||
def count(self):
|
||||
return self.items
|
||||
|
||||
def resize(self, k):
|
||||
self.items = k
|
||||
|
||||
def grow(self, delta = 1):
|
||||
self.items += delta
|
||||
|
||||
def move(newpos):
|
||||
self.pos = newpos;
|
||||
|
||||
def item(self, i = 0):
|
||||
vinter = (self.pad[0] + self.pad[2])/2.0;
|
||||
vsize = (self.size[1] - vinter)/self.items;
|
||||
return (self.pos[0] + self.pad[1], self.pos[1] + self.pad[0] + i*vsize,
|
||||
self.size[0] -self.pad[1] - self.pad[3], vsize - vinter)
|
||||
|
||||
def item_span(self, n, k = -1):
|
||||
if k < 0: k = (self.count() - n) // 2
|
||||
return rect_hull(self.item(k), self.item(k + n - 1))
|
||||
|
||||
class HLayout:
|
||||
def __init__(self, rect, nitems = 1, pad = (0.0,0.0,0.0,0.0)): # TLBR
|
||||
self.pos = (rect[0],rect[1])
|
||||
self.rep = VLayout((0.0, 0.0, rect[3], rect[2]), nitems, (pad[1], pad[0], pad[3], pad[2]))
|
||||
|
||||
def count(self):
|
||||
return self.rep.count()
|
||||
|
||||
def resize(self, k):
|
||||
self.rep.resize(k)
|
||||
|
||||
def move(newpos):
|
||||
self.rep.move(newpos)
|
||||
|
||||
def item(self, i = 0):
|
||||
t = self.rep.item(i)
|
||||
return (t[1] + self.pos[0], t[0] + self.pos[1], t[3], t[2])
|
||||
|
||||
def item_span(self, n, k = -1):
|
||||
if k < 0: k = (self.rep.count() - n) // 2
|
||||
return rect_hull(self.item(k), self.item(k + n - 1))
|
||||
|
||||
class GLayout:
|
||||
def __init__(self, rect, nrows = 1, ncols = 1, pad = (0.0,0.0,0.0,0.0)): # TLBR
|
||||
self.vrep = VLayout(rect, nrows, (pad[0], 0.0, pad[2], 0.0))
|
||||
t = self.vrep.item(0)
|
||||
self.hrep = HLayout((rect[0], rect[1], t[2], t[3]), ncols, (0.0, pad[1], 0.0, pad[3]))
|
||||
|
||||
def row_count(self):
|
||||
return self.vrep.count()
|
||||
|
||||
def col_count(self):
|
||||
return self.hrep.count()
|
||||
|
||||
def count(self):
|
||||
return self.row_count()*self.col_count()
|
||||
|
||||
def resize(self, rows, cols):
|
||||
self.vrep.resize(rows)
|
||||
t = self.vrep.item(0)
|
||||
self.hrep = HLayout(t[0:2], t[2:4], cols, (0.0, pad[1], 0.0, pad[3]))
|
||||
|
||||
def move(newpos):
|
||||
self.vrep.move(newpos)
|
||||
self.hrep.move(newpos)
|
||||
|
||||
def item(self, row, col):
|
||||
ty = self.vrep.item(row)
|
||||
tx = self.hrep.item(col)
|
||||
return (tx[0], ty[1], tx[2], tx[3])
|
||||
|
||||
def item_seq(self, k, column_wise = False):
|
||||
if not column_wise:
|
||||
row, col = k // self.col_count(), k % self.col_count()
|
||||
else:
|
||||
col, row = k // self.row_count(), k % self.row_count()
|
||||
return self.item(row, col)
|
||||
|
||||
def item_span(self, nr, nc, row = -1, col = -1):
|
||||
if row < 0: row = (self.row_count() - nr) // 2
|
||||
if col < 0: col = (self.col_count() - nc) // 2
|
||||
return rect_hull(self.item(row, col), self.item(row + nr - 1, col + nc - 1))
|
101
lib/render.py
Normal file
101
lib/render.py
Normal file
@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
# *****************************************
|
||||
# #
|
||||
# calendar drawing routines #
|
||||
# #
|
||||
# *****************************************
|
||||
|
||||
import math
|
||||
import calendar
|
||||
import random
|
||||
from xcairo import *
|
||||
from geom import *
|
||||
|
||||
# TODO: replace rects with rect_rel_scale()
|
||||
def draw_day_cell(cr, rect, day_of_month, header, footer, style, G):
|
||||
x, y, w, h = rect
|
||||
draw_box(cr, rect, style.frame, style.bg, style.frame_thickness)
|
||||
R = rect_rel_scale(rect, G.num_size[0], G.num_size[1])
|
||||
draw_str(cr, day_of_month, R, -1, style.fg, 2,
|
||||
font = style.font, measure = "55")
|
||||
if header:
|
||||
R = (x + (1 - G.header_size[0])*w/2, y + G.top_margin*h,
|
||||
w*G.header_size[0], h*G.header_size[1])
|
||||
draw_str(cr, header, R, -1, style.header, 2, font = style.header_font)
|
||||
if footer:
|
||||
R = (x + (1 - G.footer_size[0])*w/2, y + (1 - G.bottom_margin - G.footer_size[1])*h,
|
||||
w*G.footer_size[0], h*G.footer_size[1])
|
||||
draw_str(cr, footer, R, -1, style.footer, 2, font = style.footer_font)
|
||||
|
||||
def draw_day_page(cr, rect, day_of_month, header, footer, fill = (1,1,1), stroke = (0,0,0)):
|
||||
x, y, w, h = rect
|
||||
draw_box(cr, rect, (0,0,0), fill)
|
||||
draw_str(cr, day_of_month, (x + w*.382/2, y + h*.382/2, w*.618, h*.618), 3, stroke)
|
||||
draw_str(cr, header, (x +0.1*w, y + 0.05*h, w*0.8, 0.1*h), -1, (0,0,0), 2)
|
||||
draw_str(cr, footer, (x +0.1*w, y + 0.85*h, w*0.8, 0.1*h), -1, (0,0,0), 2)
|
||||
|
||||
# TODO: implement GEOMETRY, STYLE, DATA SOURCES...
|
||||
# TODO: use named options...
|
||||
def draw_month(cr, rect, month, year, style, geom, box_shadow = 0):
|
||||
x, y, w, h = rect
|
||||
cw = w/7.0;
|
||||
ch = h/7.0;
|
||||
cr.save()
|
||||
cr.translate(x,y)
|
||||
|
||||
cr.translate(w/2, h/2)
|
||||
cr.translate(w*(random.random() - 0.5)*geom.month.fuzzy_dx,
|
||||
h*(random.random() - 0.5)*geom.month.fuzzy_dy)
|
||||
cr.rotate((random.random() - 0.5)*geom.month.fuzzy_rot)
|
||||
cr.translate(-w/2.0, -h/2.0)
|
||||
|
||||
cal = calendar.monthrange(year, month)
|
||||
day = cal[0]
|
||||
dom = -day + 1;
|
||||
wmeasure = 'A'*max(map(len,calendar.day_name))
|
||||
mmeasure = 'A'*max(map(len,calendar.month_name))
|
||||
|
||||
for col in range(7):
|
||||
R = (col*cw, ch*3.0/5, cw, ch*2.0/5)
|
||||
draw_box(cr, R, style.dom.frame,
|
||||
style.dom.bg if col < 5 else style.dom_weekend.bg, style.dow.frame_thickness)
|
||||
R = (col*cw, ch*3.0/5 + ch*2.0/5*1.0/4, cw, ch*2.0/5*1/2)
|
||||
draw_str(cr, calendar.day_name[col], R, -1, style.dow.fg, 2,
|
||||
font = style.dow.font, measure = wmeasure)
|
||||
# TODO: use grid layout
|
||||
for row in range(6):
|
||||
for col in range(7):
|
||||
day_style = style.dom_weekend if col >= 5 else style.dom
|
||||
R = (col*cw, (row + 1)*ch, cw, ch)
|
||||
if dom > 0 and dom <= cal[1]:
|
||||
draw_day_cell(cr, R, str(dom), '', '', day_style, geom.dom)
|
||||
else:
|
||||
draw_box(cr, R, day_style.frame, day_style.bg, day_style.frame_thickness)
|
||||
dom += 1
|
||||
|
||||
mcolor = style.month.color_map[month]
|
||||
mcolor_fg = color_auto_fg(mcolor)
|
||||
draw_box(cr, (0, 0, w, h), style.month.frame, (), 2, box_shadow)
|
||||
draw_box(cr, (0, 0, w, ch*3.0/5), style.month.frame, mcolor)
|
||||
R = (0, ch*3.0/5*1/4, w, ch*3.0/5*1/2)
|
||||
draw_str(cr, calendar.month_name[month], R, -1, mcolor_fg, 2, False,
|
||||
style.month.font, measure=mmeasure, shadow=style.month.text_shadow)
|
||||
cr.restore()
|
||||
|
120
lib/xcairo.py
Normal file
120
lib/xcairo.py
Normal file
@ -0,0 +1,120 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
# *****************************************
|
||||
# #
|
||||
# general-purpose drawing routines #
|
||||
# higher-level CAIRO routines #
|
||||
# #
|
||||
# *****************************************
|
||||
|
||||
import cairo
|
||||
import math
|
||||
|
||||
class PDFPage:
|
||||
def __init__(self, filename, landscape = False, w = 210.0, h = 297.0, dpi = 72.0):
|
||||
self.DPI = dpi # default dpi
|
||||
if not landscape:
|
||||
self.Size_mm = (w, h) # (width, height) in mm
|
||||
else:
|
||||
self.Size_mm = (h, w)
|
||||
self.Size = (self.Size_mm[0]/25.4 * self.DPI, self.Size_mm[1]/25.4 * self.DPI) # size in dots
|
||||
Mag = 72.0/self.DPI;
|
||||
self.Margins = (self.Size[1]*0.025, self.Size[0]*0.025,
|
||||
self.Size[1]*0.025, self.Size[0]*0.025) # top left bottom right
|
||||
txs = (self.Size[0] - self.Margins[1] - self.Margins[3],
|
||||
self.Size[1] - self.Margins[0] - self.Margins[2])
|
||||
self.Text_rect = (self.Margins[1], self.Margins[0], txs[0], txs[1])
|
||||
if not landscape:
|
||||
self.Surface = cairo.PDFSurface (filename, self.Size[0]*Mag, self.Size[1]*Mag)
|
||||
else:
|
||||
self.Surface = cairo.PDFSurface (filename, self.Size[1]*Mag, self.Size[0]*Mag)
|
||||
self.cr = cairo.Context (self.Surface)
|
||||
self.cr.scale (Mag, Mag) # Normalizing the canvas
|
||||
if landscape:
|
||||
self.cr.translate(0,self.Size[0])
|
||||
self.cr.rotate(-math.pi/2)
|
||||
|
||||
def default_width(cr, factor = 1.0):
|
||||
return max(cr.device_to_user_distance(0.1*factor, 0.1*factor))
|
||||
|
||||
def set_color(cr, rgba):
|
||||
if len(rgba) == 3:
|
||||
cr.set_source_rgb(*rgba)
|
||||
else:
|
||||
cr.set_source_rgba(*rgba)
|
||||
|
||||
def draw_shadow(cr, rect, thickness, shadow_color = (0,0,0,0.3)):
|
||||
if thickness <= 0: return
|
||||
f = thickness
|
||||
x, y, w, h = rect
|
||||
cr.move_to(x + f, y + h)
|
||||
cr.rel_line_to(0, f); cr.rel_line_to(w, 0); cr.rel_line_to(0, -h)
|
||||
cr.rel_line_to(-f, 0); cr.rel_line_to(0, h - f); cr.rel_line_to(-w + f, 0);
|
||||
set_color(cr, shadow_color)
|
||||
cr.close_path(); cr.fill();
|
||||
|
||||
def draw_box(cr, rect, stroke_rgba = (), fill_rgba = (), width_scale = 1.0, shadow = 0):
|
||||
if (width_scale <= 0): return
|
||||
draw_shadow(cr, rect, shadow)
|
||||
x, y, w, h = rect
|
||||
cr.move_to(x, y)
|
||||
cr.rel_line_to(w, 0)
|
||||
cr.rel_line_to(0, h)
|
||||
cr.rel_line_to(-w, 0)
|
||||
cr.close_path()
|
||||
if fill_rgba:
|
||||
set_color(cr, fill_rgba)
|
||||
cr.fill_preserve()
|
||||
if stroke_rgba:
|
||||
set_color(cr, stroke_rgba)
|
||||
cr.set_line_width(default_width(cr, width_scale))
|
||||
cr.stroke()
|
||||
|
||||
def draw_str(cr, text, rect, stretch = -1, stroke_rgba = (), align = 0, bbox = False,
|
||||
font = "Times", slant = cairo.FONT_SLANT_NORMAL, weight = cairo.FONT_WEIGHT_NORMAL,
|
||||
measure = '', shadow = False):
|
||||
x, y, w, h = rect
|
||||
cr.save()
|
||||
cr.select_font_face(font, slant, weight)
|
||||
if not measure: measure = text
|
||||
te = cr.text_extents(measure)
|
||||
tw, th = te[2], te[3]
|
||||
cr.translate(x, y + h)
|
||||
ratio, tratio = w*1.0/h, tw*1.0/th;
|
||||
xratio, yratio = tw*1.0/w, th*1.0/h;
|
||||
if stretch < 0: stretch = 1 if xratio >= yratio else 2
|
||||
if stretch == 0: bbw, bbh = w, h;
|
||||
elif stretch == 1: bbw, bbh = tw, tw/ratio; cr.scale(1.0/xratio, 1.0/xratio)
|
||||
elif stretch == 2: bbw, bbh = th*ratio, th; cr.scale(1.0/yratio, 1.0/yratio)
|
||||
elif stretch == 3: bbw, bbh = tw, th; cr.scale(1.0/xratio, 1.0/yratio)
|
||||
te = cr.text_extents(text)
|
||||
tw,th = te[2], te[3]
|
||||
if align == 1: px, py = bbw - tw, 0
|
||||
elif align == 2: px, py = (bbw-tw)/2.0, 0
|
||||
else: px, py = 0, 0
|
||||
cr.set_line_width(default_width(cr))
|
||||
if shadow:
|
||||
cr.set_source_rgba(0, 0, 0, 0.5)
|
||||
cr.move_to(px + default_width(cr, 5), py + default_width(cr, 5))
|
||||
cr.show_text(text)
|
||||
cr.move_to(px, py)
|
||||
if stroke_rgba: set_color(cr, stroke_rgba)
|
||||
cr.show_text(text)
|
||||
if bbox: draw_box(cr, (0, 0, bbw, -bbh), stroke_rgba)
|
||||
cr.restore()
|
0
style/__init__.py
Normal file
0
style/__init__.py
Normal file
58
style/bw.py
Normal file
58
style/bw.py
Normal file
@ -0,0 +1,58 @@
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
# --- style.default ---
|
||||
|
||||
# day of week
|
||||
class dow:
|
||||
fg = (.33,.33,.33)
|
||||
frame_thickness = 1.0
|
||||
frame = (0.8,0.8,0.8)
|
||||
font = "Arial"
|
||||
|
||||
# day of month
|
||||
class dom:
|
||||
bg = (1,1,1)
|
||||
frame = (0.8,0.8,0.8)
|
||||
frame_thickness = 1.0
|
||||
fg = (0.2,0.2,0.2)
|
||||
font = "Times New Roman"
|
||||
header = (0.5,0.5,0.5)
|
||||
footer = header
|
||||
header_font = footer_font = "Arial"
|
||||
|
||||
class dom_weekend(dom):
|
||||
bg = (0.95,0.95,0.95)
|
||||
fg = (0,0,0)
|
||||
font = "Times New Roman Bold"
|
||||
|
||||
class dom_holiday(dom):
|
||||
fg = (0,0,0)
|
||||
header = (0,0,0)
|
||||
font = "Times New Roman Bold"
|
||||
|
||||
class dom_weekend_holiday_style(dom_holiday):
|
||||
bg = (0,0,0)
|
||||
|
||||
from lib.render import color_mix
|
||||
|
||||
class month:
|
||||
font = "Times New Roman Bold"
|
||||
frame = (0,0,0)
|
||||
bg = (1,1,1)
|
||||
color_map = ((1,1,1),)*13
|
||||
box_shadow = False
|
||||
text_shadow = False
|
64
style/default.py
Normal file
64
style/default.py
Normal file
@ -0,0 +1,64 @@
|
||||
# callirhoe - high quality calendar rendering
|
||||
# Copyright (C) 2012 George M. Tzoumas
|
||||
|
||||
# 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 3 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, see http://www.gnu.org/licenses/
|
||||
|
||||
# --- style.default ---
|
||||
|
||||
# day of week
|
||||
class dow:
|
||||
fg = (0,0,1)
|
||||
frame_thickness = 1.0
|
||||
frame = (0.8,0.8,0.8)
|
||||
font = "Arial"
|
||||
|
||||
# day of month
|
||||
class dom:
|
||||
bg = (1,1,1)
|
||||
frame = (0.8,0.8,0.8)
|
||||
frame_thickness = 1.0
|
||||
fg = (0.2,0.2,0.2)
|
||||
font = "GFS Bodoni"
|
||||
header = (0.5,0.5,0.5)
|
||||
footer = header
|
||||
header_font = footer_font = "Arial"
|
||||
|
||||
class dom_weekend(dom):
|
||||
bg = (0.7,1,1)
|
||||
fg = (0,0,1)
|
||||
|
||||
class dom_holiday(dom):
|
||||
fg = (1,0,0)
|
||||
header = (1,0,0)
|
||||
|
||||
class dom_weekend_holiday_style(dom_holiday):
|
||||
bg = (0.7,1,1)
|
||||
|
||||
from lib.render import color_mix
|
||||
|
||||
class month:
|
||||
font = "GFS Artemisia Bold"
|
||||
frame = (0,0,0)
|
||||
bg = (1,1,1)
|
||||
winter = (0,0.4,1)
|
||||
spring = (0.0,0.5,0.0)
|
||||
summer = (1,0.3,0)
|
||||
autumn = (0.9,0.9,0)
|
||||
color_map = ((0,0,0), winter,
|
||||
color_mix(winter,spring,0.66), color_mix(winter,spring,0.33), spring, # april
|
||||
color_mix(spring,summer,0.66), color_mix(spring,summer,0.33), summer, # july
|
||||
color_mix(summer,autumn,0.66), color_mix(summer,autumn,0.33), autumn, # october
|
||||
color_mix(autumn,winter,0.66), color_mix(autumn,winter,0.33)) # december
|
||||
text_shadow = True
|
||||
box_shadow = True
|
Loading…
x
Reference in New Issue
Block a user