PageRenderTime 32ms CodeModel.GetById 15ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/rounded_rectangle.d

http://github.com/AndrejMitrovic/cairoDSamples
D | 195 lines | 140 code | 26 blank | 29 comment | 8 complexity | 6cfa8358a6ddc7e04ea389ec6cd55a83 MD5 | raw file
  1module rounded_rectangle;
  2
  3/+
  4 +           Copyright Andrej Mitrovic 2011.
  5 +  Distributed under the Boost Software License, Version 1.0.
  6 +     (See accompanying file LICENSE_1_0.txt or copy at
  7 +           http://www.boost.org/LICENSE_1_0.txt)
  8 +/
  9
 10import cairo.cairo;
 11import cairo.win32;
 12
 13// todo: make this import in cairo
 14import std.math;
 15import std.algorithm;
 16import std.stdio;
 17
 18enum RoundMethod
 19{
 20    A,
 21    B,
 22    C,
 23    D,
 24}
 25
 26/+ @BUG@ 6574 - Erroneous recursive call: http://d.puremagic.com/issues/show_bug.cgi?id=6574
 27void roundedRectangle(RoundMethod roundMethod = RoundMethod.A)(Context ctx, Rectangle!double rect, double radius1 = 5, double radius2 = 5)
 28{
 29    with (rect)
 30    {
 31        roundedRectangle!(roundMethod)(ctx, point.x, point.y, width, height, radius1, radius2);
 32    }
 33}
 34
 35void roundedRectangle(RoundMethod roundMethod = RoundMethod.A)(Context ctx, double x, double y, double width, double height, double radius1 = 5, double radius2 = 5)
 36{
 37    roundedRectangle!(roundMethod)(ctx, x, y, width, height, radius1, radius2);
 38}
 39+/
 40
 41// convenience
 42void roundedRectangle(RoundMethod roundMethod)(Context ctx, Rectangle!double rect, double radius1 = 5, double radius2 = 5)
 43{
 44    with (rect)
 45    {
 46        roundedRectangle!(roundMethod)(ctx, point.x, point.y, width, height, radius1, radius2);
 47    }
 48}
 49
 50void roundedRectangle(RoundMethod roundMethod : RoundMethod.A)(Context ctx, double x, double y, double width, double height, double radiusX = 5, double radiusY = 5)
 51{
 52    enum ArcToBezier = 0.55228475;
 53
 54    if (radiusX > width - radiusX)
 55        radiusX = width / 2;
 56
 57    if (radiusY > height - radiusY)
 58        radiusY = height / 2;
 59
 60    // approximate the arc using a bezier curve
 61    auto c1 = ArcToBezier * radiusX;
 62    auto c2 = ArcToBezier * radiusY;
 63
 64    ctx.newPath();
 65    ctx.moveTo(x + radiusX, y);
 66    ctx.relLineTo(width - 2 * radiusX, 0.0);
 67    ctx.relCurveTo(c1, 0.0, radiusX, c2, radiusX, radiusY);
 68    ctx.relLineTo(0, height - 2 * radiusY);
 69    ctx.relCurveTo(0.0, c2, c1 - radiusX, radiusY, -radiusX, radiusY);
 70    ctx.relLineTo(-width + 2 * radiusX, 0);
 71    ctx.relCurveTo(-c1, 0, -radiusX, -c2, -radiusX, -radiusY);
 72    ctx.relLineTo(0, -height + 2 * radiusY);
 73    ctx.relCurveTo(0.0, -c2, radiusX - c1, -radiusY, radiusX, -radiusY);
 74    ctx.closePath();
 75}
 76
 77void roundedRectangle(RoundMethod roundMethod:RoundMethod.B)(Context ctx, double x, double y, double width, double height, double radius = 5, double unused = 0)
 78{
 79    // a custom shape, that could be wrapped in a function
 80    // radius = 5; and an approximate curvature radius
 81    immutable x0 = x + radius / 2.0;  // parameters like cairo_rectangle
 82    immutable y0 = y + radius / 2.0;
 83    immutable rectWidth  = width - radius;
 84    immutable rectHeight = height - radius;
 85
 86    ctx.save();
 87    ctx.newPath();
 88    // ctx.set_line_width (0.04)
 89    // self.snippet_normalize (cr, width, height)
 90
 91    immutable x1 = x0 + rectWidth;
 92    immutable y1 = y0 + rectHeight;
 93
 94    // if (!rectWidth || !rectHeight)
 95    //     return
 96
 97    if (rectWidth / 2 < radius)
 98    {
 99        if (rectHeight / 2 < radius)
100        {
101            ctx.moveTo(x0, (y0 + y1) / 2);
102            ctx.curveTo(x0, y0, x0, y0, (x0 + x1) / 2, y0);
103            ctx.curveTo(x1, y0, x1, y0, x1, (y0 + y1) / 2);
104            ctx.curveTo(x1, y1, x1, y1, (x1 + x0) / 2, y1);
105            ctx.curveTo(x0, y1, x0, y1, x0, (y0 + y1) / 2);
106        }
107        else
108        {
109            ctx.moveTo(x0, y0 + radius);
110            ctx.curveTo(x0, y0, x0, y0, (x0 + x1) / 2, y0);
111            ctx.curveTo(x1, y0, x1, y0, x1, y0 + radius);
112            ctx.lineTo(x1, y1 - radius);
113            ctx.curveTo(x1, y1, x1, y1, (x1 + x0) / 2, y1);
114            ctx.curveTo(x0, y1, x0, y1, x0, y1 - radius);
115        }
116    }
117
118    else
119    {
120        if (rectHeight / 2 < radius)
121        {
122            ctx.moveTo(x0, (y0 + y1) / 2);
123            ctx.curveTo(x0, y0, x0, y0, x0 + radius, y0);
124            ctx.lineTo(x1 - radius, y0);
125            ctx.curveTo(x1, y0, x1, y0, x1, (y0 + y1) / 2);
126            ctx.curveTo(x1, y1, x1, y1, x1 - radius, y1);
127            ctx.lineTo(x0 + radius, y1);
128            ctx.curveTo(x0, y1, x0, y1, x0, (y0 + y1) / 2);
129        }
130        else
131        {
132            ctx.moveTo(x0, y0 + radius);
133            ctx.curveTo(x0, y0, x0, y0, x0 + radius, y0);
134            ctx.lineTo(x1 - radius, y0);
135            ctx.curveTo(x1, y0, x1, y0, x1, y0 + radius);
136            ctx.lineTo(x1, y1 - radius);
137            ctx.curveTo(x1, y1, x1, y1, x1 - radius, y1);
138            ctx.lineTo(x0 + radius, y1);
139            ctx.curveTo(x0, y1, x0, y1, x0, y1 - radius);
140        }
141    }
142
143    ctx.closePath();
144    ctx.restore();
145}
146
147void roundedRectangle(RoundMethod roundMethod:RoundMethod.C)(Context ctx, double x, double y, double width, double height, double radius = 10, double unused = 0)
148{
149    immutable x1 = x + width;
150    immutable y1 = y + height;
151    
152    ctx.save();
153    ctx.moveTo(x + radius, y);                    // Move to A
154    ctx.lineTo(x1 - radius, y);                   // Straight line to B
155    ctx.curveTo(x1, y, x1, y, x1, y + radius);    // Curve to C, Control points are both at Q
156    ctx.lineTo(x1, y1 - radius);                  // Move to D
157    ctx.curveTo(x1, y1, x1, y1, x1 - radius, y1); // Curve to E
158    ctx.lineTo(x + radius, y1);                   // Line to F
159    ctx.curveTo(x, y1, x, y1, x, y1 - radius);    // Curve to G
160    ctx.lineTo(x, y + radius);                    // Line to H
161    ctx.curveTo(x, y, x, y, x + radius, y);       // Curve to A
162    ctx.restore();
163}
164
165void roundedRectangle(RoundMethod roundMethod:RoundMethod.D)(Context ctx, double x, double y, double width, double height, double radius = 10, double unused = 0)
166{
167    immutable x1 = x + width;
168    immutable y1 = y + height;
169
170    ctx.save();
171    ctx.newPath();
172    ctx.arc(x + radius, y + radius, radius, 2.0 * (PI / 2.0), 3.0 * (PI / 2.0));
173    ctx.arc(x1 - radius, y + radius, radius, 3.0 * (PI / 2.0), 4.0 * (PI / 2.0));
174    ctx.arc(x1 - radius, y1 - radius, radius, 0 * (PI / 2.0), 1.0 * (PI / 2.0));
175    ctx.arc(x + radius, y1 - radius, radius, 1.0 * (PI / 2.0), 2.0 * (PI / 2.0));
176    ctx.closePath();
177    ctx.restore();
178}
179
180RGB brightness(RGB rgb, double amount)
181{
182    with (rgb)
183    {
184        if (red > 0)
185            red = max(0, min(1.0, red + amount));
186
187        if (green > 0)
188            green = max(0, min(1.0, green + amount));
189
190        if (blue > 0)
191            blue  = max(0, min(1.0, blue  + amount));
192    }
193
194    return rgb;
195}