[cairo-commit] [cairo-www] src/cairomm.mdwn src/cookbook src/pycairo src/win32quickstart.mdwn

Carl Worth cworth at freedesktop.org
Wed Jul 4 09:49:00 PDT 2007


 src/cairomm.mdwn                      |   10 +-
 src/cookbook/convertctopyandback.mdwn |   17 +++
 src/cookbook/librsvgpython.mdwn       |   85 +++++++++++++++++
 src/cookbook/roundedrectangles.mdwn   |  109 +++++++++++++++++++++
 src/pycairo/ressources.mdwn           |   37 +++++++
 src/win32quickstart.mdwn              |  169 ++++++++++++++++++++++++++++++++++
 6 files changed, 423 insertions(+), 4 deletions(-)

New commits:
commit b0a55cbd6e62c5a0ecbe0ff44f983747603fb74e
Author: JonathonJongsma <jonathon.jongsma at gmail.com>
Date:   Wed Jul 4 09:49:00 2007 -0700

    add link to drawing area documentation of the gtkmm manual

diff --git a/src/cairomm.mdwn b/src/cairomm.mdwn
index 7ffea94..ac69b30 100644
--- a/src/cairomm.mdwn
+++ b/src/cairomm.mdwn
@@ -8,15 +8,15 @@ Standard Template Library where it makes sense.
 # Status
 
 cairomm wraps all relevant parts of the cairo API and is
