hotcocoa 0.5.1 → 0.6.0pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. data/.yardopts +14 -0
  2. data/History.txt +21 -0
  3. data/README.markdown +84 -0
  4. data/Rakefile +47 -0
  5. data/bin/hotcocoa +20 -10
  6. data/docs/Contributors.markdown +25 -0
  7. data/docs/Mappings.markdown +352 -0
  8. data/docs/MappingsExplained.markdown +22 -0
  9. data/docs/Overview.markdown +58 -0
  10. data/docs/Resources.markdown +25 -0
  11. data/docs/Tutorial.markdown +3 -0
  12. data/lib/hotcocoa/application/builder.rb +237 -0
  13. data/lib/hotcocoa/application/specification.rb +373 -0
  14. data/lib/hotcocoa/application_builder.rb +338 -242
  15. data/lib/hotcocoa/attributed_string_helpers.rb +128 -0
  16. data/lib/hotcocoa/behaviors.rb +39 -6
  17. data/lib/hotcocoa/core_extensions/kernel.rb +67 -0
  18. data/lib/hotcocoa/core_extensions/nsarray.rb +15 -0
  19. data/lib/hotcocoa/core_extensions/nsmutable_attributed_string.rb +74 -0
  20. data/lib/hotcocoa/core_extensions/nsstring.rb +36 -0
  21. data/lib/hotcocoa/core_extensions/nsurl.rb +6 -0
  22. data/lib/hotcocoa/core_extensions/numeric.rb +9 -0
  23. data/lib/hotcocoa/core_extensions/object.rb +36 -0
  24. data/lib/hotcocoa/core_extensions/range.rb +30 -0
  25. data/lib/hotcocoa/core_extensions.rb +8 -0
  26. data/lib/hotcocoa/data_sources/combo_box_data_source.rb +38 -38
  27. data/lib/hotcocoa/data_sources/outline_view_data_source.rb +33 -0
  28. data/lib/hotcocoa/data_sources/table_data_source.rb +12 -13
  29. data/lib/hotcocoa/data_sources.rb +3 -0
  30. data/lib/hotcocoa/delegate_builder.rb +114 -79
  31. data/lib/hotcocoa/graphics/canvas.rb +211 -214
  32. data/lib/hotcocoa/graphics/color.rb +89 -91
  33. data/lib/hotcocoa/graphics/elements/particle.rb +16 -19
  34. data/lib/hotcocoa/graphics/elements/rope.rb +12 -14
  35. data/lib/hotcocoa/graphics/elements/sandpainter.rb +11 -13
  36. data/lib/hotcocoa/graphics/gradient.rb +13 -14
  37. data/lib/hotcocoa/graphics/image.rb +110 -83
  38. data/lib/hotcocoa/graphics/path.rb +44 -50
  39. data/lib/hotcocoa/graphics/pdf.rb +17 -19
  40. data/lib/hotcocoa/graphics.rb +21 -20
  41. data/lib/hotcocoa/kvo_accessors.rb +10 -11
  42. data/lib/hotcocoa/layout_view.rb +394 -379
  43. data/lib/hotcocoa/mapper.rb +346 -207
  44. data/lib/hotcocoa/mapping_methods.rb +107 -37
  45. data/lib/hotcocoa/mappings/appkit/alert.rb +25 -0
  46. data/lib/hotcocoa/mappings/appkit/application.rb +112 -0
  47. data/lib/hotcocoa/mappings/{array_controller.rb → appkit/array_controller.rb} +33 -35
  48. data/lib/hotcocoa/mappings/appkit/box.rb +37 -0
  49. data/lib/hotcocoa/mappings/appkit/button.rb +88 -0
  50. data/lib/hotcocoa/mappings/appkit/collection_view.rb +42 -0
  51. data/lib/hotcocoa/mappings/appkit/color.rb +40 -0
  52. data/lib/hotcocoa/mappings/appkit/column.rb +19 -0
  53. data/lib/hotcocoa/mappings/appkit/combo_box.rb +22 -0
  54. data/lib/hotcocoa/mappings/appkit/control.rb +31 -0
  55. data/lib/hotcocoa/mappings/appkit/font.rb +58 -0
  56. data/lib/hotcocoa/mappings/appkit/gradient.rb +19 -0
  57. data/lib/hotcocoa/mappings/appkit/image.rb +15 -0
  58. data/lib/hotcocoa/mappings/appkit/image_view.rb +41 -0
  59. data/lib/hotcocoa/mappings/appkit/label.rb +23 -0
  60. data/lib/hotcocoa/mappings/appkit/layout_view.rb +9 -0
  61. data/lib/hotcocoa/mappings/appkit/line.rb +16 -0
  62. data/lib/hotcocoa/mappings/appkit/menu.rb +78 -0
  63. data/lib/hotcocoa/mappings/appkit/menu_item.rb +47 -0
  64. data/lib/hotcocoa/mappings/appkit/outline_view.rb +62 -0
  65. data/lib/hotcocoa/mappings/appkit/popup.rb +106 -0
  66. data/lib/hotcocoa/mappings/appkit/progress_indicator.rb +61 -0
  67. data/lib/hotcocoa/mappings/appkit/scroll_view.rb +28 -0
  68. data/lib/hotcocoa/mappings/appkit/search_field.rb +9 -0
  69. data/lib/hotcocoa/mappings/appkit/secure_text_field.rb +15 -0
  70. data/lib/hotcocoa/mappings/appkit/segmented_control.rb +103 -0
  71. data/lib/hotcocoa/mappings/appkit/slider.rb +23 -0
  72. data/lib/hotcocoa/mappings/appkit/sound.rb +9 -0
  73. data/lib/hotcocoa/mappings/appkit/speech_synthesizer.rb +22 -0
  74. data/lib/hotcocoa/mappings/appkit/split_view.rb +19 -0
  75. data/lib/hotcocoa/mappings/appkit/status_bar.rb +7 -0
  76. data/lib/hotcocoa/mappings/appkit/status_item.rb +9 -0
  77. data/lib/hotcocoa/mappings/appkit/table_view.rb +108 -0
  78. data/lib/hotcocoa/mappings/appkit/text_field.rb +36 -0
  79. data/lib/hotcocoa/mappings/appkit/text_view.rb +13 -0
  80. data/lib/hotcocoa/mappings/appkit/toolbar.rb +99 -0
  81. data/lib/hotcocoa/mappings/appkit/toolbar_item.rb +36 -0
  82. data/lib/hotcocoa/mappings/appkit/tracking_area.rb +24 -0
  83. data/lib/hotcocoa/mappings/appkit/view.rb +65 -0
  84. data/lib/hotcocoa/mappings/appkit/window.rb +124 -0
  85. data/lib/hotcocoa/mappings/foundation/net_service.rb +65 -0
  86. data/lib/hotcocoa/mappings/foundation/net_service_browser.rb +27 -0
  87. data/lib/hotcocoa/mappings/foundation/notification.rb +24 -0
  88. data/lib/hotcocoa/mappings/foundation/sort_descriptor.rb +17 -0
  89. data/lib/hotcocoa/mappings/foundation/timer.rb +38 -0
  90. data/lib/hotcocoa/mappings/foundation/user_defaults.rb +43 -0
  91. data/lib/hotcocoa/mappings/foundation/xml_parser.rb +44 -0
  92. data/lib/hotcocoa/mappings/qtkit/movie.rb +15 -0
  93. data/lib/hotcocoa/mappings/qtkit/movie_view.rb +28 -0
  94. data/lib/hotcocoa/mappings/webkit/web_view.rb +20 -0
  95. data/lib/hotcocoa/mappings.rb +57 -111
  96. data/lib/hotcocoa/mvc.rb +90 -81
  97. data/lib/hotcocoa/notification_listener.rb +135 -58
  98. data/lib/hotcocoa/standard_rake_tasks.rb +17 -9
  99. data/lib/hotcocoa/target_action_convenience.rb +39 -0
  100. data/lib/hotcocoa/template.rb +90 -21
  101. data/lib/hotcocoa/version.rb +3 -0
  102. data/lib/hotcocoa.rb +12 -14
  103. data/template/Rakefile +31 -3
  104. data/template/__APPLICATION_NAME__.appspec +8 -0
  105. data/template/lib/application.rb +14 -17
  106. data/template/lib/menu.rb +11 -11
  107. data/test/application/test_builder.rb +28 -0
  108. data/test/application/test_specification.rb +280 -0
  109. data/test/core_extensions/test_kernel.rb +66 -0
  110. data/test/core_extensions/test_nsarray.rb +9 -0
  111. data/test/core_extensions/test_nsmutable_attributed_string.rb +86 -0
  112. data/test/core_extensions/test_nsstring.rb +20 -0
  113. data/test/core_extensions/test_nsurl.rb +9 -0
  114. data/test/core_extensions/test_numeric.rb +10 -0
  115. data/test/core_extensions/test_object.rb +37 -0
  116. data/test/core_extensions/test_range.rb +28 -0
  117. data/test/helper.rb +30 -0
  118. data/test/mappings/test_bonjour.rb +79 -0
  119. data/test/mappings/test_color.rb +16 -0
  120. data/test/mappings/test_font.rb +21 -0
  121. data/test/mappings/test_tracking_area.rb +18 -0
  122. data/test/test_application_builder.rb +95 -0
  123. data/test/test_attributed_string_helpers.rb +63 -0
  124. data/test/test_behaviours.rb +26 -0
  125. data/test/test_bin.rb +75 -0
  126. data/test/test_mapper.rb +100 -0
  127. data/test/test_mapping_methods.rb +67 -0
  128. data/test/test_mappings.rb +68 -0
  129. data/test/test_notification_listener.rb +19 -0
  130. data/test/test_template.rb +65 -0
  131. metadata +217 -90
  132. data/lib/hotcocoa/attributed_string.rb +0 -143
  133. data/lib/hotcocoa/kernel_ext.rb +0 -14
  134. data/lib/hotcocoa/mappings/alert.rb +0 -25
  135. data/lib/hotcocoa/mappings/application.rb +0 -112
  136. data/lib/hotcocoa/mappings/box.rb +0 -39
  137. data/lib/hotcocoa/mappings/button.rb +0 -92
  138. data/lib/hotcocoa/mappings/collection_view.rb +0 -44
  139. data/lib/hotcocoa/mappings/color.rb +0 -28
  140. data/lib/hotcocoa/mappings/column.rb +0 -21
  141. data/lib/hotcocoa/mappings/combo_box.rb +0 -24
  142. data/lib/hotcocoa/mappings/control.rb +0 -33
  143. data/lib/hotcocoa/mappings/font.rb +0 -44
  144. data/lib/hotcocoa/mappings/gradient.rb +0 -15
  145. data/lib/hotcocoa/mappings/image.rb +0 -15
  146. data/lib/hotcocoa/mappings/image_view.rb +0 -43
  147. data/lib/hotcocoa/mappings/label.rb +0 -25
  148. data/lib/hotcocoa/mappings/layout_view.rb +0 -9
  149. data/lib/hotcocoa/mappings/menu.rb +0 -71
  150. data/lib/hotcocoa/mappings/menu_item.rb +0 -47
  151. data/lib/hotcocoa/mappings/movie.rb +0 -13
  152. data/lib/hotcocoa/mappings/movie_view.rb +0 -27
  153. data/lib/hotcocoa/mappings/notification.rb +0 -17
  154. data/lib/hotcocoa/mappings/popup.rb +0 -110
  155. data/lib/hotcocoa/mappings/progress_indicator.rb +0 -68
  156. data/lib/hotcocoa/mappings/scroll_view.rb +0 -29
  157. data/lib/hotcocoa/mappings/search_field.rb +0 -9
  158. data/lib/hotcocoa/mappings/secure_text_field.rb +0 -17
  159. data/lib/hotcocoa/mappings/segmented_control.rb +0 -97
  160. data/lib/hotcocoa/mappings/slider.rb +0 -25
  161. data/lib/hotcocoa/mappings/sort_descriptor.rb +0 -13
  162. data/lib/hotcocoa/mappings/sound.rb +0 -9
  163. data/lib/hotcocoa/mappings/speech_synthesizer.rb +0 -25
  164. data/lib/hotcocoa/mappings/split_view.rb +0 -21
  165. data/lib/hotcocoa/mappings/status_bar.rb +0 -7
  166. data/lib/hotcocoa/mappings/status_item.rb +0 -9
  167. data/lib/hotcocoa/mappings/table_view.rb +0 -110
  168. data/lib/hotcocoa/mappings/text_field.rb +0 -41
  169. data/lib/hotcocoa/mappings/text_view.rb +0 -13
  170. data/lib/hotcocoa/mappings/timer.rb +0 -25
  171. data/lib/hotcocoa/mappings/toolbar.rb +0 -100
  172. data/lib/hotcocoa/mappings/toolbar_item.rb +0 -36
  173. data/lib/hotcocoa/mappings/view.rb +0 -67
  174. data/lib/hotcocoa/mappings/web_view.rb +0 -22
  175. data/lib/hotcocoa/mappings/window.rb +0 -118
  176. data/lib/hotcocoa/mappings/xml_parser.rb +0 -41
  177. data/lib/hotcocoa/object_ext.rb +0 -22
  178. data/lib/hotcocoa/plist.rb +0 -45
  179. data/template/config/build.yml +0 -8
  180. data/test/test_helper.rb +0 -3
  181. data/test/test_hotcocoa.rb +0 -11
