source: tracimagesvgmacro/0.11/imagesvg/web_ui.py

Last change on this file was 8063, checked in by Richard Liao, 13 years ago

fixed #7183 , support float width, height

File size: 6.0 KB
Line 
1# -*- coding: utf-8 -*-
2#----------------------------------------------------------------------------
3# Name:         web_ui.py
4# Purpose:      The image svg file handler module
5#
6# Author:       Richard Liao <richard.liao.i@gmail.com>
7#
8#----------------------------------------------------------------------------
9
10from trac.core import *
11from trac.web.chrome import *
12from trac.util.html import html
13
14from trac.web import IRequestHandler
15from trac.web.api import RequestDone, HTTPException
16from trac.attachment import Attachment
17from trac.wiki.api import IWikiMacroProvider
18
19from pkg_resources import resource_filename
20
21import sys, os
22import time
23import inspect
24
25__all__ = ['ImageSvg']
26
27class ImageSvg(Component):
28    revision = "$Rev$"
29    url = "$URL$"
30
31    implements(
32               IWikiMacroProvider, 
33               IRequestHandler, 
34               )
35
36    # IWikiMacroProvider methods
37    def get_macros(self):
38        yield "ImageSvg"
39       
40    def get_macro_description(self, name):
41        return inspect.getdoc(self.__class__)
42
43    def expand_macro(self, formatter, name, content):
44        # args will be null if the macro is called without parenthesis.
45        if not content:
46            return ''
47        # parse arguments
48        # we expect the 1st argument to be a filename (filespec)
49        args = content.split(',')
50        if len(args) == 0:
51           raise Exception("No argument.")
52        if len(args) == 3:
53           targetSize = "width='%(w)s'height='%(h)s'" % {'w': args[1].strip(), 'h': args[2].strip()}
54        else:
55           targetSize = None
56        filespec = args[0]
57        # parse filespec argument to get module and id if contained.
58        parts = filespec.split(':')
59        if len(parts) == 3:                 # module:id:attachment
60            if parts[0] in ['wiki', 'ticket']:
61                module, id, file = parts
62            else:
63                raise Exception("%s module can't have attachments" % parts[0])
64        elif len(parts) == 2:               # #ticket:attachment or WikiPage:attachment
65            # FIXME: do something generic about shorthand forms...
66            id, file = parts
67            if id and id[0] == '#':
68                module = 'ticket'
69                id = id[1:]
70            else:
71                module = 'wiki'
72        elif len(parts) == 1:               # attachment
73            file = filespec
74            parts = formatter.req.path_info.split("/")
75            if len(parts) >= 3:
76                module = parts[1]
77                id =''
78                for p in parts[2:]:
79                    if len(id) > 0:
80                        id = id + "/"
81                    id = id + p
82            elif len(parts) == 0:
83                module = "wiki"
84                id = "WikiStart"
85            else:
86                # limit of use
87                raise Exception("Cannot use this macro in this module (len(parts)=%d, file=%s, path_info=%s, parts=%s)" % (len(parts), file, formatter.req.path_info, parts))
88
89        else:
90            raise Exception( 'No filespec given' )
91
92        try:
93            attachment = Attachment(self.env, module, id, file)
94            org_path = attachment.path
95            try:
96                if targetSize is None:
97                    f = open(org_path, 'r')
98                    svg = f.readlines()
99                    f.close()
100                    svg = "".join(svg).replace('\n', '')
101                else:
102                    svg = targetSize
103                w = re.search('''width=["']([0-9]+\.?[0-9]?)(.*?)["']''', svg)
104                h = re.search('''height=["']([0-9]+\.?[0-9]?)(.*?)["']''', svg)
105                (w_val, w_unit) = w.group(1,2)
106                (h_val, h_unit) = h.group(1,2)
107                w_unit = w_unit.strip()
108                h_unit = h_unit.strip()
109
110                unitMapping = {
111                    "cm": 72 / 2.54,
112                    "mm": 72 / 25.4,
113                    "in": 72 / 1,
114                    "pc": 72 / 6,
115                    "": 1,
116                }
117
118                import math
119                if w_unit in unitMapping.keys():
120                    w_val = int(math.ceil(float(w_val) * unitMapping[w_unit]))
121                    h_val = int(math.ceil(float(h_val) * unitMapping[w_unit]))
122                    w_unit = "pt"
123                    h_unit = "pt"
124
125
126                dimensions = 'width="%(w_val)s%(w_unit)s" height="%(h_val)s%(h_unit)s"' % locals()
127            except:
128                dimensions = 'width="100%" height="100%"'
129
130            data = {
131                "base_url": self.env.base_url,
132                "module": module,
133                "id": id,
134                "file": file,
135                "dimensions": dimensions,
136                }
137            s = '''
138            <div>
139            <embed  type="image/svg+xml"
140                style="margin: 0pt; padding: 0pt;"
141                src="%(base_url)s/svg/attachments/%(module)s/%(id)s/%(file)s
142                %(dimensions)s
143                pluginspage="http://www.adobe.com/svg/viewer/install/">
144            </embed>
145            </div>
146            ''' % data
147            return s
148        except:
149            return '%s not found' % (filespec)
150
151    # IRequestHandler methods
152    def match_request(self, req):
153        return req.path_info.startswith("/svg")
154
155
156    def process_request(self, req):
157        if req.path_info.startswith("/svg"):
158            pathSegs = req.path_info.split("/")
159            image_path = "/".join(pathSegs[2:])
160            f = os.path.join(self.env.path, image_path)
161            try:
162                message = open(f).read()
163            except:
164                raise HTTPException(404)
165
166            req.send_response(200)
167            req.send_header('Cache-control', 'no-cache')
168            req.send_header('Expires', 'Fri, 01 Jan 1999 00:00:00 GMT')
169            req.send_header('Content-Type', 'image/svg+xml')
170            req.send_header('Content-Length', len(isinstance(message, unicode) and message.encode("utf-8") or message))
171            req.end_headers()
172
173            if req.method != 'HEAD':
174                req.write(message)
175            raise RequestDone
Note: See TracBrowser for help on using the repository browser.