| 1 | # Name: Chris Lee |
|---|
| 2 | # email: chunghualee@gmail.com |
|---|
| 3 | # developed for trac 0.10.4 |
|---|
| 4 | # usage: [[svgdw(your_attachement)]] |
|---|
| 5 | # works on FireFox, sorry for IE user. |
|---|
| 6 | |
|---|
| 7 | # The attached SVG file is copied to another place, outside the trac. |
|---|
| 8 | # The returned HTML code will generate an object with link to that file |
|---|
| 9 | # Before use this macro: |
|---|
| 10 | # in trac.ini, add render_unsafe_content = true in [attachment] |
|---|
| 11 | # Set this to the directory you want the images stored in. Web server must have write access. |
|---|
| 12 | images_folder = 'D:/web/phpBB/branches/phpBB-2.0.22/files/svgdw' |
|---|
| 13 | # Base URL of the folder. |
|---|
| 14 | images_url = 'http://ezsrv/files/svgdw' |
|---|
| 15 | |
|---|
| 16 | # Adapted from the Image.py macro created by Shun-ichi Goto <gotoh@taiyo.co.jp> |
|---|
| 17 | # |
|---|
| 18 | # Display image in attachment or repository into the wiki page. |
|---|
| 19 | # |
|---|
| 20 | # First argument is filename (file spec). |
|---|
| 21 | # |
|---|
| 22 | # The file specification may refer attachments: |
|---|
| 23 | # * 'module:id:file', with module being either 'wiki' or 'ticket', |
|---|
| 24 | # to refer to the attachment named 'file' in the module:id object |
|---|
| 25 | # * 'id:file' same as above, module defaulted to 'wiki' (id can be dir/dir/node) |
|---|
| 26 | # * 'file' to refer to a local attachment named 'file' |
|---|
| 27 | # (but then, this works only from within a wiki page or a ticket). |
|---|
| 28 | # |
|---|
| 29 | # Ex. |
|---|
| 30 | # [[Image(photo.jpg)]] # simplest |
|---|
| 31 | # |
|---|
| 32 | # You can use image from other page, other ticket or other module. |
|---|
| 33 | # [[Image(OtherPage:foo.bmp)]] # if current module is wiki |
|---|
| 34 | # [[Image(base/sub:bar.bmp)]] # from hierarchical wiki page |
|---|
| 35 | # [[Image(#3:baz.bmp)]] # if in a ticket, point to #3 |
|---|
| 36 | # [[Image(ticket:36:boo.jpg)]] |
|---|
| 37 | # [[Image(source:/images/bee.jpg)]] # straight from the repository! |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | import os |
|---|
| 41 | import re |
|---|
| 42 | import string |
|---|
| 43 | import shutil |
|---|
| 44 | import md5 |
|---|
| 45 | from trac.attachment import Attachment |
|---|
| 46 | |
|---|
| 47 | def execute(hdf, txt, env): |
|---|
| 48 | # args will be null if the macro is called without parenthesis. |
|---|
| 49 | if not txt: |
|---|
| 50 | return '' |
|---|
| 51 | # parse arguments |
|---|
| 52 | # we expect the 1st argument to be a filename (filespec) |
|---|
| 53 | args = txt.split(',') |
|---|
| 54 | if len(args) == 0: |
|---|
| 55 | raise Exception("No argument.") |
|---|
| 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 | # get current module and id from hdf |
|---|
| 75 | module = hdf.getValue('args.mode', 'wiki') |
|---|
| 76 | if module == 'wiki': |
|---|
| 77 | id = hdf.getValue('args.page', 'WikiStart') |
|---|
| 78 | elif module == 'ticket': |
|---|
| 79 | id = hdf['args.id'] # for ticket |
|---|
| 80 | else: |
|---|
| 81 | # limit of use |
|---|
| 82 | raise Exception('Cannot use this macro in %s module' % module) |
|---|
| 83 | else: |
|---|
| 84 | raise Exception( 'No filespec given' ) |
|---|
| 85 | try: |
|---|
| 86 | attachment = Attachment(env, module, id, file) |
|---|
| 87 | org_path = attachment.path |
|---|
| 88 | return svg_render(images_folder, images_url, org_path) |
|---|
| 89 | except: |
|---|
| 90 | return '%s not found' % (filespec) |
|---|
| 91 | |
|---|
| 92 | def svg_render(images_folder, images_url, org_path): |
|---|
| 93 | md5sum = md5.new(org_path).hexdigest() |
|---|
| 94 | img_path = '%s/%s.svg' % (images_folder, md5sum) |
|---|
| 95 | url = '%s/%s.svg' % (images_url, md5sum) |
|---|
| 96 | img_time=org_time='' |
|---|
| 97 | try: |
|---|
| 98 | if not os.access(img_path, os.F_OK): |
|---|
| 99 | shutil.copy2(org_path, img_path) |
|---|
| 100 | else: |
|---|
| 101 | org_time = os.path.getmtime(org_path) |
|---|
| 102 | img_time = os.path.getmtime(img_path) |
|---|
| 103 | if org_time != img_time: |
|---|
| 104 | shutil.copy2(org_path, img_path) |
|---|
| 105 | except: |
|---|
| 106 | raise Exception( 'can not render svg file') |
|---|
| 107 | try: |
|---|
| 108 | f = open(img_path, 'r') |
|---|
| 109 | svg = f.readlines() |
|---|
| 110 | f.close() |
|---|
| 111 | svg = "".join(svg).replace('\n', '') |
|---|
| 112 | w = re.search('width="([0-9]+)(.*?)" ', svg) |
|---|
| 113 | h = re.search('height="([0-9]+)(.*?)"', svg) |
|---|
| 114 | (w_val, w_unit) = w.group(1,2) |
|---|
| 115 | (h_val, h_unit) = h.group(1,2) |
|---|
| 116 | # Graphviz seems to underestimate height/width for SVG images, |
|---|
| 117 | # so we have to adjust them. The correction factor seems to be constant. |
|---|
| 118 | [w_val, h_val] = [ 1.2 * x for x in (int(w_val), int(h_val))] |
|---|
| 119 | dimensions = 'width="%(w_val)s%(w_unit)s" height="%(h_val)s%(h_unit)s"' % locals() |
|---|
| 120 | except: |
|---|
| 121 | dimensions = 'width="100%" height="100%"' |
|---|
| 122 | return '<object type="image/svg+xml" data="%s" %s>\ |
|---|
| 123 | <embed src="%s" type="image/svg+xml"\ |
|---|
| 124 | PLUGINSPAGE="http://www.adobe.com/svg/viewer/install/"></embed>\ |
|---|
| 125 | </object>\n' % (url,dimensions,url) |
|---|
| 126 | |
|---|