@@ -1,17 +1,17 @@
1
- # Ruby Cocoa Graphics is a graphics library providing a simple object-oriented
2
- # interface into the power of Mac OS X's Core Graphics and Core Image drawing libraries.
3
- # With a few lines of easy-to-read code, you can write scripts to draw simple or complex
4
- # shapes, lines, and patterns, process and filter images, create abstract art or visualize
1
+ # Ruby Cocoa Graphics is a graphics library providing a simple object-oriented
2
+ # interface into the power of Mac OS X's Core Graphics and Core Image drawing libraries.
3
+ # With a few lines of easy-to-read code, you can write scripts to draw simple or complex
4
+ # shapes, lines, and patterns, process and filter images, create abstract art or visualize
5
5
  # scientific data, and much more.
6
- #
7
- # Inspiration for this project was derived from Processing and NodeBox. These excellent
8
- # graphics programming environments are more full-featured than RCG, but they are implemented
9
- # in Java and Python, respectively. RCG was created to offer similar functionality using
6
+ #
7
+ # Inspiration for this project was derived from Processing and NodeBox. These excellent
8
+ # graphics programming environments are more full-featured than RCG, but they are implemented
9
+ # in Java and Python, respectively. RCG was created to offer similar functionality using
10
10
  # the Ruby programming language.
