File: glal.py

package info (click to toggle)
cyclograph 1.7.1-1
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,136 kB
  • ctags: 705
  • sloc: python: 9,682; makefile: 5
file content (269 lines) | stat: -rw-r--r-- 9,878 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# -*- coding: utf-8 -*-
#glal.py
"""This module provides a graphic library abstraction layer for Cyclograph"""

# Copyright (C) 2008, 2009, 2010, 2011, 2012 Federico Brega, Pierluigi Villani

# 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.

from __future__ import print_function, unicode_literals

import sys
import os.path
import glal_selected
LIBRARY = glal_selected.library
(FD_OPEN, FD_SAVE) = range(2)

def Message(*args):
    """This funcion return the class that wraps the using messaging library"""
    if LIBRARY == 'cli':
        return Message_cli(*args)

def DeviceContext(*args):
    if LIBRARY == 'cli':
        return DeviceContext_cli(*args)

def Image(*args):
    if LIBRARY == 'cli':
        return Image_cli(*args)

def addstatusbartext(maingui, text):
    """Add text to main gui status bar"""
    if LIBRARY == 'cli':
        sys.stderr.write(text)

def FileDialog(parent, title, dirname, other, file_types, rw, filename=None):
    """Return File dialog """
    return gui.FileDialog(parent, title, dirname, filename, other,
                               file_types, rw, FD_OPEN, FD_SAVE)

### Begin of cli classes ###

class Message_cli():
    """CLI interfaces doesn't need to update their view
    because they haven't got any
    """
    def send(self, *args):
        """ send method not used for cli"""
        pass
    def subscribe(self, *args):
        """ subscribe method not used for cli"""
        pass

def DeviceContext_cli(*args):
    """ Get a device contex for CLI default is an svg generator."""
    return DeviceContext_svg(*args)

class Image_cli():
    """ Image cli not used"""
    pass
### End of cli classes ###

