PageRenderTime 23ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/rounded_rectangle.d

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