11
11
  #
12
12
  # Author:: James Reynolds (mailto:drtoast@drtoast.com)
13
13
  # Copyright:: Copyright (c) 2008 James Reynolds
14
- # License:: Distributes under the same terms as Ruby
14
+ # License:: Distributes under the same terms as Ruby
15
15
 
16
16
  # In Quartz 2D, the canvas is often referred as the "page".
17
17
  # Overview of the underlying page concept available at:
@@ -22,7 +22,7 @@ module HotCocoa::Graphics
22
22
 
23
23
  # drawing destination for writing a PDF, PNG, GIF, JPG, or TIF file
24
24
  class Canvas
25
-
25
+
26
26
  BlendModes = {
27
27
  :normal => KCGBlendModeNormal,
28
28
  :darken => KCGBlendModeDarken,
@@ -43,44 +43,44 @@ module HotCocoa::Graphics
43
43
  :luminosity => KCGBlendModeLuminosity,
44
44
  }
45
45
  BlendModes.default(KCGBlendModeNormal)
46
-
46
+
47
47
  DefaultOptions = {:quality => 0.8, :width => 400, :height => 400}
48
-
49
- attr_accessor :width, :height
50
-
48
+
49
+ attr_accessor :width, :height
50
+
51
51
  # We make the context available so developers can directly use underlying CG methods
52
52
  # on objects created by this wrapper
53
53
  attr_reader :ctx
54
-
54
+
55
55
  class << self
56
56
  def for_rendering(options={}, &block)
57
57
  options[:type] = :render
58
58
  Canvas.new(options, &block)
59
59
  end
60
-
60
+
61
61
  def for_pdf(options={}, &block)
62
62
  options[:type] = :pdf
63
63
  Canvas.new(options, &block)
64
64
  end
65
-
65
+
66
66
  def for_image(options={}, &block)
67
67
  options[:type] = :image
68
68
  Canvas.new(options, &block)
69
69
  end
70
-
70
+
71
71
  def for_context(options={}, &block)
72
72
  options[:type] = :context
73
73
  Canvas.new(options, &block)
74
74
  end
75
-
75
+
76
76
  def for_current_context(options={}, &block)
77
77
  options[:type] = :context
78
78
  options[:context] = NSGraphicsContext.currentContext.graphicsPort
79
79
  Canvas.new(options, &block)
80
80
  end
81
-
81
+
82
82
  end
83
-
83
+
84
84
  # create a new canvas with the given width, height, and output filename (pdf, png, jpg, gif, or tif)
85
85
  def initialize(options={}, &block)