-API/ABI-stable. cairomm is used by [gtkmm][] since 2.10.
+API/ABI-stable. cairomm is used by [gtkmm](http://gtkmm.org/) since 2.10.
 
 # Download
 
 There have been several releases, which you can download from the
 [cairo release area](/releases/). If you want bleeding-edge code, (or
 if you want to help out with development or cairomm), you can also
-check out cairomm from CVS. Freedesktop.org has some instructions on
-[using CVS][cvs]. You can also view the code online with [viewcvs][].
+check out cairomm from git. Freedesktop.org has some instructions on
+[using git](http://www.freedesktop.org/wiki/Infrastructure/git). You can also view the code online with [gitweb](http://gitweb.cairographics.org/?p=cairomm.git;a=summary).
 
 # Documentation
 
@@ -28,7 +28,9 @@ documentation](/manual/) as well.
 In addition to the API documentation, there are several small example
 programs which ship with cairomm and demonstrate some of the basic
 functionality. These examples are in the examples/ directory of the
-release tarball or can be [browsed online][examples].
+release tarball or can be [browsed online](http://gitweb.cairographics.org/?p=cairomm.git;a=tree;f=examples).
+
+There is also some tutorial-like documentation available in the gtkmm manual.  The [Drawing Area chapter](http://gtkmm.org/docs/gtkmm-2.4/docs/tutorial/html/ch15.html) introduces some basic cairomm drawing concepts.  Although the documentation is about using cairomm with gtkmm, most of the concepts apply whether you're using gtkmm or not.
 
 # License
 
diff --git a/src/cookbook/convertctopyandback.mdwn b/src/cookbook/convertctopyandback.mdwn
new file mode 100644
index 0000000..0c24532
--- /dev/null
+++ b/src/cookbook/convertctopyandback.mdwn
@@ -0,0 +1,17 @@
+
+Converting cairo code between languages is very easy.
+
+##C to Python
+
+the following C code:
+	cairo_new_path (cr);
+	cairo_move_to (cr, x + radius_x, y);
+to Python:
+        cr.new_path()
+        cr.move_to ( x + radius_x, y)
+
+* replace cairo_ with cr
+* remove cr as first argument
+
+Note that in some instances the python bindings will try to simplify, and then a direct translation is not possible. In such a case refer to the source code of [[pycairo]], it is relatively easy to read.
+
diff --git a/src/cookbook/librsvgpython.mdwn b/src/cookbook/librsvgpython.mdwn
new file mode 100644
index 0000000..4c5cc8d
--- /dev/null
+++ b/src/cookbook/librsvgpython.mdwn
@@ -0,0 +1,85 @@
+[[meta title="Rendering SVG with libRSVG,Python and c-types"]]
+Back to [[cookbook]]
+    
+
+    # Very primitive librsvg bindings for win32
+    # no error checking, etc.
+    # but hey it works!
+    
+    from ctypes import *
+    import cairo
+
+    l=CDLL('librsvg-2-2.dll')
+    g=CDLL('libgobject-2.0-0.dll')
+    g.g_type_init()    
+    
+    
+    class PycairoContext(Structure):
+        _fields_ = [("PyObject_HEAD", c_byte * object.__basicsize__),
+                    ("ctx", c_void_p),
+                    ("base", c_void_p)]
+    
+    
+    
+    class RsvgDimensionData(Structure):
+        _fields_ = [("width", c_int),
+                    ("height", c_int),
+                    ("em",c_double),
+                    ("ex",c_double)]
+    
+    
+    svghandlecache = {}
+    
+    
+    def renderSVG(ctx,filename,x,y):  
+        
+        if not filename in svghandlecache:  
+            error=''
+            handle1 = l.rsvg_handle_new_from_file(filename,error)
+            svghandlecache[filename] = handle1
+        else:
+            handle1 = svghandlecache[filename]
+        #print error
+        #print handle1    
+        
+        #svgDim = RsvgDimensionData()
+    
+        #l.rsvg_handle_get_dimensions(handle1,byref(svgDim))
+    
+        #print 'SVG Dimensions: ',svgDim.width,'x',svgDim.height
+    
+        #scaleX = float(WIDTH) / float(svgDim.width)
+        #scaleY = float(HEIGHT) / float(svgDim.height)
+        #scaleY = scaleX
+        #scaleX = 1
+        #scaleY = 1
+    
+        #print scaleY
+    
+        ctx.save()
+        #ctx.scale(scaleX, scaleY)
+        ctx.translate(x,y)
+    
+        z = PycairoContext.from_address(id(ctx))
+        #print z.ctx
+    
+        #print '>>',l.rsvg_handle_render_cairo(handle1, z.ctx)
+        l.rsvg_handle_render_cairo(handle1, z.ctx)
+        ctx.restore()    
+
+
+
+    WIDTH, HEIGHT = 400, 400
+
+    # Setup Cairo
+    surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT)
+    ctx = cairo.Context(surface)
+
+    #bg
+    bg = WebColour('#FFFFFF')
+    ctx.set_source_rgb(bg[0],bg[1],bg[2])
+    ctx.paint()
+
+    renderSVG(ctx,'ball.svg',0,0)
+
+    surface.write_to_png("test.png")
diff --git a/src/cookbook/roundedrectangles.mdwn b/src/cookbook/roundedrectangles.mdwn
new file mode 100644
index 0000000..036a25e
--- /dev/null
+++ b/src/cookbook/roundedrectangles.mdwn
@@ -0,0 +1,109 @@
+##Method A
+
+From the cairo samples, modified. Gives a very nice shape but takes width and height only as guides.
+
+    def roundedrecA(self,cr,x,y,width,height,radius=5):
+        #/* a custom shape, that could be wrapped in a function */
+        #radius = 5  #/*< and an approximate curvature radius */        
+        x0       = radius/2.0   #/*< parameters like cairo_rectangle */
+        y0       = radius/2.0
+        rect_width  = width - radius
+        rect_height = height - radius
+        
+        cr.save()
+        #cr.set_line_width (0.04)
+        #self.snippet_normalize (cr, width, height)
+        
+        x1=x0+rect_width
+        y1=y0+rect_height
+        #if (!rect_width || !rect_height)
+        #    return
+        if rect_width/2<radius:
+            if rect_height/2<radius:
+                cr.move_to  (x0, (y0 + y1)/2)
+                cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
+                cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
+                cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
+                cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
+            else:
+                cr.move_to  (x0, y0 + radius)
+                cr.curve_to (x0 ,y0, x0, y0, (x0 + x1)/2, y0)
+                cr.curve_to (x1, y0, x1, y0, x1, y0 + radius)
+                cr.line_to (x1 , y1 - radius)
+                cr.curve_to (x1, y1, x1, y1, (x1 + x0)/2, y1)
+                cr.curve_to (x0, y1, x0, y1, x0, y1- radius)
+        
+        else:
+            if rect_height/2<radius:
+                cr.move_to  (x0, (y0 + y1)/2)
+                cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
+                cr.line_to (x1 - radius, y0)
+                cr.curve_to (x1, y0, x1, y0, x1, (y0 + y1)/2)
+                cr.curve_to (x1, y1, x1, y1, x1 - radius, y1)
+                cr.line_to (x0 + radius, y1)
+                cr.curve_to (x0, y1, x0, y1, x0, (y0 + y1)/2)
+            else:
+                cr.move_to  (x0, y0 + radius)
+                cr.curve_to (x0 , y0, x0 , y0, x0 + radius, y0)
+                cr.line_to (x1 - radius, y0)
+                cr.curve_to (x1, y0, x1, y0, x1, y0 + radius)
+                cr.line_to (x1 , y1 - radius)
+                cr.curve_to (x1, y1, x1, y1, x1 - radius, y1)
+                cr.line_to (x0 + radius, y1)
+                cr.curve_to (x0, y1, x0, y1, x0, y1- radius)
+        
+        cr.close_path ()
+        
+        cr.restore()
+
+##Method B
+From mono moonlight aka mono silverlight. Works very well on larger shapes.
+
+    def roundedrecMoonlight(self,cr,x,y,w,h,radius_x=5,radius_y=5):
+        #from mono moonlight aka mono silverlight
+        #test limits (without using multiplications)
+        # http://graphics.stanford.edu/courses/cs248-98-fall/Final/q1.html
+        ARC_TO_BEZIER = 0.55228475
+        if radius_x > w - radius_x:
+            radius_x = w / 2
+        if radius_y > h - radius_y:
+            radius_y = h / 2
+    
+        #approximate (quite close) the arc using a bezier curve
+        c1 = ARC_TO_BEZIER * radius_x
+        c2 = ARC_TO_BEZIER * radius_y
+    
+        cr.new_path();
+        cr.move_to ( x + radius_x, y)
+        cr.rel_line_to ( w - 2 * radius_x, 0.0)
+        cr.rel_curve_to ( c1, 0.0, radius_x, c2, radius_x, radius_y)
+        cr.rel_line_to ( 0, h - 2 * radius_y)
+        cr.rel_curve_to ( 0.0, c2, c1 - radius_x, radius_y, -radius_x, radius_y)
+        cr.rel_line_to ( -w + 2 * radius_x, 0)
+        cr.rel_curve_to ( -c1, 0, -radius_x, -c2, -radius_x, -radius_y)
+        cr.rel_line_to (0, -h + 2 * radius_y)
+        cr.rel_curve_to (0.0, -c2, radius_x - c1, -radius_y, radius_x, -radius_y)
+        cr.close_path ()  
+
+##Method C
+I can't remember where I got this. If you are the author please add your name. Works well on smaller shapes.
+
+    def roundedrec(self,context,x,y,w,h,r = 10):
+        "Draw a rounded rectangle"
+        #   A****BQ
+        #  H      C
+        #  *      *
+        #  G      D
+        #   F****E
+    
+        context.move_to(x+r,y)                      # Move to A
+        context.line_to(x+w-r,y)                    # Straight line to B
+        context.curve_to(x+w,y,x+w,y,x+w,y+r)       # Curve to C, Control points are both at Q
+        context.line_to(x+w,y+h-r)                  # Move to D
+        context.curve_to(x+w,y+h,x+w,y+h,x+w-r,y+h) # Curve to E
+        context.line_to(x+r,y+h)                    # Line to F
+        context.curve_to(x,y+h,x,y+h,x,y+h-r)       # Curve to G
+        context.line_to(x,y+r)                      # Line to H
+        context.curve_to(x,y,x,y,x+r,y)             # Curve to A
+        return 
+
diff --git a/src/pycairo/ressources.mdwn b/src/pycairo/ressources.mdwn
new file mode 100644
index 0000000..ba6f1c4
--- /dev/null
+++ b/src/pycairo/ressources.mdwn
@@ -0,0 +1,37 @@
+[[meta title="Pycairo ressources"]]
+
+Various useful ressources about [python cairo bindings](/pycairo).
+
+# API Reference and Documentation
+
+Currently there is no Python specific cairo API documentation. However there is the [cairo C documentation](/manual) which can be useful.
+
+# Tutorials
+
+  * [Cairo Tutorial for Python (and other) Programmers][1]: Generic introduction to cairo concepts oriented to python.
+  * [Cairo Tutorial for PyGTK Programmers][2]: Tutorial about how to use cairo for drawing in [PyGTK](http://www.pygtk.org).
+  * _Writing a widget using cairo and PyGTK 2.8_ [Part 1][3], [Part 2][4]: A translation of the GNOME Journal tutorial by Davyd Madeley from C to Python.
+
+# Cairo-based canvas
+   * [GooCanvas python bindings][5] - python API reference available. (Report bugs [here](https://launchpad.net/pygoocanvas))
+   * [Libccc][6] python bindings - not documented at all.
+   * [HippoCanvas][7] - part of the [OLPC](http://www.laptop.org) project.
+
+# Demos
+
+   * [A Basic Cairo-clock in Python][8] using XShape.
+   * [A simple clock implemented in pygtk and cairo][9].
+   * [A Shogiban for Gnushogi][10].
+
+   [1]: http://www.tortall.net/mu/wiki/CairoTutorial
+   [2]: http://www.tortall.net/mu/wiki/PyGTKCairoTutorial
+   [3]: http://www.pygtk.org/articles/cairo-pygtk-widgets/cairo-pygtk-widgets.htm
+   [4]: http://www.pygtk.org/articles/cairo-pygtk-widgets/cairo-pygtk-widgets2.htm
+
+   [5]: https://developer.berlios.de/projects/pygoocanvas/
+   [6]: http://live.gnome.org/Criawips/CriaCanvas
+   [7]: http://wiki.laptop.org/go/HippoCanvas
+
+   [8]: http://blog.eikke.com/index.php/ikke/2007/02/17/python_cairo_xshape_and_clocks
+   [9]: http://ralph-glass.homepage.t-online.de/clock/readme.html
+   [10]: http://ralph-glass.homepage.t-online.de/shogi/readme.html
\ No newline at end of file
diff --git a/src/win32quickstart.mdwn b/src/win32quickstart.mdwn
new file mode 100644
index 0000000..c5ab8c1
--- /dev/null
+++ b/src/win32quickstart.mdwn
@@ -0,0 +1,169 @@
+[[meta title="Win32 Quickstart"]]
+Back to [[cookbook]]
+
+##Python
+The following is a minimal windows application that uses cairo. It has double buffering and uses the PyWin32 library.
+
+    from win32api import *
+    try:
+        from winxpgui import *
+    except ImportError:
+        from win32gui import *
+        
+    import win32con
+    import sys, os
+    import cairo
+    
+    def WebColour(sCol):
+        #print sCol
+        ic = [int(sCol[i:i+2], 16)/255.0 for i in range(1, 7, 2)]
+        #print ic
+        return ic
+    
+    def roundedRectangle(cr,x,y,w,h,radius_x=5,radius_y=5):
+        #from mono moonlight aka mono silverlight
+        #test limits (without using multiplications)
+        # http://graphics.stanford.edu/courses/cs248-98-fall/Final/q1.html
+        ARC_TO_BEZIER = 0.55228475
+        if radius_x > w - radius_x:
+            radius_x = w / 2
+        if radius_y > h - radius_y:
+            radius_y = h / 2
+    
+        #approximate (quite close) the arc using a bezier curve
+        c1 = ARC_TO_BEZIER * radius_x
+        c2 = ARC_TO_BEZIER * radius_y
+    
+        cr.new_path();
+        cr.move_to ( x + radius_x, y)
+        cr.rel_line_to ( w - 2 * radius_x, 0.0)
+        cr.rel_curve_to ( c1, 0.0, radius_x, c2, radius_x, radius_y)
+        cr.rel_line_to ( 0, h - 2 * radius_y)
+        cr.rel_curve_to ( 0.0, c2, c1 - radius_x, radius_y, -radius_x, radius_y)
+        cr.rel_line_to ( -w + 2 * radius_x, 0)
+        cr.rel_curve_to ( -c1, 0, -radius_x, -c2, -radius_x, -radius_y)
+        cr.rel_line_to (0, -h + 2 * radius_y)
+        cr.rel_curve_to (0.0, -c2, radius_x - c1, -radius_y, radius_x, -radius_y)
+        cr.close_path ()
+    
+    
+    class MainWindow(object):
+        def __init__(self):        
+            message_map = {
+                    win32con.WM_DESTROY: self.OnDestroy,
+                    win32con.WM_PAINT: self.OnPaint,
+                    win32con.WM_SETCURSOR: self.OnCursor,
+                    win32con.WM_ERASEBKGND: self.OnBackgroundErase,
+                    win32con.WM_LBUTTONDOWN: self.OnClick,
+                    win32con.WM_KEYUP: self.OnKey,
+                    #win32con.WM_COMMAND: self.OnCommand,
+                    #win32con.WM_USER+20 : self.OnTaskbarNotify,
+                    # owner-draw related handlers.
+                    #win32con.WM_MEASUREITEM: self.OnMeasureItem,
+                    #win32con.WM_DRAWITEM: self.OnDrawItem,
+            }
+            # Register the Window class.
+            wc = WNDCLASS()
+            hinst = wc.hInstance = GetModuleHandle(None)
+            self.hinst = hinst
+            wc.lpszClassName = "CairoWindow"
+            wc.lpfnWndProc = message_map # could also specify a wndproc.
+            classAtom = RegisterClass(wc)
+            # Create the Window.
+            style = win32con.WS_THICKFRAME | win32con.WS_MAXIMIZEBOX | win32con.WS_MINIMIZEBOX | win32con.WS_SYSMENU | win32con.WS_VISIBLE
+            self.hwnd = CreateWindow( classAtom, "Cairo is the greatest thing!", style, \
+                    0, 0, 550, 350, \
+                    0, 0, hinst, None)
+            UpdateWindow(self.hwnd)
+            
+            
+        def OnKey(self, hWnd, msg, wParam, lparam):
+            if wParam == 38: #up
+                print "up"
+            elif wParam == 40: #down
+                print "down"
+            
+        def OnClick(self, hWnd, msg, wparam, lparam):
+            x = LOWORD(lparam)
+            y = HIWORD(lparam) 
+                    
+        def Render(self):
+            try:
+                InvalidateRect(self.hwnd, None, True)
+                return True
+            except:
+                print "That didn't work"
+                return False
+    
+        def OnPaint(self, hWnd, msg, wparam, lparam):   
+            hdc, ps = BeginPaint(hWnd)
+            rc = GetClientRect(hWnd)
+            left, top, right, bottom = rc            
+            
+            width = right - left
+            height = bottom - top
+            x = left
+            y = top 
+            
+            _buffer = CreateCompatibleDC(hdc) 
+            #Double Buffer Stage 1
+            hBitmap = CreateCompatibleBitmap(hdc,width,height)
+            hOldBitmap = SelectObject(_buffer, hBitmap )
+            
+            
+            surf = cairo.Win32Surface(_buffer)
+            ctx = cairo.Context(surf) 
+            
+            ctx.set_source_rgb(1,1,1)
+            ctx.paint()
+            
+            
+            roundedRectangle(ctx, 50, 50, 250, 250, 10, 10)
+            clr = WebColour("#F0FEE9")        
+            ctx.set_source_rgb(clr[0],clr[1],clr[2])
+            ctx.fill_preserve()
+            clr = WebColour("#B3FF8D")        
+            ctx.set_source_rgb(clr[0],clr[1],clr[2])
+            ctx.stroke()        
+                
+            ctx.set_source_rgb(0,0,0)
+            ctx.select_font_face("Arial",cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
+            ctx.set_font_size(10)    
+    
+            txt = "Cairo is the greatest thing!"
+                
+            ctx.move_to(5,10)        
+            ctx.show_text(txt)
+            
+            surf.finish()
+            
+            BitBlt(hdc,0, 0, width,  height,
+              _buffer, x, y, win32con.SRCCOPY) 
+            
+            SelectObject( _buffer, hOldBitmap ) 
+            DeleteObject( hBitmap ) 
+            DeleteDC( _buffer )               
+            
+            EndPaint(hWnd,ps)        
+            
+        def OnCursor(self, hwnd, msg, wparam, lparam):
+            #IDC_HAND = 32649
+            #IDC_ARROW
+            cur_normal = LoadCursor(0, win32con.IDC_ARROW)
+            SetCursor(cur_normal)
+            
+        def OnBackgroundErase(self, hwnd, msg, wparam, lparam):
+            return False
+    
+            
+        def OnDestroy(self, hwnd, msg, wparam, lparam):
+            #nid = (self.hwnd, 0)
+            #Shell_NotifyIcon(NIM_DELETE, nid)
+            PostQuitMessage(0) # Terminate the app. 
+            print "Exited."
+               
+            
+    w=MainWindow()
+    PumpMessages()
+          
+##Other?
\ No newline at end of file


More information about the cairo-commit mailing list