~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/share/extensions/perspective.py

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
"""
 
3
Copyright (C) 2005 Aaron Spike, aaron@ekips.org
 
4
 
 
5
This program is free software; you can redistribute it and/or modify
 
6
it under the terms of the GNU General Public License as published by
 
7
the Free Software Foundation; either version 2 of the License, or
 
8
(at your option) any later version.
 
9
 
 
10
This program is distributed in the hope that it will be useful,
 
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
GNU General Public License for more details.
 
14
 
 
15
You should have received a copy of the GNU General Public License
 
16
along with this program; if not, write to the Free Software
 
17
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 
 
19
Perspective approach & math by Dmitry Platonov, shadowjack@mail.ru, 2006
 
20
"""
 
21
import sys, inkex, os, re, simplepath, cubicsuperpath 
 
22
import gettext
 
23
_ = gettext.gettext
 
24
from ffgeom import *
 
25
try:
 
26
    from numpy import *
 
27
    from numpy.linalg import *
 
28
except:
 
29
    inkex.errormsg(_("Failed to import the numpy or numpy.linalg modules. These modules are required by this extension. Please install them and try again.  On a Debian-like system this can be done with the command, sudo apt-get install python-numpy."))
 
30
    exit()
 
31
 
 
32
try:
 
33
    from subprocess import Popen, PIPE
 
34
    bsubprocess = True
 
35
except:
 
36
    bsubprocess = False
 
37
 
 
38
uuconv = {'in':90.0, 'pt':1.25, 'px':1, 'mm':3.5433070866, 'cm':35.433070866, 'pc':15.0}
 
39
def unittouu(string):
 
40
    unit = re.compile('(%s)$' % '|'.join(uuconv.keys()))
 
41
    param = re.compile(r'(([-+]?[0-9]+(\.[0-9]*)?|[-+]?\.[0-9]+)([eE][-+]?[0-9]+)?)')
 
42
 
 
43
    p = param.match(string)
 
44
    u = unit.search(string)    
 
45
    if p:
 
46
        retval = float(p.string[p.start():p.end()])
 
47
    else:
 
48
        retval = 0.0
 
49
    if u:
 
50
        try:
 
51
            return retval * uuconv[u.string[u.start():u.end()]]
 
52
        except KeyError:
 
53
            pass
 
54
    return retval
 
55
 
 
56
class Project(inkex.Effect):
 
57
    def __init__(self):
 
58
        inkex.Effect.__init__(self)
 
59
    def effect(self):
 
60
        if len(self.options.ids) < 2:
 
61
            inkex.errormsg(_("This extension requires two selected paths."))
 
62
            exit()            
 
63
            
 
64
        #obj is selected second
 
65
        obj = self.selected[self.options.ids[0]]
 
66
        envelope = self.selected[self.options.ids[1]]
 
67
        if obj.get(inkex.addNS('type','sodipodi')):
 
68
            inkex.errormsg(_("The first selected object is of type '%s'.\nTry using the procedure Path | Object to Path." % obj.get(inkex.addNS('type','sodipodi'))))
 
69
            exit()
 
70
        if obj.tag == inkex.addNS('path','svg') or obj.tag == inkex.addNS('g','svg'):
 
71
            if envelope.tag == inkex.addNS('path','svg'):
 
72
                path = cubicsuperpath.parsePath(envelope.get('d'))
 
73
                if len(path) < 1 or len(path[0]) < 4:
 
74
                    inkex.errormsg(_("This extension requires that the second selected path be four nodes long."))
 
75
                    exit()
 
76
                dp = zeros((4,2), dtype=float64)
 
77
                for i in range(4):
 
78
                    dp[i][0] = path[0][i][1][0]
 
79
                    dp[i][1] = path[0][i][1][1]
 
80
 
 
81
                #query inkscape about the bounding box of obj
 
82
                q = {'x':0,'y':0,'width':0,'height':0}
 
83
                file = self.args[-1]
 
84
                id = self.options.ids[0]
 
85
                for query in q.keys():
 
86
                    if bsubprocess:
 