86
86
  if options[:size]
@@ -88,14 +88,14 @@ module HotCocoa::Graphics
88
88
  options[:height] = options[:size][1]
89
89
  end
90
90
  options = DefaultOptions.merge(options)
91
-
91
+
92
92
  @width = options[:width]
93
93
  @height = options[:height]
94
94
  @output = options[:filename] || 'test'
95
95
  @stacksize = 0
96
96
  @colorspace = CGColorSpaceCreateDeviceRGB() # => CGColorSpaceRef
97
97
  @autoclosepath = false
98
-
98
+
99
99
  case options[:type]
100
100
  when :pdf
101
101
  @filetype = :pdf
@@ -155,22 +155,22 @@ module HotCocoa::Graphics
155
155
  def verbose(tf=true)
156
156
  @verbose = tf
157
157
  end
158
-
158
+
159
159
  # set whether or not drawn paths should be antialiased (true/false)
160
160
  def antialias(tf=true)
161
161
  CGContextSetShouldAntialias(@ctx, tf)
162
162
  end
163
-
163
+
164
164
  # set the alpha value for subsequently drawn objects
165
165
  def alpha(val=1.0)
166
166
  CGContextSetAlpha(@ctx, val)
167
167
  end
168
-
168
+
169
169
  # set compression (0.0 = max, 1.0 = none)
170
170
  def quality(factor=0.8)
171
171
  @quality = factor
172
172
  end
173
-
173
+
174
174
  # set the current fill (given a Color object, or RGBA values)
175
175
  def fill(r=0, g=0, b=0, a=1)
176
176
  case r
@@ -183,15 +183,15 @@ module HotCocoa::Graphics
183
183
  CGContextSetRGBFillColor(@ctx, r, g, b, a) # RGBA
184
184
  @fill = true
185
185
  end
186
-
186
+
187
187
  # remove current fill
188
188
  def nofill
189
189
  CGContextSetRGBFillColor(@ctx, 0.0, 0.0, 0.0, 0.0) # RGBA
190
190
  @fill = nil
191
191
  end
192
-
192
+
193
193
  # SET CANVAS STROKE PARAMETERS
194
-
194
+
195
195
  # set stroke color (given a Color object, or RGBA values)
196
196
  def stroke(r=0, g=0, b=0, a=1.0)
197
197
  case r
@@ -204,18 +204,18 @@ module HotCocoa::Graphics
204
204
  CGContextSetRGBStrokeColor(@ctx, r, g, b, a) # RGBA
205
205
  @stroke = true
206
206
  end
207
-
207
+
208
208
  # set stroke width
209
209
  def strokewidth(width=1)
210
210
  CGContextSetLineWidth(@ctx, width.to_f)
211
211
  end
212
-
212
+
213
213
  # don't use a stroke for subsequent drawing operations
214
214
  def nostroke
215
215
  CGContextSetRGBStrokeColor(@ctx, 0, 0, 0, 0) # RGBA
216
216
  @stroke = false
217
217
  end
218
-
218
+
219
219
  # set cap style to round, square, or butt
220
220
  def linecap(style=:butt)
221
221
  case style
@@ -230,7 +230,7 @@ module HotCocoa::Graphics
230
230
  end
231
231
  CGContextSetLineCap(@ctx,cap)
232
232
  end
233
-
233
+
234
234
  # set line join style to round, miter, or bevel
235
235
  def linejoin(style=:miter)
236
236
  case style
@@ -245,21 +245,21 @@ module HotCocoa::Graphics
245
245
  end
246
246
  CGContextSetLineJoin(@ctx,join)
247
247
  end
248
-
248
+
249
249
  # set lengths of dashes and spaces, and distance before starting dashes
250
250
  def linedash(lengths=[10,2], phase=0.0)
251
251
  count=lengths.size
252
252
  CGContextSetLineDash(@ctx, phase, lengths, count)
253
253
  end
254
-
254
+
255
255
  # revert to solid lines
256
256
  def nodash
257
257
  CGContextSetLineDash(@ctx, 0.0, nil, 0)
258
258
  end
259
-
260
-
259
+
260
+
261
261
  # DRAWING SHAPES ON CANVAS
262
-
262
+
263
263
  # draw a rectangle starting at x,y and having dimensions w,h
264
264
  def rect(x=0, y=0, w=20, h=20, reg=@registration)
265
265
  # center the rectangle
@@ -270,7 +270,7 @@ module HotCocoa::Graphics
270
270
  CGContextAddRect(@ctx, NSMakeRect(x, y, w, h))
271
271
  CGContextDrawPath(@ctx, KCGPathFillStroke)
272
272
  end
273
-
273
+
274
274
  # inscribe an oval starting at x,y inside a rectangle having dimensions w,h
275
275
  def oval(x=0, y=0, w=20, h=20, reg=@registration)
276
276
  # center the oval
@@ -281,7 +281,7 @@ module HotCocoa::Graphics
281
281
  CGContextAddEllipseInRect(@ctx, NSMakeRect(x, y, w, h))
282
282
  CGContextDrawPath(@ctx, KCGPathFillStroke) # apply fill and stroke
283
283
  end
284
-
284
+
285
285
  # draw a background color (given a Color object, or RGBA values)
286
286
  def background(r=1, g=1, b=1, a=1.0)
287
287
  case r
@@ -296,7 +296,7 @@ module HotCocoa::Graphics
296
296
  rect(0,0,@width,@height)
297
297
  pop
298
298
  end
299
-
299
+
300
300
  # draw a radial gradiant starting at sx,sy with radius er
301
301
  # optional: specify ending at ex,ey and starting radius sr
302
302
  def radial(gradient, sx=@width/2, sy=@height/2, er=@width/2, ex=sx, ey=sy, sr=0.0)
