Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/elements/drawing.py
diff options
context:
space:
mode:
authorWalter Bender <walter@sugarlabs.org>2013-12-11 18:24:21 (GMT)
committer Walter Bender <walter@sugarlabs.org>2013-12-11 18:24:21 (GMT)
commit445dc0cc5770f9aa62264efb37c35d5964e41c0f (patch)
tree995e3ec3d512fe6cc5773e9122b58d3ee9301713 /elements/drawing.py
parentfdf37546041d212d97f7fa94dd9013589f9f1f57 (diff)
unpacking elements so as to be able to remove cjson dependency
Diffstat (limited to 'elements/drawing.py')
-rw-r--r--elements/drawing.py376
1 files changed, 376 insertions, 0 deletions
diff --git a/elements/drawing.py b/elements/drawing.py
new file mode 100644
index 0000000..b4722fb
--- /dev/null
+++ b/elements/drawing.py
@@ -0,0 +1,376 @@
+"""
+This file is part of the 'Elements' Project
+Elements is a 2D Physics API for Python (supporting Box2D2)
+
+Copyright (C) 2008, The Elements Team, <elements@linuxuser.at>
+
+Home: http://elements.linuxuser.at
+IRC: #elements on irc.freenode.org
+
+Code: http://www.assembla.com/wiki/show/elements
+ svn co http://svn2.assembla.com/svn/elements
+
+License: GPLv3 | See LICENSE for the full text
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+from math import pi
+from math import cos
+from math import sin
+from math import sqrt
+
+import tools
+
+# Functions of a rendering class
+# mandatory:
+# __init__
+# start_drawing
+# after_drawing
+# draw_circle
+# draw_polygon
+# draw_lines
+# set_lineWidth
+#
+# renderer-specific mandatory functions:
+# for pygame:
+# set_surface
+# for cairo:
+# draw_text
+# for opengl:
+#
+
+# IMPORTANT
+# The drawing functions get the coordinates in their screen coordinate system
+# no need for translations anymore :)
+
+class draw_pygame(object):
+ """ This class handles the drawing with pygame, which is really
+ simple since we only need draw_ellipse and draw_polygon.
+ """
+ lineWidth = 0
+
+ def __init__(self):
+ """ Load pygame.draw and pygame.Rect, and reference it for
+ the drawing methods
+
+ Parameters:
+ surface .... pygame surface (default: None)
+ lineWidth ..
+
+ Return: Class draw_pygame()
+ """
+ print "* Pygame selected as renderer"
+ from pygame import draw
+ from pygame import Rect
+
+ self.draw = draw
+ self.Rect = Rect
+
+ def set_lineWidth(self, lw):
+ """
+ """
+ self.lineWidth = lw
+
+ def set_surface(self, surface):
+ """
+ """
+ self.surface = surface
+
+ def get_surface(self):
+ """
+ """
+ return self.surface
+
+ def start_drawing(self):
+ pass
+
+ def after_drawing(self):
+ pass
+
+ def draw_circle(self, clr, pt, radius, angle):
+ """ Draw a circle
+
+ Parameters:
+ pt ........ (x, y)
+ clr ....... color in rgb ((r), (g), (b))
+ radius .... circle radius
+ angle ..... rotation in radians
+
+ Return: -
+ """
+ x, y = pt
+
+ x1 = x - radius
+ y1 = y - radius
+
+ rect = self.Rect( [x1, y1, 2*radius, 2*radius] )
+ self.draw.ellipse(self.surface, clr, rect, self.lineWidth)
+
+ # draw the orientation vector
+ if radius > 10:
+ rx = cos(angle) * radius
+ ry = -sin(angle) * radius
+
+ self.draw.line(self.surface, (255,255,255), pt, (x+rx, y+ry))
+
+ def draw_polygon(self, clr, points):
+ """ Draw a polygon
+
+ Parameters:
+ clr ....... color in rgb ((r), (g), (b))
+ points .... polygon points in normal (x,y) positions
+
+ Return: -
+ """
+ self.draw.polygon(self.surface, clr, points, self.lineWidth)
+ #self.draw.lines(self.surface, clr, True, points)
+
+ def draw_lines(self, clr, closed, points, width=None):
+ """ Draw a polygon
+
+ Parameters:
+ clr ....... color in rgb ((r), (g), (b))
+ points .... polygon points in normal (x,y) positions
+
+ Return: -
+ """
+ if width == None:
+ lw = self.lineWidth
+ else:
+ lw = width
+
+ self.draw.lines(self.surface, clr, closed, points, lw)
+
+class draw_cairo(object):
+ """ This class handles the drawing with cairo, which is really
+ simple since we only need draw_ellipse and draw_polygon.
+ """
+ window = None
+ da = None
+ circle_surface = None
+ box_surface = None
+
+ def __init__(self, drawMethod="filled"):
+ """ Load cairo.draw and cairo.Rect, and reference it for
+ the drawing methods
+
+ Return: Class draw_cairo()
+ """
+ print "* Cairo selected as renderer"
+ import cairo
+ self.cairo = cairo
+ self.set_drawing_method(drawMethod)
+ #self.draw_box = self.draw_box_image
+
+ def set_lineWidth(self, lw): # unused
+ self.lineWidth = lw
+
+ def set_drawing_area(self, da):
+ """ Set the area for Cairo to draw to
+
+ da ...... drawing area (gtk.DrawingArea)
+
+ Return: -
+ """
+ self.da = da
+ self.window = da.window
+ print "* Cairo renderer drawing area set"
+
+ def set_drawing_method(self, type):
+ """ type = filled, image """
+ self.draw_circle = getattr(self, "draw_circle_%s" % type)
+ #self.draw_box = getattr(self, "draw_box_%s" % type)
+
+ def start_drawing(self):
+ self.width, self.height = self.window.get_size()
+ self.imagesurface = self.cairo.ImageSurface(self.cairo.FORMAT_ARGB32, self.width, self.height);
+ self.ctx = ctx = self.cairo.Context(self.imagesurface)
+
+ ctx.set_source_rgb(1, 1, 1) # background color
+ ctx.paint()
+
+ ctx.move_to(0, 0)
+ ctx.set_source_rgb(0, 0, 0) # defaults for the rest of the drawing
+ ctx.set_line_width(1)
+ ctx.set_tolerance(0.1)
+
+ ctx.set_line_join(self.cairo.LINE_CAP_BUTT)
+ # LINE_CAP_BUTT, LINE_CAP_ROUND, LINE_CAP_SQUARE, LINE_JOIN_BEVEL, LINE_JOIN_MITER, LINE_JOIN_ROUND
+
+ #ctx.set_dash([20/4.0, 20/4.0], 0)
+
+ def after_drawing(self):
+ dest_ctx = self.window.cairo_create()
+ dest_ctx.set_source_surface(self.imagesurface)
+ dest_ctx.paint()
+
+ def set_circle_image(self, filename):
+ self.circle_surface = self.cairo.ImageSurface.create_from_png(filename)
+ self.draw_circle = self.draw_circle_image
+
+# def set_box_image(self, filename):
+# self.box_surface = self.cairo.ImageSurface.create_from_png(filename)
+# self.draw_box = self.draw_box_image
+
+ def draw_circle_filled(self, clr, pt, radius, angle=0):
+ x, y = pt
+
+ clr = tools.rgb2floats(clr)
+ self.ctx.set_source_rgb(*clr)
+ self.ctx.move_to(x, y)
+ self.ctx.arc(x, y, radius, 0, 2*3.1415)
+ self.ctx.fill()
+
+ def draw_circle():
+ pass
+
+ def draw_circle_image(self, clr, pt, radius, angle=0, sf=None):
+ if sf == None:
+ sf = self.circle_surface
+ x, y = pt
+ self.ctx.save()
+ self.ctx.translate(x, y)
+ self.ctx.rotate(-angle)
+ image_r = sf.get_width() / 2
+ scale = float(radius) / image_r
+ self.ctx.scale(scale, scale)
+ self.ctx.translate(-0.5*sf.get_width(), -0.5*sf.get_height())
+ self.ctx.set_source_surface(sf)
+ self.ctx.paint()
+ self.ctx.restore()
+
+ def draw_image(self, source, pt, scale=1.0, rot=0, sourcepos=(0,0)):
+ self.ctx.save()
+ self.ctx.rotate(rot)
+ self.ctx.scale(scale, scale)
+ destx, desty = self.ctx.device_to_user_distance(pt[0], pt[1])
+ self.ctx.set_source_surface(source, destx-sourcepos[0], desty-sourcepos[1])
+ self.ctx.rectangle(destx, desty, source.get_width(), source.get_height())
+ self.ctx.fill()
+ self.ctx.restore()
+
+ def draw_polygon(self, clr, points):
+ """ Draw a polygon
+
+ Parameters:
+ clr ....... color in rgb ((r), (g), (b))
+ points .... polygon points in normal (x,y) positions
+
+ Return: -
+ """
+ clr = tools.rgb2floats(clr)
+ self.ctx.set_source_rgb(clr[0], clr[1], clr[2])
+
+ pt = points[0]
+ self.ctx.move_to(pt[0], pt[1])
+ for pt in points[1:]:
+ self.ctx.line_to(pt[0], pt[1])
+
+ self.ctx.fill()
+
+ def draw_text(self, text, center, clr=(0,0,0), size=12, fontname="Georgia"):
+ clr = tools.rgb2floats(clr)
+ self.ctx.set_source_rgb(clr[0], clr[1], clr[2])
+
+ self.ctx.select_font_face(fontname, self.cairo.FONT_SLANT_NORMAL, self.cairo.FONT_WEIGHT_NORMAL)
+ self.ctx.set_font_size(size)
+ x_bearing, y_bearing, width, height = self.ctx.text_extents(text)[:4]
+ self.ctx.move_to(center[0] + 0.5 - width / 2 - x_bearing, center[1] + 0.5 - height / 2 - y_bearing)
+ self.ctx.show_text(text)
+
+ def draw_lines(self, clr, closed, points):
+ """ Draw a polygon
+
+ Parameters:
+ clr ....... color in rgb ((r), (g), (b))
+ closed .... whether or not to close the lines (as a polygon)
+ points .... polygon points in normal (x,y) positions
+ Return: -
+ """
+ clr = tools.rgb2floats(clr)
+ self.ctx.set_source_rgb(clr[0], clr[1], clr[2])
+
+ pt = points[0]
+ self.ctx.move_to(pt[0], pt[1])
+ for pt in points[1:]:
+ self.ctx.line_to(pt[0], pt[1])
+
+ if closed:
+ pt = points[0]
+ self.ctx.line_to(pt[0], pt[1])
+
+ self.ctx.stroke()
+
+class draw_opengl_pyglet(object):
+ """ This class handles the drawing with pyglet
+ """
+ lineWidth = 0
+ def __init__(self):
+ """ Load pyglet.gl, and reference it for the drawing methods
+
+ Parameters:
+ surface .... not used with pyglet
+ lineWidth ..
+ """
+ print "* OpenGL_Pyglet selected as renderer"
+
+ from pyglet import gl
+ self.gl = gl
+
+ def set_lineWidth(self, lw):
+ self.lineWidth = lw
+
+ def draw_circle(self, clr, pt, radius, a=0):
+ clr = tools.rgb2floats(clr)
+ self.gl.glColor3f(clr[0], clr[1], clr[2])
+
+ x, y = pt
+ segs = 15
+ coef = 2.0*pi/segs;
+
+ self.gl.glBegin(self.gl.GL_LINE_LOOP)
+ for n in range(segs):
+ rads = n*coef
+ self.gl.glVertex2f(radius*cos(rads + a) + x, radius*sin(rads + a) + y)
+ self.gl.glVertex2f(x,y)
+ self.gl.glEnd()
+
+ def draw_polygon(self, clr, points):
+ clr = tools.rgb2floats(clr)
+ self.gl.glColor3f(clr[0], clr[1], clr[2])
+
+ self.gl.glBegin(self.gl.GL_LINES)
+
+ p1 = points[0]
+ for p in points[1:]:
+ x1, y1 = p1
+ x2, y2 = p1 = p
+
+ self.gl.glVertex2f(x1, y1)
+ self.gl.glVertex2f(x2, y2)
+
+ x1, y1 = points[0]
+
+ self.gl.glVertex2f(x2, y2)
+ self.gl.glVertex2f(x1, y1)
+
+ self.gl.glEnd()
+
+ def draw_lines(self, clr, closed, points):
+ pass
+
+ def start_drawing(self):
+ pass
+
+ def after_drawing(self):
+ pass