Wednesday, August 27, 2008

Reworked Graffiti's first render


After quite a few weeks of work, Graffiti has (again) reached the stage where it can render it's first words. It's now at 488 lines of code, of which the CSS related stuff itself comes in at 288 lines! There is no word wrapping yet, or any layout logic. I've been busy fixing quite a few bugs in the CSS overlays and so on.

This is how you would use it.



import pygame
from pygame.locals import *

import graffiti as g # 1

pygame.init()

g.init() # 2

pygame.display.set_caption('Graffiti Render Test')

screen = pygame.display.set_mode((800, 600))
screen.fill((0, 0, 0))

page = g.page.Page('<body><p>Testing Graffiti</p></body>') # 3

page.render.on(screen) # 4

while True:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit(0)

pygame.display.update()


Sunday, August 17, 2008

Nikhil meet Archlinux and KDE4



I've been home (Mumbai) this weekend and have been hacking away for the last two days to get Arch running on my external HDD, since I can't stand Mandriva anymore. The cool thing about Arch and Pacman is their flexibility. Following this guide I was able to install Arch from within my internal hdd arch, and have all the latest packages (including KDE 4.1).

There was only one problem which wasn't mentioned. External HDDs require usb support in the initrd which is not done in Arch by default. So before rebooting just edit /etc/mkinitcpio.conf and add "usb" to the line HOOKS="base udev …". Then remake the initrd using "mkinitcpio -g /boot/kernel26.img".

I must say I'm pretty impressed with KDE 4.1. There are still a few rough edges like the khotkeys keyboard shortcuts not working and some KWin effects not exactly doing anything. But overall a great effort.

Wednesday, August 13, 2008

Custom hash objects in Python

It's quite common to use strings, integers and other 'native' Python data types as hash keys. But sometimes it is much easier to be able to use your own class instances as keys. Python's magic methods allow you to do this.

Note: This is not a tip on implementing hash functions, this is how you can remove a certain layer of peeking around into objects

__hash and __cmp__


Consider a useless HTML parser with a simple node design where you want to associate the node name with its attributes.

You want to use the absolute node name as a unique hash.

The solution is to define custom implementations for __hash__ and __cmp__, two magic methods. For more information and constraints about them take a look at the Python docs.

The builtin functions hash(obj) and cmp(obj1, obj2) will attempt to call there __underscored__ counterparts on objs.



import UserDict # allow NodeAttrs to behave like a dictionary, not significant for this example

class NodeName(object):
def __init__(self, name, parent=None):
self.name = name
self.parent = parent

def __str__(self):
return (parent and str(parent) or '') + self.name

def __hash__(self):
# the hash of our string is our unique hash
return hash(str(self))

def __cmp__(self, other):
# similarly the strings are good for comparisons
return cmp(str(self), str(other))

class NodeAttrs(UserDict.UserDict):
def __init__(self, attrs={}):
self.update(attrs)



Where we assume that the parser is doing the heavy lifting of parsing the name, and putting the attributes in a dictionary. Now to use this in a dictionary you would do the following:



>>> d = {}
>>> d[node_name] = attrs # node_name is an instance of NodeName and attrs

... # do anything which can be done to a dictionary and its keys



Thats it! For more magic methods see Python __Underscore__ Methods

Monday, August 04, 2008

Sierpinski, my first fractal



The Sierpinski triangle in Python, inspired by HTDP, and using Pygame




import sys
import pygame
from pygame.locals import *

class Point(object):
def __init__(self, x, y):
self.x, self.y = x, y

def distance_sq(self, other):
return (self.x-other.x)**2 + (self.y-other.y)**2

def distance(self, other):
return sqrt(self.distance_sq(other))

def tupl(self):
return (self.x, self.y)

def midpt(p1, p2):
return Point( (p1.x+p2.x)/2, (p1.y+p2.y)/2 )

def too_small(p1, p2, p3):
return max([ p1.distance_sq(p2), p2.distance_sq(p3), p3.distance_sq(p1) ]) < 5

def draw_line(p1, p2, surf, col):
pygame.draw.line(surf, col, p1.tupl(), p2.tupl())


def draw_triangle(a, b, c, screen, col):
if too_small(a, b, c):
return
else:
a_b = midpt(a, b)
a_c = midpt(a, c)
b_c = midpt(b, c)

draw_line(a, b, screen, col)
draw_line(b, c, screen, col)
draw_line(a, c, screen, col)

draw_triangle(a, a_b, a_c, screen, col)
draw_triangle(b, a_b, b_c, screen, col)
draw_triangle(c, b_c, a_c, screen, col)

pygame.init()
pygame.display.set_caption('Sierpinski')
screen = pygame.display.set_mode((640,480))
screen.fill((0, 0, 0))

draw_triangle(Point(10, 10), Point(630, 10), Point(310, 450), screen, (255, 0, 0))
draw_triangle(Point(50, 10), Point(630, 240), Point(310, 0), screen, (0, 255, 0))

while True:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pygame.quit()
sys.exit()
pygame.display.update()

pygame.quit()

Great Weekend

So my second weekend in this place went pretty great. Now that I've found the right computer which easily boots from external devices I'm ready to slowly begin coding. On saturday five of us saw Ugly and Pagli — crappy movie — but I got my first pair of studs. Its been raining a lot for the last three days here. It starts at around 7 and goes on till late into the night, which means a lot of fun football (I've discovered that playing barefoot is better than playing with normal shoes), but being cooped up in the rooms afterwards.

I also made some headway into How To Design Programs which is a really great book, and read almost all of Joel On Software (the book) which is entertaining to say the least.

So right now I'm sitting here after attending a particularly boring calculus lecture. I haven't had a bath because there was no water, and I'm reading a boring story as part of the assignment for Communication Skills.

Right now I'm replanning Graffiti since I wiped it out a few weeks ago. I've also been messing around with Scheme, but can't think of what application to write to dig deeper into it.