@@ -304,7 +304,7 @@ module HotCocoa::Graphics
304
304
  #options = KCGGradientDrawsAfterEndLocation
305
305
  CGContextDrawRadialGradient(@ctx, gradient.gradient, NSMakePoint(sx, sy), sr, NSMakePoint(ex, ey), er, gradient.pre + gradient.post)
306
306
  end
307
-
307
+
308
308
  # draw an axial(linear) gradient starting at sx,sy and ending at ex,ey
309
309
  def gradient(gradient=Gradient.new, start_x=@width/2, start_y=0, end_x=@width/2, end_y=@height)
310
310
  #options = KCGGradientDrawsBeforeStartLocation
@@ -341,25 +341,25 @@ module HotCocoa::Graphics
341
341
  # restore previous state
342
342
  end
343
343
  end
344
-
345
-
344
+
345
+
346
346
  # DRAWING COMPLETE PATHS TO CANVAS
347
-
347
+
348
348
  # draw a line starting at x1,y1 and ending at x2,y2
349
349
  def line(x1, y1, x2, y2)
350
350
  CGContextAddLines(@ctx, [NSPoint.new(x1, y1), NSPoint.new(x2, y2)], 2)
351
351
  CGContextDrawPath(@ctx, KCGPathStroke) # apply stroke
352
352
  endpath
353
-
353
+
354
354
  end
355
-
355
+
356
356
  # draw a series of lines connecting the given array of points
357
357
  def lines(points)
358
358
  CGContextAddLines(@ctx, points, points.size)
359
359
  CGContextDrawPath(@ctx, KCGPathStroke) # apply stroke
360
360
  endpath
361
361
  end
362
-
362
+
363
363
  # draw the arc of a circle with center point x,y, radius, start angle (0 deg = 12 o'clock) and end angle
364
364
  def arc(x, y, radius, start_angle, end_angle)
365
365
  start_angle = radians(90-start_angle)
@@ -368,21 +368,21 @@ module HotCocoa::Graphics
368
368
  CGContextAddArc(@ctx, x, y, radius, start_angle, end_angle, clockwise)
369
369
  CGContextDrawPath(@ctx, KCGPathStroke)
370
370
  end
371
-
371
+
372
372
  # draw a bezier curve from the current point, given the coordinates of two handle control points and an end point
373
373
  def curve(cp1x, cp1y, cp2x, cp2y, x1, y1, x2, y2)
374
374
  beginpath(x1, y1)
375
375
  CGContextAddCurveToPoint(@ctx, cp1x, cp1y, cp2x, cp2y, x2, y2)
376
376
  endpath
377
377
  end
378
-
378
+
379
379
  # draw a quadratic bezier curve from x1,y1 to x2,y2, given the coordinates of one control point
380
380
  def qcurve(cpx, cpy, x1, y1, x2, y2)
381
381
  beginpath(x1, y1)
382
382
  CGContextAddQuadCurveToPoint(@ctx, cpx, cpy, x2, y2)
383
383
  endpath
384
384
  end
385
-
385
+
386
386
  # draw the given Path object
387
387
  def draw(object, *args)
388
388
  case object
@@ -401,13 +401,13 @@ module HotCocoa::Graphics
401
401
  def autoclosepath(tf=false)
402
402
  @autoclosepath = tf
403
403
  end
404
-
404
+
405
405
  def new_path(x, y, &block)
406
406
  beginpath(x, y)
407
407
  block.call
408
408
  endpath
409
409
  end
410
-
410
+
411
411
  # begin drawing a path at x,y
412
412
  def beginpath(x, y)
413
413
  CGContextBeginPath(@ctx)
@@ -421,7 +421,7 @@ module HotCocoa::Graphics
421
421
  mode = KCGPathFillStroke
422
422
  CGContextDrawPath(@ctx, mode) # apply fill and stroke
423
423
  end
424
-
424
+
425
425
  # move the "pen" to x,y
426
426
  def moveto(x, y)
427
427
  CGContextMoveToPoint(@ctx, x, y)
@@ -431,7 +431,7 @@ module HotCocoa::Graphics
431
431
  def lineto(x, y)
432
432
  CGContextAddLineToPoint(@ctx ,x, y)
433
433
  end
434
-
434
+
435
435
  # draw a bezier curve from the current point, given the coordinates of two handle control points and an end point
436
436
  def curveto(cp1x, cp1y, cp2x, cp2y, x, y)
437
437
  CGContextAddCurveToPoint(@ctx, cp1x, cp1y, cp2x, cp2y, x, y)
@@ -441,12 +441,12 @@ module HotCocoa::Graphics
441
441
  def qcurveto(cpx, cpy, x, y)
442
442
  CGContextAddQuadCurveToPoint(@ctx, cpx, cpy, x, y)
443
443
  end
444
-
444
+
445
445
  # draw an arc given the endpoints of two tangent lines and a radius
446
446
  def arcto(x1, y1, x2, y2, radius)
447
447
  CGContextAddArcToPoint(@ctx, x1, y1, x2, y2, radius)
448
448
  end
449
-
449
+
450
450
  # draw the path in a grid with rows, columns
451
451
  def grid(path, rows=10, cols=10)
452
452
  push
@@ -462,58 +462,58 @@ module HotCocoa::Graphics
462
462
  end
463
463
  pop
464
464
  end
465
-
465
+
466
466
 
467
467
  # TRANSFORMATIONS
468
-
468
+
469
469
  # set registration mode to :center or :corner
470
470
  def registration(mode=:center)
471
471
  @registration = mode
472
472
  end
473
-
473
+
474
474
  # rotate by the specified degrees
475
475
  def rotate(deg=0)
476
476
  CGContextRotateCTM(@ctx, radians(-deg));
477
477
  end
478
-
478
+
479
479
  # translate drawing context by x,y
480
480
  def translate(x, y)
481
481
  CGContextTranslateCTM(@ctx, x, y);
