Skip to content

Instantly share code, notes, and snippets.

@pzurek
Created November 23, 2008 17:20
Show Gist options
  • Save pzurek/28157 to your computer and use it in GitHub Desktop.
Save pzurek/28157 to your computer and use it in GitHub Desktop.
#light
open System
open Cairo
open Gtk
Gtk.Application.Init()
let window = new Gtk.Window("F# Cairo")
let vBox = new Gtk.VBox()
let drawingArea = new Gtk.DrawingArea()
let buttonHBox = new Gtk.HBox()
let closeButton = new Gtk.Button()
let SketchCircle (cc:Cairo.Context, xc, yc, xr, yr) =
cc.Save()
let m = cc.Matrix
cc.Translate(xc, yc)
cc.Scale(1., yr/xr)
cc.MoveTo(xr, 0.)
cc.Arc(0., 0., xr, 0., 2.*Math.PI)
cc.ClosePath()
cc.Matrix <- m
cc.Restore()
let FillChecks (cc:Cairo.Context, x, y, w, h) =
let checkSize = 32
cc.Save()
use check = cc.Target.CreateSimilar(Cairo.Content.Color, 2*checkSize, 2*checkSize)
use cr2 = new Cairo.Context(check)
cr2.Operator <- Cairo.Operator.Source
cr2.Color <- new Cairo.Color(0.4, 0.4, 0.4)
cr2.Rectangle(0., 0., 2.*(float)checkSize, 2.*(float)checkSize)
cr2.Fill()
cr2.Color <- new Cairo.Color(0.7, 0.7, 0.7)
cr2.Rectangle(x, y, (float)checkSize, (float)checkSize)
cr2.Fill()
cr2.Rectangle(x + (float)checkSize, y + (float)checkSize, (float)checkSize, (float)checkSize)
cr2.Fill()
use checkPattern = new Cairo.SurfacePattern(check)
checkPattern.Extend <- Cairo.Extend.Repeat
cc.Source <- checkPattern
cc.Rectangle(0., 0., w, h)
cc.Fill()
cc.Restore()
let Draw3Circles (cc:Cairo.Context, xc, yc, radius, alfa) =
cc.Save()
let subradius = radius * (2./3. - 0.1)
cc.Color <- new Cairo.Color(1., 0., 0., alfa)
SketchCircle(cc, xc + radius / 3. * Math.Cos(Math.PI * 0.5), yc - radius / 3. * Math.Sin (Math.PI * 0.5), subradius, subradius)
cc.Fill()
cc.Color <- new Cairo.Color(0., 1., 0., alfa)
SketchCircle(cc, xc + radius / 3. * Math.Cos(Math.PI * (0.5 + 2. / 0.3)), yc - radius / 3. * Math.Sin (Math.PI * (0.5 + 2. / 0.3)), subradius, subradius)
cc.Fill()
cc.Color <- new Cairo.Color(0., 0., 1., alfa)
SketchCircle(cc, xc + radius / 3. * Math.Cos(Math.PI * (0.5 + 4. / 0.3)), yc - radius / 3. * Math.Sin (Math.PI * (0.5 + 4. / 0.3)), subradius, subradius)
cc.Fill()
cc.Restore()
let Draw (cc:Cairo.Context, w, h) =
let radius = 0.5 * Math.Min(w, h) - 10.
let xc = w / 2.
let yc = h / 2.
use overlay = cc.Target.CreateSimilar (Cairo.Content.ColorAlpha, (int)w , (int)h)
use punch = cc.Target.CreateSimilar (Cairo.Content.Alpha, (int)w , (int)h)
use circles = cc.Target.CreateSimilar (Cairo.Content.ColorAlpha, (int)w , (int)h)
FillChecks(cc, 0., 0., w, h)
cc.Save()
use cr_overlay = new Cairo.Context(overlay)
cr_overlay.Color <- new Cairo.Color(0., 0., 0.)
SketchCircle(cr_overlay, xc, yc, radius, radius)
cr_overlay.Fill()
use cr_temp = new Cairo.Context(punch)
Draw3Circles(cr_temp, xc, yc, radius, 1.)
cr_overlay.Operator <- Cairo.Operator.DestOut
cr_overlay.SetSourceSurface (punch, 0, 0)
cr_overlay.Paint()
use cr_circles = new Cairo.Context(circles)
cr_circles.Operator <- Cairo.Operator.Over
Draw3Circles(cr_circles, xc, yc, radius, 0.5)
cr_overlay.Operator <- Cairo.Operator.Add
cr_overlay.SetSourceSurface(circles, 0, 0)
cr_overlay.Paint()
cc.SetSourceSurface(overlay, 0, 0)
cc.Paint()
cc.Restore()
let Knockout(da:Gtk.DrawingArea) =
use drawable = da.GdkWindow
let w,h = da.Allocation.Width, da.Allocation.Height
use cairoContext = Gdk.CairoHelper.Create (drawable)
Draw(cairoContext, (float)w, (float)h)
window.WindowPosition <- Gtk.WindowPosition.Center
window.SetDefaultSize(400, 400)
window.Destroyed.Add(fun _ -> Application.Quit() )
drawingArea.ExposeEvent.Add(fun _ -> Knockout(drawingArea))
drawingArea.ButtonReleaseEvent.Add(fun _ -> () )
closeButton.Label <- " Close "
closeButton.Clicked.Add(fun _ -> Application.Quit() )
vBox.BorderWidth <- (uint32) 12
vBox.Spacing <- 12
vBox.PackStart(drawingArea, true, true, (uint32) 0)
buttonHBox.PackEnd(closeButton, false, false, (uint32) 0)
vBox.PackStart(buttonHBox, false, false, (uint32) 0)
window.Add(vBox)
window.ShowAll()
Gtk.Application.Run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment