+++ /dev/null
-#!/usr/bin/env python
-
-from __future__ import division
-import web
-import sys, os, re
-from storm.locals import *
-from ruler import RulerImage
-
-# the url map for the application
-urls = ( '/', 'index',
- '/ruler_([0-9\.]+)px_([0-9\.]+)([A-Za-z]+).(svg|png|jpg)', 'ruler_img',
- '/show/(.*(svg|png|jpg))', 'ruler',
- '/gallery(.*)', 'gallery',
- '/delete/(\d+)', 'delete',
- '/undelete/(\d+)', 'undelete')
-
-database = create_database("sqlite:ruler_web.db")
-store = Store(database)
-
-class SavedRuler(object):
- __storm_table__ = "gallery"
- id = Int(primary=True)
- pixel_width = Float()
- unit_width = Float()
- model = Unicode()
- units = Unicode()
- show = Int()
-
- def __init__(self, **kw):
- self.pixel_width = kw['pixel_width']
- self.unit_width = kw['unit_width']
- self.units = kw['units']
- self.model = kw['model']
-
- def cm_width(self):
- if self.units == 'centimeters':
- return self.unit_width
- elif self.units == 'inches':
- return(self.unit_width * 2.54)
-
- def in_width(self):
- if self.units == 'inches':
- return self.unit_width
- elif self.units == 'centimeters':
- return(self.unit_width * 0.3937)
-
-
-class index:
- def GET(self):
- web.header("Content-Type","text/html; charset=utf-8")
- web.render('index.tmpl')
-
- def POST(self):
- input = web.input()
-
- pixel_width = input['pixel_width']
- unit_width = input['unit_width']
- units = input['units']
- ruler_url = 'ruler_%spx_%s%s.png' % (pixel_width, unit_width, units)
- web.redirect('/show/%s' % ruler_url)
-
-class ruler:
- def GET(self, ruler_url, ext):
- web.debug('test test')
- if web.input().has_key('fromgallery'):
- fromgallery = True
- else:
- fromgallery = False
-
- other_unit, other_unit_url = get_other_units(ruler_url)
-
- web.header("Content-Type","text/html; charset=utf-8")
- web.render('show_ruler.tmpl')
-
-
-class ruler_img:
- def GET(self, pixel_width=None, unit_width=None, units=None, ext=None):
-
- # TODO check to see if it's a format that we support
-
- # set ruler height to be 200 px always
- pixel_width = float(pixel_width)
- unit_width = float(unit_width)
-
- ruler_height = 200
-
- scale = pixel_width / unit_width
- ruler_length = int(unit_width)
-
- ruler = Ruler(scale, units, ruler_height, ruler_length)
-
- # print the header
- if ext == 'svg': ext = 'svg+xml'
- web.header("Content-Type", "image/%s" % ext)
-
- if ext == 'svg+xml':
- sys.stdout.write(ruler.output())
- else:
- pin, pout = os.popen2('convert -size %sx%s - %s:-' % \
- (pixel_width, ruler_height, ext))
-
- pin.write(ruler.output())
- pin.close()
- sys.stdout.write(pout.read())
-
-class gallery:
- def GET(self, ruler_url):
-
- if ruler_url:
- pixel_width, unit_width, units = process_ruler_url(ruler_url)[0:3]
-
- rulers = store.find(SavedRuler, SavedRuler.show == 1)
- rulers.order_by(SavedRuler.model)
-
- web.render('gallery.tmpl')
-
- def POST(self):
- input = web.input()
-
- new_ruler = SavedRuler(pixel_width=float(input['pixel_width']),
- unit_width=float(input['unit_width']),
- units=unicode(input['units']),
- model=unicode(input['model']))
-
- store.add(new_ruler)
- store.commit()
-
- web.redirect('gallery')
-
-class delete:
- def GET(self, id):
- ruler = store.get(SavedRuler, int(id))
- ruler.show = 0
- store.commit()
- web.redirect('/gallery')
-
-
-class undelete:
- def GET(self, id):
- ruler = store.get(SavedRuler, int(id))
- ruler.show = 1
- store.commit()
- web.redirect('/gallery')
-
-def get_other_units(url):
- pixel_width, unit_width, units = process_ruler_url(url)[0:3]
- ruler = SavedRuler(pixel_width=float(pixel_width),
- unit_width=float(unit_width),
- units=unicode(units),
- model=unicode(model))
-
-def process_ruler_url(url):
- url = re.sub(r'^/?(ruler.*)$', r'\1', url)
- return(re.match( r'ruler_([\d\.]+)px_([\d\.]+)(\w+).(png|svg|jpg)',
- url).groups())
-
-# render the site template here so that i can use it later
-web.render('site.tmpl', None, True, 'site')
-
-web.webapi.internalerror = web.debugerror
-if __name__ == "__main__":
- web.run(urls, globals(), web.reloader)
-
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.45.1"
+ width="885.40912"
+ height="138.02615"
+ sodipodi:docname="yourule_banner.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ sodipodi:docbase="/tmp"
+ version="1.0"
+ inkscape:export-filename="/tmp/yourule_banner.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <metadata
+ id="metadata191">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs189">
+ <linearGradient
+ id="linearGradient3312">
+ <stop
+ style="stop-color:#032466;stop-opacity:1;"
+ offset="0"
+ id="stop3314" />
+ <stop
+ id="stop4311"
+ offset="0.51612902"
+ style="stop-color:#829ac8;stop-opacity:1;" />
+ <stop
+ id="stop4309"
+ offset="1"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient3312"
+ id="linearGradient3326"
+ x1="-1"
+ y1="85.749016"
+ x2="884.20636"
+ y2="85.749016"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1.0001854,0,0,0.7932477,1.0195184,0.9928715)" />
+ </defs>
+ <sodipodi:namedview
+ inkscape:cy="59.142887"
+ inkscape:cx="324.2777"
+ inkscape:zoom="0.61490055"
+ inkscape:window-height="587"
+ inkscape:window-width="860"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-x="56"
+ inkscape:window-y="54"
+ inkscape:current-layer="svg2">
+ <sodipodi:guide
+ orientation="vertical"
+ position="13.823373"
+ id="guide4313" />
+ <sodipodi:guide
+ orientation="vertical"
+ position="-4.606614"
+ id="guide4315" />
+ </sodipodi:namedview>
+ <rect
+ height="136.24471"
+ width="883.62769"
+ y="0.8907271"
+ x="0.8907271"
+ id="rect4"
+ style="fill:url(#linearGradient3326);fill-opacity:1;stroke:#000000;stroke-width:1.78145421;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none"
+ rx="10"
+ ry="10"
+ inkscape:export-filename="/tmp/yourule_banner.png"
+ inkscape:export-xdpi="90.12661"
+ inkscape:export-ydpi="90.12661" />
+ <g
+ id="g4349"
+ style="stroke:#727272;stroke-opacity:1"
+ transform="matrix(1.0001854,0,0,0.7932477,1.9332533e-2,0.1996237)"
+ inkscape:export-filename="/tmp/yourule_banner.png"
+ inkscape:export-xdpi="90.12661"
+ inkscape:export-ydpi="90.12661">
+ <g
+ id="g4319"
+ style="stroke:#727272;stroke-opacity:1">
+ <line
+ y2="53.914421"
+ x2="15.607819"
+ y1="0.88384312"
+ x1="15.607819"
+ id="line8"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="30.331795"
+ y1="0.88384312"
+ x1="30.331795"
+ id="line10"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="45.055771"
+ y1="0.88384312"
+ x1="45.055771"
+ id="line14"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="107.45097"
+ x2="60.9314"
+ y1="1.3898103"
+ x1="60.9314"
+ id="line16"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="74.503723"
+ y1="0.88384312"
+ x1="74.503723"
+ id="line20"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="89.227707"
+ y1="0.88384312"
+ x1="89.227707"
+ id="line22"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="103.95169"
+ y1="0.88384312"
+ x1="103.95169"
+ id="line26"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="118.67566"
+ y1="0.88384312"
+ x1="118.67566"
+ id="line28"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="133.39964"
+ y1="0.88384312"
+ x1="133.39964"
+ id="line32"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="148.12361"
+ y1="0.88384312"
+ x1="148.12361"
+ id="line34"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="162.84758"
+ y1="0.88384312"
+ x1="162.84758"
+ id="line38"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="177.57156"
+ y1="0.88384312"
+ x1="177.57156"
+ id="line40"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="192.29555"
+ y1="0.88384312"
+ x1="192.29555"
+ id="line44"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="207.01952"
+ y1="0.88384312"
+ x1="207.01952"
+ id="line46"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="221.7435"
+ y1="0.88384312"
+ x1="221.7435"
+ id="line50"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="236.46745"
+ y1="0.88384312"
+ x1="236.46745"
+ id="line52"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="251.19145"
+ y1="0.88384312"
+ x1="251.19145"
+ id="line56"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="265.91541"
+ y1="0.88384312"
+ x1="265.91541"
+ id="line58"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="280.6394"
+ y1="0.88384312"
+ x1="280.6394"
+ id="line62"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="295.36337"
+ y1="0.88384312"
+ x1="295.36337"
+ id="line64"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="310.08737"
+ y1="0.88384312"
+ x1="310.08737"
+ id="line68"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="324.81134"
+ y1="0.88384312"
+ x1="324.81134"
+ id="line70"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="339.53531"
+ y1="0.88384312"
+ x1="339.53531"
+ id="line74"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="354.25928"
+ y1="0.88384312"
+ x1="354.25928"
+ id="line76"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="368.98328"
+ y1="0.88384312"
+ x1="368.98328"
+ id="line80"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="383.70724"
+ y1="0.88384312"
+ x1="383.70724"
+ id="line82"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="53.914421"
+ x2="398.43121"
+ y1="0.88384312"
+ x1="398.43121"
+ id="line86"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ <line
+ y2="106.945"
+ x2="413.15518"
+ y1="0.88384312"
+ x1="413.15518"
+ id="line88"
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1" />
+ </g>
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line92"
+ x1="427.87918"
+ y1="0.88384312"
+ x2="427.87918"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line94"
+ x1="442.60315"
+ y1="0.88384312"
+ x2="442.60315"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line98"
+ x1="457.32715"
+ y1="0.88384312"
+ x2="457.32715"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line100"
+ x1="472.05109"
+ y1="0.88384312"
+ x2="472.05109"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line104"
+ x1="486.77505"
+ y1="0.88384312"
+ x2="486.77505"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line106"
+ x1="501.49905"
+ y1="0.88384312"
+ x2="501.49905"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line110"
+ x1="516.22302"
+ y1="0.88384312"
+ x2="516.22302"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line112"
+ x1="530.94696"
+ y1="0.88384312"
+ x2="530.94696"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line116"
+ x1="545.67096"
+ y1="0.88384312"
+ x2="545.67096"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line118"
+ x1="560.39496"
+ y1="0.88384312"
+ x2="560.39496"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line122"
+ x1="575.11896"
+ y1="0.88384312"
+ x2="575.11896"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line124"
+ x1="589.8429"
+ y1="0.88384312"
+ x2="589.8429"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line128"
+ x1="604.56689"
+ y1="0.88384312"
+ x2="604.56689"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line130"
+ x1="619.29089"
+ y1="0.88384312"
+ x2="619.29089"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line134"
+ x1="634.01489"
+ y1="0.88384312"
+ x2="634.01489"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line136"
+ x1="648.73883"
+ y1="0.88384312"
+ x2="648.73883"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line140"
+ x1="663.46283"
+ y1="0.88384312"
+ x2="663.46283"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line142"
+ x1="678.18677"
+ y1="0.88384312"
+ x2="678.18677"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line146"
+ x1="692.91071"
+ y1="0.88384312"
+ x2="692.91071"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line148"
+ x1="707.6347"
+ y1="0.88384312"
+ x2="707.6347"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line152"
+ x1="722.3587"
+ y1="0.88384312"
+ x2="722.3587"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line154"
+ x1="737.0827"
+ y1="0.88384312"
+ x2="737.0827"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line158"
+ x1="751.80664"
+ y1="0.88384312"
+ x2="751.80664"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line160"
+ x1="766.53064"
+ y1="0.88384312"
+ x2="766.53064"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line164"
+ x1="781.25464"
+ y1="0.88384312"
+ x2="781.25464"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line166"
+ x1="795.97864"
+ y1="0.88384312"
+ x2="795.97864"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line170"
+ x1="810.70258"
+ y1="0.88384312"
+ x2="810.70258"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line172"
+ x1="825.42651"
+ y1="0.88384312"
+ x2="825.42651"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line176"
+ x1="840.15051"
+ y1="0.88384312"
+ x2="840.15051"
+ y2="53.914421" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line178"
+ x1="854.87451"
+ y1="0.88384312"
+ x2="854.87451"
+ y2="106.945" />
+ <line
+ style="stroke:#727272;stroke-width:1.76768601;stroke-opacity:1"
+ id="line182"
+ x1="869.59845"
+ y1="0.88384312"
+ x2="869.59845"
+ y2="53.914421" />
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-size:12.6378603px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="13.549175"
+ y="98.016769"
+ id="text3332"
+ inkscape:export-filename="/tmp/yourule_banner.png"
+ inkscape:export-xdpi="90.12661"
+ inkscape:export-ydpi="90.12661"><tspan
+ sodipodi:role="line"
+ id="tspan3334"
+ x="13.549175"
+ y="98.016769"
+ style="font-size:63.18930054px;font-weight:bold;fill:#ffffff;fill-opacity:1;font-family:Bitstream Vera Sans Mono">YouRule</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:13.47839546px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="12.11779"
+ y="129.42696"
+ id="text3336"
+ inkscape:export-filename="/tmp/yourule_banner.png"
+ inkscape:export-xdpi="90.12661"
+ inkscape:export-ydpi="90.12661"><tspan
+ sodipodi:role="line"
+ id="tspan3338"
+ x="12.11779"
+ y="129.42696"
+ style="font-size:33.6959877px;font-weight:bold;fill:#ffffff;fill-opacity:1">Onscreen Ruler Generator</tspan></text>
+</svg>
--- /dev/null
+@charset "UTF-8";
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+dl, dt, dd,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ font-weight: inherit;
+ font-style: inherit;
+ font-family: inherit;
+ vertical-align: baseline;
+}
+
+body {
+ font: Arial, Helvetica, sans-serif;
+}
+
+label {
+ font-weight: bold;
+}
+
+em {
+ font-style: italic;
+}
+
+#wrapper {
+ padding: 1em 0 0 0;
+ margin: 0 auto 0 auto;
+ width: 885px;
+}
+
+#header {
+ width: 885px;
+ height: 138px;
+ background: url(/static/images/yourule_banner.png);
+}
+
+#header h1, #header h2 {
+ display: none;
+}
+
+.mainbox {
+ margin-top: 1em;
+ background: url(/static/images/tl.png) no-repeat top left;
+}
+
+.mainbox_top {
+ background: url(/static/images/tr.png) no-repeat top right;
+}
+
+.mainbox_bottom {
+ background: url(/static/images/bl.png) no-repeat bottom left;
+}
+
+.mainbox_bottom div {
+ background: url(/static/images/br.png) no-repeat bottom right;
+}
+
+.mainbox_content {
+ background: url(/static/images/r.png) top right repeat-y;
+}
+
+
+.mainbox_top div, .mainbox_top, .mainbox_bottom div, .mainbox_bottom {
+ width: 100%;
+ height: 30px;
+ font-size: 1px;
+}
+
+.mainbox_content, .mainbox_bottom {
+ margin-top: -19px;
+}
+
+.mainbox_content {
+ padding: 0em 3em 2em 3em;
+ line-height: 1.5em;
+}
+
+.mainbox_content h2 {
+ border-bottom: 3px #1e3d7b solid;
+ margin: 19px 0 0.8em 0;
+ font-weight: bold;
+}
+
+.mainbox_content p {
+ margin-bottom: 0.5em;
+}
+
+#gallery {
+ border: 1px solid #1e3d7b;
+ width: 100%;
+ border-collapse: collapse;
+}
+
+#gallery th {
+ background: #1e3d7b;
+ color: white;
+}
+
+#gallery td {
+ text-align: center;
+}
+
+#menu {
+ text-align: right;
+ margin: 0.5em;
+}
+
+#rulerimg {
+ margin: 0.5em;
+}
+
+.errormsg {
+ background-color: #f7fb70;
+ color: #4c4c4c;
+ text-align: center;
+ border: 1px #fdff00 solid;
+ width: 20em;
+ margin: 1em;
+}
+
+strong {
+ font-weight: bold;
+}
+
+#footer {
+ margin-top: 3em;
+ font-size: 0.8em;
+ text-align: center;
+}
from __future__ import division
import SVGdraw
-class Ruler:
+class SVGRuler:
def __init__(self, scale=None, units=None,
ruler_height=None, ruler_length=None):
self.__drawline(0.3)
self.__drawline(0.6)
- self.svg.addElement(SVGdraw.text((self.point - font_height * 1.4),
+ self.svg.addElement(SVGdraw.text((self.point - font_height * 1.15),
(self.ruler_height * 0.6 - 5),
str(i + 1), font_height))
self.drawing.setSVG(self.svg)
- def output(self):
+ def getxml(self):
import cStringIO
xml = cStringIO.StringIO()
xml.write("<?xml version='1.0' encoding='UTF-8'?>\n")
-<p>Units:
+<p><label for="units">Units:</label>
<select id="unitselector" name="units">
<option values="centimeters"#if $getVar('units', '') == 'centimeters'# selected="selected"'#end if#>centimeters</option>
<option value="inches"#if $getVar('units', '') == 'inches'# selected="selected"'#end if#>inches</option>
</select>
</p>
-<p><label for="pixel_width">Your screen width (in pixels):</label>
+<p><label for="pixel_width">Screen width (in pixels):</label>
<input type="text" name="pixel_width" value="$getVar('pixel_width', None)" /></p>
-<p><label for="unit_width">Your screen width (in <span class="unittext">units</span>):</label>
+<p><label for="unit_width"><em>Horizontal</em> screen width (in <span class="unittext">units</span>):</label>
<input type="text" name="unit_width" value="$getVar('unit_width', None)" /></p>
<script>
<h2>Gallery of Existing Rulers</h2>
-<table>
+<table id="gallery">
<tr>
<th>Model</th>
<th>Pixel Width</th>
<td>$ruler.pixel_width</td>
<td>$ruler.cm_width()/$ruler.in_width</td>
<td>
- <a href="/show/ruler_${ruler.pixel_width}px_${ruler.cm_width}centimeters.png?fromgallery=true">cm</a>
- <a href="/show/ruler_${ruler.pixel_width}px_${ruler.in_width}inches.png?fromgallery=true">in</a>
+ <a href="/show/ruler_${ruler.pixel_width}px_${ruler.cm_width}centimeters.png?fromgallery=true">cm</a>/<a href="/show/ruler_${ruler.pixel_width}px_${ruler.in_width}inches.png?fromgallery=true">in</a>
</td>
<td><form method="GET" action="delete/$ruler.id" style="display:inline;">
<input type="submit" value="delete" /></form></td>
<p>If your ruler is not on the list you should add it with the box
form.</p>
-
+#if $getVar('errormsg', False)
+<div class="errormsg">
+<strong>Error</strong><br />
+$getVar('errormsg', False)
+</div>
+#end if
<form method="POST" action="/gallery">
#include 'templates/_form_elements.tmpl'
#block body
-<h1>Screen Ruler Generator</h1>
+<h2>Ruler Gallery </h2>
-<h2>Create a new screen ruler</h2>
+<p>To view a list of rulers others have created or to save your ruler so
+that others with your computer can find it, visit the <a
+href="/gallery">ruler gallery</a>.</p>
+
+<h2>Create Custom Ruler</h2>
+#if $getVar('errormsg', False)
+<div class="errormsg">
+<strong>Error</strong><br />
+$getVar('errormsg', False)
+</div>
+
+#end if
<form method="POST" action="/">
#include 'templates/_form_elements.tmpl'
<input type="Submit" name="submit" value="Generate" />
<form>
-<p>To view a list of rulers others have created or to save your ruler so
-that others with your computer can find it, visit the <a
-href="/gallery">ruler gallery</a>.</p>
#end block body
-#extends site
-
-#block body
-
-<h2>Your Ruler</h2>
-
-<img src="/$ruler_url" alt="$ruler_url" />
-
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="/static/style.css" />
+</head>
+<p id="menu">
+<a href="/show/$other_unit_url">show in $other_unit</a>
+/
#if $fromgallery
-<p><a href="/gallery">Back to gallery</a>.</p>
+<a href="/gallery">back to gallery</a>
#else
-<p><a href="/gallery/$ruler_url">Save your ruler to the gallery</a> for others to use in
-the future.</p>
+<a href="/gallery/$ruler_url">save for others</a>
#end if
+</p>
+
+<div id="rulerimg">
+<img src="/$ruler_url" alt="$ruler_url" />
+</div>
-#end block body
<html>
<head>
+ <link rel="stylesheet" type="text/css" href="/static/style.css" />
<script src="/static/prototype.js" type="text/javascript"></script>
</head>
<body>
+<div id="wrapper">
+<div id="header">
+<h1>YouRule</h1>
+<h2>Onscreen Ruler Generator</h2>
+</div>
+
+<div class="mainbox">
+ <div class="mainbox_top"><div></div></div>
+ <div class="mainbox_content">
+
#filter Filter
$body
#end filter
+ </div>
+ <div class="mainbox_bottom"><div></div></div>
+</div>
+
+<div id="footer">
+<p>copyright 2007 :: <a href="http://mako.cc/">benjamin mako hill</a><br />
+<a href="http://mako.cc/projects/yourule">source freely available</a> :: <a
+href="http://www.affero.org/oagpl.html">affero general public
+license</a></p>
+</div>
+
+</div>
+
</body>
</html>
--- /dev/null
+#!/usr/bin/env python
+
+from __future__ import division
+import web
+import sys, os, re
+from storm.locals import *
+from svgruler import SVGRuler
+
+# the url map for the application
+urls = ( '/', 'index',
+ '/ruler_([0-9\.]+)px_([0-9\.]+)([A-Za-z]+).(svg|png|jpg)', 'ruler_img',
+ '/show/(.*(svg|png|jpg))', 'show_ruler',
+ '/gallery(.*)', 'gallery',
+ '/delete/(\d+)', 'delete',
+ '/undelete/(\d+)', 'undelete')
+
+database = create_database("sqlite:yourule.db")
+store = Store(database)
+
+class Ruler(object):
+ __storm_table__ = "gallery"
+ id = Int(primary=True)
+ pixel_width = Float()
+ unit_width = Float()
+ model = Unicode()
+ units = Unicode()
+ show = Int()
+ cm_in_ratio = 0.3937
+
+ def __init__(self, **kw):
+ self.pixel_width = float(kw['pixel_width'])
+ self.unit_width = float(kw['unit_width'])
+ self.units = unicode(kw['units'])
+ if kw.has_key('model'):
+ self.model = unicode(kw['model'])
+ else:
+ self.model = u''
+
+ def cm_width(self):
+ if self.units == 'centimeters':
+ return self.unit_width
+ elif self.units == 'inches':
+ return(round(self.unit_width / self.cm_in_ratio, 2))
+
+ def in_width(self):
+ if self.units == 'inches':
+ return self.unit_width
+ elif self.units == 'centimeters':
+ return(round(self.unit_width * self.cm_in_ratio, 2))
+
+ def url(self):
+ return('ruler_%spx_%s%s.png' % (self.pixel_width,
+ self.unit_width, self.units))
+
+
+class index:
+ def GET(self):
+ web.header("Content-Type","text/html; charset=utf-8")
+ web.render('index.tmpl')
+
+ def POST(self):
+ input = web.input()
+
+ errormsg = validate_input(input)
+
+ if errormsg:
+ pixel_width = input['pixel_width']
+ unit_width = input['unit_width']
+ units = input['units']
+ web.render('index.tmpl')
+ else:
+ ruler = Ruler(pixel_width = input['pixel_width'],
+ unit_width = input['unit_width'],
+ units = input['units'])
+
+ web.redirect('/show/%s' % ruler.url())
+
+class show_ruler:
+ def GET(self, ruler_url, ext):
+ web.debug('test test')
+ if web.input().has_key('fromgallery'):
+ fromgallery = True
+ else:
+ fromgallery = False
+
+ other_unit, other_unit_url = get_other_unit(ruler_url)
+
+ web.header("Content-Type","text/html; charset=utf-8")
+ web.render('show_ruler.tmpl')
+
+
+class ruler_img:
+ def GET(self, pixel_width=None, unit_width=None, units=None, ext=None):
+
+ # TODO check to see if it's a format that we support
+
+ # set ruler height to be 200 px always
+ pixel_width = float(pixel_width)
+ unit_width = float(unit_width)
+
+ ruler_height = 200
+
+ scale = pixel_width / unit_width
+ ruler_length = int(unit_width)
+
+ ruler = SVGRuler(scale, units, ruler_height, ruler_length)
+
+ # print the header
+ if ext == 'svg': ext = 'svg+xml'
+ web.header("Content-Type", "image/%s" % ext)
+
+ if ext == 'svg+xml':
+ sys.stdout.write(ruler.getxml())
+ else:
+ pin, pout = os.popen2('convert -size %sx%s - %s:-' % \
+ (pixel_width, ruler_height, ext))
+
+ pin.write(ruler.getxml())
+ pin.close()
+ sys.stdout.write(pout.read())
+
+class gallery:
+ def GET(self, ruler_url):
+
+ if ruler_url:
+ pixel_width, unit_width, units = process_ruler_url(ruler_url)[0:3]
+
+ rulers = store.find(Ruler, Ruler.show == 1)
+ rulers.order_by(Ruler.model)
+ web.render('gallery.tmpl')
+
+ def POST(self, ruler_url):
+ input = web.input()
+
+ errormsg = valid_input(input)
+ if not input.model:
+ errormsg = 'Please fill out all fields.'
+
+ if errormsg:
+ pixel_width = input['pixel_width']
+ unit_width = input['unit_width']
+ units = input['units']
+ model = input['model']
+ else:
+ new_ruler = Ruler(pixel_width = input['pixel_width'],
+ unit_width = input['unit_width'],
+ units = input['units'],
+ model = input['model'])
+
+ store.add(new_ruler)
+ store.commit()
+
+ rulers = store.find(Ruler, Ruler.show == 1)
+ rulers.order_by(Ruler.model)
+ web.render('gallery.tmpl')
+
+class delete:
+ def GET(self, id):
+ ruler = store.get(Ruler, int(id))
+ ruler.show = 0
+ store.commit()
+ web.redirect('/gallery')
+
+
+class undelete:
+ def GET(self, id):
+ ruler = store.get(Ruler, int(id))
+ ruler.show = 1
+ store.commit()
+ web.redirect('/gallery')
+
+def get_other_unit(url):
+ pixel_width, unit_width, units = process_ruler_url(url)[0:3]
+
+ ruler = Ruler(pixel_width=pixel_width, unit_width=unit_width, units=units)
+ pixel_width, unit_width, units = process_ruler_url(url)[0:3]
+
+ if units == 'centimeters':
+ units = 'inches'
+ unit_width = ruler.in_width()
+ elif units == 'inches':
+ units = 'centimeters'
+ unit_width = ruler.cm_width()
+
+ new_ruler = Ruler(pixel_width=pixel_width, unit_width=unit_width,
+ units=units)
+
+ web.debug(units)
+ return(units, new_ruler.url())
+
+
+def process_ruler_url(url):
+ url = re.sub(r'^/?(ruler.*)$', r'\1', url)
+ return(re.match( r'ruler_([\d\.]+)px_([\d\.]+)(\w+).(png|svg|jpg)',
+ url).groups())
+
+def validate_input(input):
+ errormsg = False
+
+ if not input.pixel_width \
+ or not input.unit_width:
+ errormsg = 'Please fill out all fields.'
+ elif not re.match('^[\d\.]+$', input.pixel_width) \
+ or not re.match('^[\d\.]+$', input.unit_width):
+ errormsg = "Widths must be numbers."
+ elif input['pixel_width'] < 0 \
+ or input['unit_width'] < 0:
+ errormsg = 'Widths must be greater than postive.'
+
+ return(errormsg)
+
+# render the site template here so that i can use it later
+web.render('site.tmpl', None, True, 'site')
+
+web.webapi.internalerror = web.debugerror
+if __name__ == "__main__":
+ web.run(urls, globals(), web.reloader)
+
+application = web.wsgifunc(web.webpyfunc(urls, globals()))
+