482
482
  end
483
-
483
+
484
484
  # scale drawing context by x,y
485
485
  def scale(x, y=x)
486
486
  CGContextScaleCTM(@ctx, x, y)
487
487
  end
488
-
488
+
489
489
  def skew(x=0, y=0)
490
490
  x = Math::PI * x / 180.0
491
491
  y = Math::PI * y / 180.0
492
492
  transform = CGAffineTransformMake(1.0, Math::tan(y), Math::tan(x), 1.0, 0.0, 0.0)
493
493
  CGContextConcatCTM(@ctx, transform)
494
494
  end
495
-
496
-
495
+
496
+
497
497
  # STATE
498
-
498
+
499
499
  def new_state(&block)
500
500
  push
501
501
  block.call
502
502
  pop
503
503
  end
504
-
504
+
505
505
  # push the current drawing context onto the stack
506
506
  def push
507
507
  CGContextSaveGState(@ctx)
508
508
  @stacksize = @stacksize + 1
509
509
  end
510
-
510
+
511
511
  # pop the previous drawing context off the stack
512
512
  def pop
513
513
  CGContextRestoreGState(@ctx)
514
514
  @stacksize = @stacksize - 1
515
515
  end
516
-
516
+
517
517
  # restore the initial context
518
518
  def reset
519
519
  until (@stacksize <= 1)
@@ -521,35 +521,35 @@ module HotCocoa::Graphics
521
521
  end
522
522
  push # push the retrieved pristine default state back onto the stack
523
523
  end
524
-
525
-
524
+
525
+
526
526
  # EFFECTS
527
-
527
+
528
528
  # apply a drop shadow with offset dx,dy, alpha, and blur
529
529
  def shadow(dx=0.0, dy=0.0, a=2.0/3.0, blur=5)
530
530
  color = CGColorCreate(@colorspace, [0.0, 0.0, 0.0, a])
531
531
  CGContextSetShadowWithColor(@ctx, [dx, dy], blur, color)
532
532
  end
533
-
533
+
534
534
  # apply a glow with offset dx,dy, alpha, and blur
535
535
  def glow(dx=0.0, dy=0.0, a=2.0/3.0, blur=5)
536
536
  color = CGColorCreate(@colorspace, [1.0, 1.0, 0.0, a])
537
537
  CGContextSetShadowWithColor(@ctx, [dx, dy], blur, color)
538
538
  end
539
-
539
+
540
540
  # stop using a shadow
541
541
  def noshadow
542
542
  CGContextSetShadowWithColor(@ctx, [0,0], 1, nil)
543
543
  end
544
-
544
+
545
545
  # set the canvas blend mode (:normal, :darken, :multiply, :screen, etc)
546
546
  def blend(mode)
547
547
  CGContextSetBlendMode(@ctx, BlendModes[mode])
548
548
  end
549
-
550
-
549
+
550
+
551
551
  # CLIPPING MASKS
552
-
552
+
553
553
  # clip subsequent drawing operations within the given path
554
554
  def beginclip(p, &block)
555
555
  push
@@ -560,17 +560,17 @@ module HotCocoa::Graphics
560
560
  endclip
561
561
  end
562
562
  end
563
-
563
+
564
564
  # stop clipping drawing operations
565
565
  def endclip
566
566
  pop
567
567
  end
568
-
568
+
569
569
  # DRAW TEXT TO CANVAS
570
-
570
+
571
571
  # NOTE: may want to switch to ATSUI for text handling
572
572
  # http://developer.apple.com/documentation/Carbon/Reference/ATSUI_Reference/Reference/reference.html
573
-
573
+
574
574
  # write the text at x,y using the current fill
575
575
  def text(txt="A", x=0, y=0)
576
576
  txt = txt.to_s unless txt.kind_of?(String)
@@ -581,7 +581,7 @@ module HotCocoa::Graphics
581
581
  end
582
582
  CGContextShowTextAtPoint(@ctx, x, y, txt, txt.length)
583
583
  end
584
-
584
+
585
585
  # determine the width of the given text without drawing it
586
586
  def textwidth(txt, width=nil)
587
587
  push
@@ -592,15 +592,15 @@ module HotCocoa::Graphics
592
592
  pop
593
593
  final.x - start.x
594
594
  end
595
-
595
+
596
596
  # def textheight(txt)
597
597
  # # need to use ATSUI
598
598
  # end
599
- #
599
+ #
600
600
  # def textmetrics(txt)
601
601
  # # need to use ATSUI
602
602
  # end
603
-
603
+
604
604
  # set font by name and optional size
605
605
  def font(name="Helvetica", size=nil)
606
606
  fontsize(size) if size
@@ -608,7 +608,7 @@ module HotCocoa::Graphics
608
608
  fontsize unless @fsize
609
609
  CGContextSelectFont(@ctx, @fname, @fsize, KCGEncodingMacRoman)
610
610
  end
611
-
611
+
612
612
  # set font size in points
613
613
  def fontsize(points=20)
614
614
  @fsize = points
@@ -616,22 +616,22 @@ module HotCocoa::Graphics
616
616
  #CGContextSetFontSize(@ctx,points)
617
617
  CGContextSelectFont(@ctx, @fname, @fsize, KCGEncodingMacRoman)
618
618
  end
619
-
620
-
619
+
620
+
621
621
  # SAVING/EXPORTING
622
-
622
+
623
623
  def nsimage
624
624
  image = NSImage.alloc.init
625
625
  image.addRepresentation(NSBitmapImageRep.alloc.initWithCGImage(cgimage))
626
626
  image
627
627
  end
628
-
628
+
629
629
  # return a CGImage of the canvas for reprocessing (only works if using a bitmap context)
630
630
  def cgimage
631
631
  CGBitmapContextCreateImage(@ctx) # => CGImageRef (works with bitmap context only)
