1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
using System;
using Gtk;
using Cairo;
class CairoSample : DrawingArea
{
static void Main ()
{
Application.Init ();
Window win = new Window ("Cairo with Gtk# 3");
win.SetDefaultSize (400, 400);
win.DeleteEvent += delegate { Application.Quit (); };
win.Add (new CairoSample ());
win.ShowAll ();
Application.Run ();
}
void OvalPath (Context cr, double xc, double yc, double xr, double yr)
{
Matrix m = cr.Matrix;
cr.Translate (xc, yc);
cr.Scale (1.0, yr / xr);
cr.MoveTo (xr, 0.0);
cr.Arc (0, 0, xr, 0, 2 * Math.PI);
cr.ClosePath ();
cr.Matrix = m;
}
void FillChecks (Context cr, int x, int y, int width, int height)
{
int CHECK_SIZE = 32;
cr.Save ();
Surface check;
using (var target = cr.GetTarget ()) {
check = target.CreateSimilar (Content.Color, 2 * CHECK_SIZE, 2 * CHECK_SIZE);
}
// draw the check
using (Context cr2 = new Context (check)) {
cr2.Operator = Operator.Source;
cr2.SetSourceRGB (0.4, 0.4, 0.4);
cr2.Rectangle (0, 0, 2 * CHECK_SIZE, 2 * CHECK_SIZE);
cr2.Fill ();
cr2.SetSourceRGB (0.7, 0.7, 0.7);
cr2.Rectangle (x, y, CHECK_SIZE, CHECK_SIZE);
cr2.Fill ();
cr2.Rectangle (x + CHECK_SIZE, y + CHECK_SIZE, CHECK_SIZE, CHECK_SIZE);
cr2.Fill ();
}
// Fill the whole surface with the check
SurfacePattern check_pattern = new SurfacePattern (check);
check_pattern.Extend = Extend.Repeat;
cr.SetSource (check_pattern);
cr.Rectangle (0, 0, width, height);
cr.Fill ();
check_pattern.Dispose ();
check.Dispose ();
cr.Restore ();
}
void Draw3Circles (Context cr, int xc, int yc, double radius, double alpha)
{
double subradius = radius * (2 / 3.0 - 0.1);
cr.SetSourceRGBA (1.0, 0.0, 0.0, alpha);
OvalPath (cr, xc + radius / 3.0 * Math.Cos (Math.PI * 0.5), yc - radius / 3.0 * Math.Sin (Math.PI * 0.5), subradius, subradius);
cr.Fill ();
cr.SetSourceRGBA (0.0, 1.0, 0.0, alpha);
OvalPath (cr, xc + radius / 3.0 * Math.Cos (Math.PI * (0.5 + 2 / 0.3)), yc - radius / 3.0 * Math.Sin (Math.PI * (0.5 + 2 / 0.3)), subradius, subradius);
cr.Fill ();
cr.SetSourceRGBA (0.0, 0.0, 1.0, alpha);
OvalPath (cr, xc + radius / 3.0 * Math.Cos (Math.PI * (0.5 + 4 / 0.3)), yc - radius / 3.0 * Math.Sin (Math.PI * (0.5 + 4 / 0.3)), subradius, subradius);
cr.Fill ();
}
void Draw (Context cr, int width, int height)
{
double radius = 0.5 * Math.Min (width, height) - 10;
int xc = width / 2;
int yc = height / 2;
Surface overlay, punch, circles;
using (var target = cr.GetTarget ()) {
overlay = target.CreateSimilar (Content.ColorAlpha, width, height);
punch = target.CreateSimilar (Content.Alpha, width, height);
circles = target.CreateSimilar (Content.ColorAlpha, width, height);
}
FillChecks (cr, 0, 0, width, height);
cr.Save ();
// Draw a black circle on the overlay
using (Context cr_overlay = new Context (overlay)) {
cr_overlay.SetSourceRGB (0.0, 0.0, 0.0);
OvalPath (cr_overlay, xc, yc, radius, radius);
cr_overlay.Fill ();
// Draw 3 circles to the punch surface, then cut
// that out of the main circle in the overlay
using (Context cr_tmp = new Context (punch))
Draw3Circles (cr_tmp, xc, yc, radius, 1.0);
cr_overlay.Operator = Operator.DestOut;
cr_overlay.SetSourceSurface (punch, 0, 0);
cr_overlay.Paint ();
// Now draw the 3 circles in a subgroup again
// at half intensity, and use OperatorAdd to join up
// without seams.
using (Context cr_circles = new Context (circles)) {
cr_circles.Operator = Operator.Over;
Draw3Circles (cr_circles, xc, yc, radius, 0.5);
}
cr_overlay.Operator = Operator.Add;
cr_overlay.SetSourceSurface (circles, 0, 0);
cr_overlay.Paint ();
}
cr.SetSourceSurface (overlay, 0, 0);
cr.Paint ();
overlay.Dispose ();
punch.Dispose ();
circles.Dispose ();
}
protected override bool OnDrawn (Cairo.Context ctx)
{
Draw (ctx, AllocatedWidth, AllocatedHeight);
return true;
}
}
|