callirhoe/lib/xcairo.py
geortz@gmail.com 21c3f79c9f first import
git-svn-id: https://callirhoe.googlecode.com/svn/trunk@5 81c8bb96-aa45-f2e2-0eef-c4fa4a15c6df
2012-07-17 20:44:12 +00:00

121 lines
4.7 KiB
Python

# -*- 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()