632
632
  #cgimageref = CGImageCreate(@width, @height, @bits_per_component, nil,nil,@colorspace, nil, @provider,nil,true,KCGRenderingIntentDefault)
633
633
  end
634
-
634
+
635
635
  # return a CIImage of the canvas for reprocessing (only works if using a bitmap context)
636
636
  def ciimage
637
637
  cgimageref = self.cgimage
@@ -648,10 +648,10 @@ module HotCocoa::Graphics
648
648
  puts "WARNING: newpage only valid when using PDF output"
649
649
  end
650
650
  end
651
-
651
+
652
652
  # save the image to a file
653
653
  def save
654
-
654
+
655
655
  properties = {}
656
656
  # exif = {}
657
657
  # KCGImagePropertyExifDictionary
@@ -687,150 +687,147 @@ module HotCocoa::Graphics
687
687
  def open
688
688
  system "open #{@output}"
689
689
  end
690
-
690
+
691
691
  # def save(dest)
692
692
  ## http://developer.apple.com/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_data_mgr/chapter_11_section_3.html
693
693
  # properties = {
694
- #
694
+ #
695
695
  # }
696
696
  # cgimageref = CGBitmapContextCreateImage(@ctx) # => CGImageRef
697
697
  # destination = CGImageDestinationCreateWithURL(NSURL.fileURLWithPath(dest)) # => CGImageDestinationRef
698
698
  # CGImageDestinationSetProperties(destination,properties)
699
699
  # CGImageDestinationAddImage(cgimageref)
700
700
  # end
701
-
701
+
702
702
  private
703
-
704
- # DRAWING PATHS ON A CANVAS
705
-
706
- def draw_path(p, tx=0, ty=0, iterations=1)
707
- new_state do
708
- iterations.times do |i|
709
- if (i > 0)
710
- # INCREMENT TRANSFORM:
711
- # translate x, y
712
- translate(choose(p.inc[:x]), choose(p.inc[:y]))
713
- # choose a rotation factor from the range
714
- rotate(choose(p.inc[:rotation]))
715
- # choose a scaling factor from the range
716
- sc = choose(p.inc[:scale])
717
- sx = choose(p.inc[:scalex]) * sc
718
- sy = p.inc[:scaley] ? choose(p.inc[:scaley]) * sc : sx * sc
719
- scale(sx, sy)
720
- end
721
703
 
722
- new_state do
723
- # PICK AND ADJUST FILL/STROKE COLORS:
724
- [:fill,:stroke].each do |kind|
725
- # PICK A COLOR
726
- if (p.inc[kind]) then
727
- # increment color from array
728
- colorindex = i % p.inc[kind].size
729
- c = p.inc[kind][colorindex].copy
730
- else
731
- c = p.rand[kind]
732
- case c
733
- when Array
734
- c = choose(c).copy
735
- when Color
736
- c = c.copy
737
- else
738
- next
739
- end
740
- end
704
+ # DRAWING PATHS ON A CANVAS
705
+
706
+ def draw_path(p, tx=0, ty=0, iterations=1)
707
+ new_state do
708
+ iterations.times do |i|
709
+ if (i > 0)
710
+ # INCREMENT TRANSFORM:
711
+ # translate x, y
712
+ translate(choose(p.inc[:x]), choose(p.inc[:y]))
713
+ # choose a rotation factor from the range
714
+ rotate(choose(p.inc[:rotation]))
715
+ # choose a scaling factor from the range
716
+ sc = choose(p.inc[:scale])
717
+ sx = choose(p.inc[:scalex]) * sc
718
+ sy = p.inc[:scaley] ? choose(p.inc[:scaley]) * sc : sx * sc
719
+ scale(sx, sy)
720
+ end
741
721
 
742
- if (p.inc[:hue] or p.inc[:saturation] or p.inc[:brightness])
743
- # ITERATE COLOR
744
- if (p.inc[:hue])
745
- newhue = (c.hue + choose(p.inc[:hue])) % 1
746
- c.hue(newhue)
747
- end
748
- if (p.inc[:saturation])
749
- newsat = (c.saturation + choose(p.inc[:saturation]))
750
- c.saturation(newsat)
751
- end
752
- if (p.inc[:brightness])
753
- newbright = (c.brightness + choose(p.inc[:brightness]))
754
- c.brightness(newbright)
755
- end
756
- if (p.inc[:alpha])
757
- newalpha = (c.a + choose(p.inc[:alpha]))
758
- c.a(newalpha)
759
- end
760
- p.rand[kind] = c
722
+ new_state do
723
+ # PICK AND ADJUST FILL/STROKE COLORS:
724
+ [:fill,:stroke].each do |kind|
725
+ # PICK A COLOR
726
+ if (p.inc[kind]) then
727
+ # increment color from array
728
+ colorindex = i % p.inc[kind].size
729
+ c = p.inc[kind][colorindex].copy
730
+ else
731
+ c = p.rand[kind]
732
+ case c
733
+ when Array
734
+ c = choose(c).copy
735
+ when Color
736
+ c = c.copy
761
737
  else
762
- # RANDOMIZE COLOR
763
- c.hue(choose(p.rand[:hue])) if p.rand[:hue]
764
- c.saturation(choose(p.rand[:saturation])) if p.rand[:saturation]
765
- c.brightness(choose(p.rand[:brightness])) if p.rand[:brightness]
738
+ next
766
739
  end
767
-
768
- # APPLY COLOR
769
- fill(c) if kind == :fill
770
- stroke(c) if kind == :stroke
771
740
  end
