#!/usr/bin/python # -*- coding: utf-8 -*- """ """ import os, sys import re import time import platform import pygame ANTIALIASING=True ANTIALIASING=False class Pic (pygame.Surface): def __init__ (self): pygame.Surface.__init__ (self, g.size) self.clear () self.rec = [] self.tmplines = [] self.delete = [] self.true=1 def reveal (self, silent=0, cleartmp=True): if cleartmp: self.tmplines = [] self.true=1 if not silent: g.scr.fill ((0,0,0)) pygame.display.flip () rec = list (self.rec) tmplines = list (self.tmplines) self.clear () count = 0 for p0,p1 in rec: if count%g.speed==0: g.scr.blit (self, (0,0)) pygame.display.flip () count += 1 self.line (p0,p1) if cleartmp: return for p0,p1 in tmplines: if count%g.speed==0: g.scr.blit (self, (0,0)) pygame.display.flip () count += 1 self.line (p0,p1,fg='red',rec='tmp') def line (self, pos0, pos1, fg='black', spacing=1, thickness=1, rec=1): ''' ''' if rec=='tmp': self.tmplines.append ((pos0, pos1)) elif rec: self.rec.append ((pos0, pos1)) if ANTIALIASING: pygame.draw.aaline (self, pygame.Color(fg), pos0, pos1, 1) else: pygame.draw.line (self, pygame.Color(fg), pos0, pos1, thickness+1) return img = pygame.Surface ((thickness, thickness), pygame.HWSURFACE | pygame.SRCALPHA, 32) fg = pygame.Color (fg) x0, y0 = pos0 x1, y1 = pos1 def norm (a, b, c): if c > a >= b: return a elif c <= a: return c-1 elif a < b: return b dx = x1 - x0 dy = y1 - y0 adx = abs (dx) ady = abs (dy) # (ix, iy) : the iterating point ix, iy = x0, y0 carry = 0 inc = spacing incy = (dy==ady) * inc or -inc incx = (dx==adx) * inc or -inc if ANTIALIASING: def setat (x,y, c, alpha): x = norm (x, 0, self.get_width()) y = norm (y, 0, self.get_height()) r,v,b,a=c c=r,v,b, ((a/255.0) * alpha)*255 img.fill (c) self.blit (img, (x,y)) else: def setat (x,y, c, alpha): x = norm (x, 0, self.get_width()) y = norm (y, 0, self.get_height()) r,v,b,a=c c=r,v,b, 255#((a/255.0) * alpha)*255 img.fill (c) self.blit (img, (x,y)) if dx == 0: while abs (iy - y1) >= inc: iy += incy alpha = 1 setat (ix , iy, fg, alpha) setat (ix+incx, iy, fg, 1-alpha) elif adx >= ady: while abs (ix - x1) >= inc: ix += incx carry += ady if carry >= adx: carry -= adx; iy += incy r,g,b,a = fg alpha = float (carry)/adx setat (ix,iy+incy, fg, alpha) setat (ix,iy , fg, 1-alpha) elif ady > adx: while abs (iy - y1) >= inc: iy += incy carry += adx if carry >= ady: carry -= ady; ix += incx alpha = float (carry)/ady setat (ix+incx,iy, fg, alpha) setat (ix ,iy, fg, 1-alpha) ix, iy = x1, y1 setat (ix, iy, fg, 1.0) self.blit (self, (0,0)) def clear (self, bg='white'): bg=pygame.Color (bg) self.fill (bg) self.rec = [] self.tmplines = [] class Obj:'' g=Obj () def main (): pygame.init () g.expuser=os.path.expanduser if 'in32' in platform.system() or 'indows' in platform.system(): def e (p): return p.replace('~',os.path.expandvars('%APPDATA%')) g.expuser=e g.res = (500,520) g.size = (500, 500) g.speed = 25 g.wait = 0.01 font = pygame.font.Font (None, 17) scr = pygame.display.set_mode (g.res, pygame.HWSURFACE, 32) g.scr=scr g.playing=0 pygame.display.set_caption ('Notes') g.notes = [] g.current = 0 def autonumfile (filename, startat=0): dir, name = os.path.split (filename) n=0 filename=os.path.join (dir,name%n) while os.path.exists (filename): n+=1 filename=os.path.join (dir,name%n) return filename g.conffile = os.path.realpath(os.path.expanduser ('~/.dnotes.conf')) g.sfile = os.path.realpath (os.path.expanduser('~/.dnotes/saved')) if not os.path.isdir(os.path.split(g.sfile)[0]): os.mkdir (os.path.split(g.sfile)[0]) if os.path.isfile (g.conffile): g.sfile=open (g.conffile,'r').read().split('\n')[0] if len (sys.argv[1:]): if sys.argv[1]=="new": print 'new file' g.sfile = autonumfile (os.path.realpath (os.path.expanduser ('~/.dnotes/auto.%04d.da')), 1) else: g.sfile = os.path.realpath(os.path.expanduser(sys.argv[1])) last_time = time.time () g.lastup = (0,0) g.lastdown=(0,0) def convert_to_avi (): if os.path.isdir ('/tmp/dnotes_vid/'): for f in os.listdir ('/tmp/dnotes_vid'): os.remove (os.path.join('/tmp/dnotes_vid',f)) os.rmdir ('/tmp/dnotes_vid') os.mkdir ('/tmp/dnotes_vid') prefix = '/tmp/dnotes_vid/tmpdnotes' for n,pic in enumerate(g.notes): if pic.true==0: pic.reveal(silent=1, cleartmp=1) pygame.image.save (pic, '%s_%03d.png'%(prefix,n)) outfile = '%s.mp4'%os.path.join(os.path.expanduser ('~/.dnotes'),g.sfile) com = 'ffmpeg -y -r %d -qscale 5 -an -i '%g.speed com+= '"/tmp/dnotes_vid/tmpdnotes_%%03d.png" "%s"' com%=outfile print com os.system (com) #os.system ('bash -c "thunar ~/.dnotes&"') #os.system ('bash -c "mplayer %s &"'%outfile) def save (): final = [] final.append ('%d'%(g.current)) for pic in g.notes: rec=pic.rec r=[] for line in rec: p0,p1 = line r.append ('%d %d %d %d'%(p0+p1)) r='|'.join(r) final.append (r) final = '\n'.join (final) open (g.sfile,'w').write (final) print 'saved' open (g.conffile,'w').write(g.sfile) def load (): if os.path.isfile (g.sfile): g.notes = [] saved = open (g.sfile, 'r').read ().split ('\n') g.current = int(saved[0]); saved = saved[1:] for rec in saved: savedpic = Pic (); savedpic.clear() g.notes.append (savedpic) if rec=='': continue for line in rec.split ('|'): p0x,p0y,p1x,p1y = map (int, line.split (' ')) p0=(p0x,p0y) p1=(p1x,p1y) savedpic.rec.append ((p0,p1)) savedpic.true=0 print 'loaded' def reorder (): '' print 'reordering' copy=list(g.notes) c=g.current g.notes.sort (key=lambda pic: (copy.index(pic)-c)%len(copy)) g.current=0 g.notes[0].reveal (silent=1) load () if len(g.notes)==0: g.notes.append (Pic()) g.stopped = 0 g.mode_rec = 1 precision = 0.09 mdown = 0 path = [] g.esize = 10 g.hesize = g.esize/2 def stop (): g.stopped = 1 while not g.stopped: if g.playing: g.wait = 1./g.speed time.sleep (g.wait) if g.playing: g.current+=1 g.current %= len(g.notes) showcur = font.render ('%s/%s'%(g.current+1,len(g.notes)), 1, (0,0,0)) cnote = g.notes[g.current] if cnote.true==0: cnote.reveal () scr.fill ((255,255,255), ((0,g.res[1]-20),(g.res[0], 20))) scr.fill ((0,0,0), ((0,g.res[1]-20),(g.res[0], 1))) scr.blit (showcur, (g.res[0]-40, g.res[1]-17)) dstr = '%s c:(%s;%s;%s;%s)'%(g.sfile,len(cnote.rec),precision,g.speed,g.esize) scr.blit (font.render (dstr, 1, (0,0,180)), (10, g.res[1]-14)) scr.blit (cnote, (0,0)) pygame.display.flip () keys = pygame.key.get_pressed () if (keys[pygame.K_LCTRL] or keys[pygame.K_RCTRL]): k_ctrl=1 else: k_ctrl=0 if (keys[pygame.K_LSHIFT] or keys[pygame.K_RSHIFT]): k_shift=1 else: k_shift=0 if (keys[pygame.K_LALT] or keys[pygame.K_RALT]): k_alt=1 else: k_alt=0 for event in pygame.event.get (): if event.type == pygame.QUIT: save () stop () break elif event.type == pygame.KEYUP: if 0:'' elif event.key == pygame.K_LEFT: g.current -= 1 elif event.key == pygame.K_RIGHT: g.current += 1 elif event.key == pygame.K_SPACE: cnote.clear () elif event.key == pygame.K_RETURN: if k_ctrl: g.playing=not g.playing if g.playing: g.wait = 1./g.speed else: g.wait = 0.01 else: cnote.rec += cnote.tmplines cnote.reveal () elif event.key == pygame.K_BACKSPACE: if k_shift: for i in range(4): if not len (cnote.rec): break p0,p1=cnote.rec.pop () cnote.line (p0,p1,fg='white', thickness=3, rec=0) if not len (cnote.rec): break p0,p1=cnote.rec.pop () cnote.line (p0,p1,fg='white', thickness=3, rec=0) elif event.key == pygame.K_r: if k_shift: reorder () else: cnote.reveal () elif event.key == pygame.K_n: g.current+=1 g.notes.insert (g.current, Pic ()) elif event.key == pygame.K_c: g.current+=1 old, new=cnote, Pic() g.notes.insert (g.current, new) new.tmplines = list (old.rec) new.reveal (cleartmp=False) elif event.key == pygame.K_d: if (len (g.notes)==1): break g.notes.remove (cnote) g.current -= 1 elif event.key == pygame.K_s: if k_shift: convert_to_avi() else: save() elif event.key == pygame.K_l: scr.fill ((0,0,0)) pygame.display.flip () load() elif event.key == pygame.K_q: stop() elif event.type == pygame.MOUSEBUTTONDOWN: mx, my = mpos = event.pos mdown = event.button if event.button == 1: 'press left' p0 = mpos if k_ctrl: g.mode_rec = 0 elif event.button == 3: 'press right' p0 = mpos hasmoved = 0 elif event.type == pygame.MOUSEMOTION: hasmoved = 1 mx, my = mpos = event.pos if mdown==1: 'motion left' if time.time () - last_time < precision: continue (x0,y0),(x1,y1)=p0,mpos if abs(x0-x1) < 2 and abs(y0-y1) < 2: 'too short' continue color = 'black' if g.mode_rec else 'red' p1=mpos cnote.line (p0,p1, fg=color, rec=g.mode_rec) if g.mode_rec==0:cnote.tmplines.append ((p0,p1)) last_time = time.time () elif mdown==3: 'motion right' p1=mpos cnote.delete.append ((p0,p1)) (p0x,p0y),(p1x,p1y)=p0,p1 cnote.fill ((255,255,200), ((p0x-g.hesize,p0y-g.hesize),(g.esize,g.esize))) cnote.fill ((255,255,200), ((p0x-g.hesize,p0y-g.hesize),(g.esize,g.esize))) p0=mpos elif event.type == pygame.MOUSEBUTTONUP: mdown = 0 if event.button == 1: mdown = 0 mx, my = mpos = event.pos color = 'black' if g.mode_rec else 'red' if hasmoved: p1=mpos cnote.line (p0,p1, fg=color, rec=g.mode_rec) if g.mode_rec==0:cnote.tmplines.append ((p0,p1)) else: if k_shift: cnote.line (g.lastup,mpos, fg=color, rec=g.mode_rec) if g.mode_rec==0:cnote.tmplines.append ((g.lastup,mpos)) if k_alt: x0,y0 = g.lastup x1,y1 = mpos cnote.line ((x0,y0),(x0,y1), fg=color, rec=g.mode_rec) cnote.line ((x0,y0),(x1,y0), fg=color, rec=g.mode_rec) cnote.line ((x0,y1),(x1,y1), fg=color, rec=g.mode_rec) cnote.line ((x1,y0),(x1,y1), fg=color, rec=g.mode_rec) if g.mode_rec==0: cnote.tmplines.append (((x0,y0),(x0,y1))) cnote.tmplines.append (((x0,y0),(x1,y0))) cnote.tmplines.append (((x0,y1),(x1,y1))) cnote.tmplines.append (((x1,y0),(x1,y1))) g.mode_rec = 1 g.lastup = mpos elif event.button == 3: p1 = mpos cnote.delete.append ((p0,p1)) redraw=0 #if ((len(cnote.rec) < 150) # or (len (cnote.delete) > 20 and len (cnote.rec) < 400) # or (len (cnote.delete) > 80 and len (cnote.rec) < 700) # or (len (cnote.delete) > 200 and len (cnote.rec) < 1500) # ): redraw=1 #else: redraw=0 while len (cnote.delete): p = cnote.delete.pop () (px0, py0), (px1, py1) = p newrec = [] for pts in cnote.rec: (ptx0, pty0), (ptx1, pty1) = pts if (( px0-g.hesize < ptx0 < px0+g.hesize and py0-g.hesize < pty0 < py0+g.hesize ) or ( px0-g.hesize < ptx1 < px0+g.hesize and py0-g.hesize < pty1 < py0+g.hesize )): cnote.line ((ptx0,pty0),(ptx1,pty1), fg='white', rec=0) else: newrec.append (pts) cnote.rec = newrec if redraw: cnote.reveal (silent=1) elif event.button == 4: if k_ctrl and not (k_shift or k_alt): precision=min(max(precision+0.01,0),0.6) elif k_shift and not (k_ctrl or k_alt): g.hesize = min(max(g.hesize+1,0),100) g.esize = g.hesize*2 elif k_alt and not (k_ctrl or k_shift): g.speed = max (min (g.speed + 1, 100), 1) elif not (k_shift or k_ctrl or k_alt): g.current -= 1 elif event.button == 5: if k_ctrl: precision=min(max(precision-0.01,0),0.6) elif k_shift: g.hesize = min(max(g.hesize-1,0),100) g.esize = g.hesize*2 elif k_alt and not (k_ctrl or k_shift): g.speed = max (min (g.speed - 1, 100), 1) else:g.current += 1 if __name__ == "__main__": try: main () except KeyboardInterrupt: print "\033[31mLeaving: User typed Ctrl+C.\033[0m"