### Begin of SVG ###
class DeviceContext_svg():
    """Device Context class to draw sgv files"""
    colors = {'white' : '#ffffff',
              'black' : '#000000'}
    def setcolor(self, color):
        """ Set color converting to svg compatible format."""
        if type(color) == type(unicode()):
            if color.startswith('#'):
                return color
            elif color.startswith('rgb'):
                tuple_ = map(int, color[4:-1].split(','))
                return tupletocss(tuple_)
            else:
                return self.colors[color]
        else:
            sys.stderr.write("Color type unknown: "+color+" "+str(type(color))+"\n")
            return False

    def init_draw_surf(self, size, p3d):
        """ Init draw surface"""
        self.size_x = size[0]
        self.size_y = size[1]
        self.pencolor = None
        self.lineargcount = 0
        self.pensize = 0
        self.svg = '''<?xml version="1.0" standalone="no"?>
<!-- Created with CycloGraph (http://cyclograph.sourceforge.net) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="%d" height="%d" version="1.1"
xmlns="http://www.w3.org/2000/svg">\n
''' % size
        if p3d:
            self.brushcolor = '#ffffff' #white background
            self.svg += '''<rect x="0" y="0" width="%i" height="%i" fill=" %s"/>
''' % ( self.size_x, self.size_y, self.brushcolor)
    def shear(self, shear):
        self.shear = shear
        if shear:
            self.svg += '<g transform="skewY(%f)">' % (shear*50,)
    def getsize(self):
        """ Return size"""
        return (self.size_x, self.size_y)
    def gradfill(self, rect, startcolor, endcolor):
        """ Fill gradient"""
        self.svg += '''
<defs>
<linearGradient id="background" x1="0%%" y1="0%%" x2="0%%" y2="100%%">
<stop offset="0%%" style="stop-color:%s;stop-opacity:1;"/>
<stop offset="80%%" style="stop-color:%s;stop-opacity:1;"/>
</linearGradient>
</defs>
<rect width="%d" height="%d" style="fill:url(#background)"/>
''' % (self.setcolor(startcolor), self.setcolor(endcolor),
        rect[2] - rect[0], rect[3] - rect[1])
    def setpen(self, color, size):
        """ Set pen's size and color"""
        self.pencolor = self.setcolor(color)
        self.pensize = str(size)
    def setfont(self, fontdict):
        """ Set font"""
        self.dim = fontdict['dim']
        self.font = "font-family:%s;font-size:%spx" % (fontdict['des'], self.dim)
    def drawtext(self, text, pos_x, pos_y):
        """ Draw text at position pos_x,pos_y """
        self.drawrotatedtext(text, pos_x, pos_y, 0)
    def gettextwidth(self, text):
        """ Return text length"""
        return self.dim*len(text)-30#TODO: check if there is a more accurate method
    def gettextheight(self, text):
        """ Return text height"""
        return self.dim #TODO: check if there is a more accurate method
    def drawline(self, pos_x0, pos_y0, pos_x1, pos_y1):
        """ draw line"""
        self.svg += '''<line x1="%d" y1="%d" x2="%d" y2="%d"
style="stroke:%s;stroke-width:%s"/>
''' % (pos_x0, pos_y0, pos_x1, pos_y1, self.pencolor, self.pensize)
    def setlineargradientbrush(self, colorlist, startp, endp):
        """ Get a linear gradient from startp to endp, using colors in colorlist.
        The elments of colorlist are tuple in the format (color, realtive position)."""
        self.svg += '''<defs>
<linearGradient id="linearg%s" gradientUnits="userSpaceOnUse" x1="%s" y1="%s" x2="%s" y2="%s">
''' % (self.lineargcount, startp[0], startp[1], endp[0], endp[1])
        for color in colorlist:
            self.svg += '''<stop offset="%s%%" style="stop-color:%s;stop-opacity:1;"/>
''' % (color[1]*100, self.setcolor(color[0]))
        self.svg += '''</linearGradient>
</defs>
'''
        self.brushcolor = "url(#linearg%s)" % (self.lineargcount)
        self.lineargcount = self.lineargcount + 1

    def setbrush(self, color):
        """ Set brush color"""
        self.brushcolor = self.setcolor(color)
    def drawrectangle(self, pos_x0, pos_y0, width, height):
        """ Draw rectangle"""
        self.svg += '''<rect x="%i" y="%i" width="%i" height="%i"
style="fill: %s;stroke:%s;stroke-width:%s"/>
''' % (pos_x0, pos_y0, width, height, self.brushcolor,
       self.pencolor, self.pensize)
    def drawrotatedtext(self, text, pos_x, pos_y, angle):
        """Draw the text given, rotated by the angle."""
        dy = self.dim
        self.svg += '<text x="%i" y="%i" style="%s;fill:%s"' % (pos_x, pos_y+dy, self.font, self.pencolor)
        if angle:
            self.svg += ' transform="rotate(%d,%d,%d)"' % (-angle, pos_x, pos_y)
        self.svg += '''>%s</text>
''' % (text)
    def drawpolygon(self, sequence):
        """ Draw polygon"""
        if len(sequence) < 2:
            return
        self.svg += '<polygon points="'
        for pt in sequence:
            self.svg += '%d, %d ' % (pt[0], pt[1])
        self.svg += '"\n style="fill:%s;stroke:%s;stroke-width:%s"/>\n' \
                % (self.brushcolor, self.pencolor, self.pensize)
    def startpath(self, point):
        """ Start a path in the specified point,"""
        self.svg += '''<path style="fill:%s;stroke:%s;stroke-width:%s;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="M %d,%d''' % (self.brushcolor, self.pencolor, self.pensize, point[0], point[1])
        self.path = point
        return self.path
    def drawpathlineto(self, path, point):
        """ Draw a straight line from the last point to the given point."""
        self.svg += ''' L %d,%d''' % (point[0], point[1])
        self.path = point
    def drawpathcubicto(self, path, controlpoints):
        """ Draw a cubic BeziƩr frome the last point using the given list of
        three control points."""
        self.svg += ''' C %d,%d %d,%d %d,%d''' % (controlpoints[0][0], controlpoints[0][1],
        controlpoints[1][0], controlpoints[1][1],
        controlpoints[2][0], controlpoints[2][1])
        self.path = controlpoints[2]
    def endpath(self, path):
        """ Show the path."""
        self.svg += '"/>\n'
    def end_draw(self):
        """ end drawing"""
        if self.shear:
            self.svg += '</g>'
        self.svg += "</svg>\n"
        print(self.svg)

class Image_svg():
    """ svg image"""
    def __init__(self, size_x,  size_y, plotfnct):
        self.size = (size_x,  size_y)
        self.plotfnct = plotfnct
        self.svg = ""
    def plot(self, settings):
        """draw svg image"""
        dcwrpp = DeviceContext_svg()
        dcwrpp.init_draw_surf(self.size, settings['3d'])
        self.plotfnct(settings, dcwrpp)
        #dcwrpp.end_draw()
        self.svg = dcwrpp.svg
        if settings['3d']:
            self.svg += "</g>\n"
        self.svg += "</svg>\n"
    def savetofile(self, path, format):
        """ Save to file"""
        if format == 'svg':
            try:
                fid = open(path, 'wb')
                fid.write(self.svg)
            finally:
                fid.close()

def tupletocss(tuple_):
    """ convert tuple to css"""
    numb = tuple_[0] << 16 | tuple_[1] << 8 | tuple_[2]
    return '#' + hex(numb).split('x')[1].zfill(6)
### End of SVG ###

if LIBRARY == 'qt':
    #import sip
    #sip.setapi('QString', 2)

    #from PyQt4 import QtGui
    #from PyQt4 import QtCore

    from qt.glal import *
    #import qt.gui as gui

elif LIBRARY == 'gtk3':
    from gtk3.glal import *

elif LIBRARY == 'cli':
    # HACK to make print to utf8 also when stdout is piped
    # probably better to do something like
    #    stdout = codecs.EncodedFile(sys.stdout, 'utf-8')
    # and use it to write the svg.
    reload(sys)
    sys.setdefaultencoding('utf8')


# vim:sw=4:softtabstop=4:expandtab