772
- # choose a stroke width from the range
773
- strokewidth(choose(p.rand[:strokewidth])) if p.rand[:strokewidth]
774
- # choose an alpha level from the range
775
- alpha(choose(p.rand[:alpha])) if p.rand[:alpha]
776
-
777
- # RANDOMIZE TRANSFORM:
778
- # translate x, y
779
- translate(choose(p.rand[:x]), choose(p.rand[:y]))
780
- # choose a rotation factor from the range
781
- rotate(choose(p.rand[:rotation]))
782
- # choose a scaling factor from the range
783
- sc = choose(p.rand[:scale])
784
- sx = choose(p.rand[:scalex]) * sc
785
- sy = p.rand[:scaley] ? choose(p.rand[:scaley]) * sc : sx * sc
786
- scale(sx,sy)
787
-
788
- # DRAW
789
- if (tx > 0 || ty > 0)
790
- translate(tx, ty)
741
+
742
+ if (p.inc[:hue] or p.inc[:saturation] or p.inc[:brightness])
743
+ # ITERATE COLOR
744
+ if (p.inc[:hue])
745
+ newhue = (c.hue + choose(p.inc[:hue])) % 1
746
+ c.hue(newhue)
747
+ end
748
+ if (p.inc[:saturation])
749
+ newsat = (c.saturation + choose(p.inc[:saturation]))
750
+ c.saturation(newsat)
751
+ end
752
+ if (p.inc[:brightness])
753
+ newbright = (c.brightness + choose(p.inc[:brightness]))
754
+ c.brightness(newbright)
755
+ end
756
+ if (p.inc[:alpha])
757
+ newalpha = (c.a + choose(p.inc[:alpha]))
758
+ c.a(newalpha)
759
+ end
760
+ p.rand[kind] = c
761
+ else
762
+ # RANDOMIZE COLOR
763
+ c.hue(choose(p.rand[:hue])) if p.rand[:hue]
764
+ c.saturation(choose(p.rand[:saturation])) if p.rand[:saturation]
765
+ c.brightness(choose(p.rand[:brightness])) if p.rand[:brightness]
791
766
  end
792
767
 
793
- CGContextAddPath(@ctx, p.path) if p.class == Path
794
- CGContextDrawPath(@ctx, KCGPathFillStroke) # apply fill and stroke
768
+ # APPLY COLOR
769
+ fill(c) if kind == :fill
770
+ stroke(c) if kind == :stroke
771
+ end
772
+ # choose a stroke width from the range
773
+ strokewidth(choose(p.rand[:strokewidth])) if p.rand[:strokewidth]
774
+ # choose an alpha level from the range
775
+ alpha(choose(p.rand[:alpha])) if p.rand[:alpha]
795
776
 
796
- # if there's an image, draw it clipped by the path
797
- if (p.image)
798
- beginclip(p)
799
- image(p.image)
800
- endclip
801
- end
777
+ # RANDOMIZE TRANSFORM:
778
+ # translate x, y
779
+ translate(choose(p.rand[:x]), choose(p.rand[:y]))
780
+ # choose a rotation factor from the range
781
+ rotate(choose(p.rand[:rotation]))
782
+ # choose a scaling factor from the range
783
+ sc = choose(p.rand[:scale])
784
+ sx = choose(p.rand[:scalex]) * sc
785
+ sy = p.rand[:scaley] ? choose(p.rand[:scaley]) * sc : sx * sc
786
+ scale(sx,sy)
802
787
 
788
+ # DRAW
789
+ if (tx > 0 || ty > 0)
790
+ translate(tx, ty)
803
791
  end
792
+
793
+ CGContextAddPath(@ctx, p.path) if p.class == Path
794
+ CGContextDrawPath(@ctx, KCGPathFillStroke) # apply fill and stroke
795
+
796
+ # if there's an image, draw it clipped by the path
797
+ if (p.image)
798
+ beginclip(p)
799
+ image(p.image)
800
+ endclip
801
+ end
802
+
804
803
  end
805
804
  end
806
805
  end
807
-
808
- # DRAWING IMAGES ON CANVAS
809
-
810
- # draw the specified image at x,y with dimensions w,h.
811
- # "img" may be a path to an image, or an Image instance
812
- def draw_image(img, x=0, y=0, w=nil, h=nil, pagenum=1)
813
- new_state do
814
- if (img.kind_of?(Pdf))
815
- w ||= img.width(pagenum)
816
- h ||= img.height(pagenum)
817
- if(@registration == :center)
818
- x = x - w / 2
819
- y = y - h / 2
820
- end
821
- img.draw(@ctx, x, y, w, h, pagenum)
822
- elsif(img.kind_of?(String) || img.kind_of?(Image))
823
- img = Image.new(img) if img.kind_of?(String)
824
- w ||= img.width
825
- h ||= img.height
826
- img.draw(@ctx, x, y, w, h)
827
- else
828
- raise ArgumentError.new("canvas.image: not a recognized image type: #{img.class}")
806
+ end
807
+
808
+ # DRAWING IMAGES ON CANVAS
809
+
810
+ # draw the specified image at x,y with dimensions w,h.
811
+ # "img" may be a path to an image, or an Image instance
812
+ def draw_image(img, x=0, y=0, w=nil, h=nil, pagenum=1)
813
+ new_state do
814
+ if (img.kind_of?(Pdf))
815
+ w ||= img.width(pagenum)
816
+ h ||= img.height(pagenum)
817
+ if(@registration == :center)
818
+ x = x - w / 2
819
+ y = y - h / 2
829
820
  end
821
+ img.draw(@ctx, x, y, w, h, pagenum)
822
+ elsif(img.kind_of?(String) || img.kind_of?(Image))
823
+ img = Image.new(img) if img.kind_of?(String)
824
+ w ||= img.width
825
+ h ||= img.height
826
+ img.draw(@ctx, x, y, w, h)
827
+ else
828
+ raise ArgumentError.new("canvas.image: not a recognized image type: #{img.class}")
830
829
  end
831
830
  end
832
-
833
-
831
+ end
834
832
  end
835
-
836
833
  end