87
                        p = Popen('inkscape --query-%s --query-id=%s "%s"' % (query,id,file), shell=True, stdout=PIPE, stderr=PIPE)
 
88
                        rc = p.wait()
 
89
                        q[query] = float(p.stdout.read())
 
90
                        err = p.stderr.read()
 
91
                    else:
 
92
                        f,err = os.popen3('inkscape --query-%s --query-id=%s "%s"' % (query,id,file))[1:]
 
93
                        q[query] = float(f.read())
 
94
                        f.close()
 
95
                        err.close()
 
96
                sp = array([[q['x'], q['y']+q['height']],[q['x'], q['y']],[q['x']+q['width'], q['y']],[q['x']+q['width'], q['y']+q['height']]], dtype=float64)
 
97
            else:
 
98
                if envelope.tag == inkex.addNS('g','svg'):
 
99
                    inkex.errormsg(_("The second selected object is a group, not a path.\nTry using the procedure Object | Ungroup."))
 
100
                else:
 
101
                    inkex.errormsg(_("The second selected object is not a path.\nTry using the procedure Path | Object to Path."))
 
102
                exit()
 
103
        else:
 
104
            inkex.errormsg(_("The first selected object is not a path.\nTry using the procedure Path | Object to Path."))
 
105
            exit()
 
106
 
 
107
        solmatrix = zeros((8,8), dtype=float64)
 
108
        free_term = zeros((8), dtype=float64)
 
109
        for i in (0,1,2,3):
 
110
            solmatrix[i][0] = sp[i][0]
 
111
            solmatrix[i][1] = sp[i][1]
 
112
            solmatrix[i][2] = 1
 
113
            solmatrix[i][6] = -dp[i][0]*sp[i][0]
 
114
            solmatrix[i][7] = -dp[i][0]*sp[i][1]
 
115
            solmatrix[i+4][3] = sp[i][0]
 
116
            solmatrix[i+4][4] = sp[i][1]
 
117
            solmatrix[i+4][5] = 1
 
118
            solmatrix[i+4][6] = -dp[i][1]*sp[i][0]
 
119
            solmatrix[i+4][7] = -dp[i][1]*sp[i][1]
 
120
            free_term[i] = dp[i][0]
 
121
            free_term[i+4] = dp[i][1]
 
122
 
 
123
        res = solve(solmatrix, free_term)
 
124
        projmatrix = array([[res[0],res[1],res[2]],[res[3],res[4],res[5]],[res[6],res[7],1.0]],dtype=float64)
 
125
        if obj.tag == inkex.addNS("path",'svg'):
 
126
            self.process_path(obj,projmatrix)
 
127
        if obj.tag == inkex.addNS("g",'svg'):
 
128
            self.process_group(obj,projmatrix)
 
129
 
 
130
 
 
131
    def process_group(self,group,m):
 
132
        for node in group:
 
133
            if node.tag == inkex.addNS('path','svg'):
 
134
                self.process_path(node,m)
 
135
            if node.tag == inkex.addNS('g','svg'):
 
136
                self.process_group(node,m)    
 
137
 
 
138
 
 
139
    def process_path(self,path,m):
 
140
        d = path.get('d')
 
141
        p = cubicsuperpath.parsePath(d)
 
142
        for subs in p:
 
143
            for csp in subs:
 
144
                csp[0] = self.project_point(csp[0],m)
 
145
                csp[1] = self.project_point(csp[1],m)
 
146
                csp[2] = self.project_point(csp[2],m)
 
147
        path.set('d',cubicsuperpath.formatPath(p))
 
148
 
 
149
 
 
150
 
 
151
    def project_point(self,p,m):
 
152
        x = p[0]
 
153
        y = p[1]
 
154
        return [(x*m[0][0] + y*m[0][1] + m[0][2])/(x*m[2][0]+y*m[2][1]+m[2][2]),(x*m[1][0] + y*m[1][1] + m[1][2])/(x*m[2][0]+y*m[2][1]+m[2][2])]
 
155
 
 
156
if __name__ == '__main__':
 
157
    e = Project()
 
158
    e.affect()
 
159
 
 
160
 
 
161
# vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99