giga-fast-kit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/giga-fast-kit.gemspec +12 -0
  3. data/prawn-2.5.0/COPYING +2 -0
  4. data/prawn-2.5.0/GPLv2 +339 -0
  5. data/prawn-2.5.0/GPLv3 +674 -0
  6. data/prawn-2.5.0/LICENSE +56 -0
  7. data/prawn-2.5.0/data/fonts/Courier-Bold.afm +342 -0
  8. data/prawn-2.5.0/data/fonts/Courier-BoldOblique.afm +342 -0
  9. data/prawn-2.5.0/data/fonts/Courier-Oblique.afm +342 -0
  10. data/prawn-2.5.0/data/fonts/Courier.afm +342 -0
  11. data/prawn-2.5.0/data/fonts/Helvetica-Bold.afm +2827 -0
  12. data/prawn-2.5.0/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  13. data/prawn-2.5.0/data/fonts/Helvetica-Oblique.afm +3051 -0
  14. data/prawn-2.5.0/data/fonts/Helvetica.afm +3051 -0
  15. data/prawn-2.5.0/data/fonts/MustRead.html +19 -0
  16. data/prawn-2.5.0/data/fonts/Symbol.afm +213 -0
  17. data/prawn-2.5.0/data/fonts/Times-Bold.afm +2588 -0
  18. data/prawn-2.5.0/data/fonts/Times-BoldItalic.afm +2384 -0
  19. data/prawn-2.5.0/data/fonts/Times-Italic.afm +2667 -0
  20. data/prawn-2.5.0/data/fonts/Times-Roman.afm +2419 -0
  21. data/prawn-2.5.0/data/fonts/ZapfDingbats.afm +225 -0
  22. data/prawn-2.5.0/lib/prawn/document/bounding_box.rb +625 -0
  23. data/prawn-2.5.0/lib/prawn/document/column_box.rb +177 -0
  24. data/prawn-2.5.0/lib/prawn/document/internals.rb +76 -0
  25. data/prawn-2.5.0/lib/prawn/document/span.rb +65 -0
  26. data/prawn-2.5.0/lib/prawn/document.rb +846 -0
  27. data/prawn-2.5.0/lib/prawn/encoding.rb +85 -0
  28. data/prawn-2.5.0/lib/prawn/errors.rb +73 -0
  29. data/prawn-2.5.0/lib/prawn/font.rb +567 -0
  30. data/prawn-2.5.0/lib/prawn/font_metric_cache.rb +50 -0
  31. data/prawn-2.5.0/lib/prawn/fonts/afm.rb +332 -0
  32. data/prawn-2.5.0/lib/prawn/fonts/dfont.rb +42 -0
  33. data/prawn-2.5.0/lib/prawn/fonts/otf.rb +14 -0
  34. data/prawn-2.5.0/lib/prawn/fonts/to_unicode_cmap.rb +151 -0
  35. data/prawn-2.5.0/lib/prawn/fonts/ttc.rb +41 -0
  36. data/prawn-2.5.0/lib/prawn/fonts/ttf.rb +615 -0
  37. data/prawn-2.5.0/lib/prawn/fonts.rb +14 -0
  38. data/prawn-2.5.0/lib/prawn/graphics/blend_mode.rb +62 -0
  39. data/prawn-2.5.0/lib/prawn/graphics/cap_style.rb +44 -0
  40. data/prawn-2.5.0/lib/prawn/graphics/color.rb +257 -0
  41. data/prawn-2.5.0/lib/prawn/graphics/dash.rb +123 -0
  42. data/prawn-2.5.0/lib/prawn/graphics/join_style.rb +60 -0
  43. data/prawn-2.5.0/lib/prawn/graphics/patterns.rb +389 -0
  44. data/prawn-2.5.0/lib/prawn/graphics/transformation.rb +172 -0
  45. data/prawn-2.5.0/lib/prawn/graphics/transparency.rb +79 -0
  46. data/prawn-2.5.0/lib/prawn/graphics.rb +791 -0
  47. data/prawn-2.5.0/lib/prawn/grid.rb +449 -0
  48. data/prawn-2.5.0/lib/prawn/image_handler.rb +61 -0
  49. data/prawn-2.5.0/lib/prawn/images/image.rb +48 -0
  50. data/prawn-2.5.0/lib/prawn/images/jpg.rb +121 -0
  51. data/prawn-2.5.0/lib/prawn/images/png.rb +383 -0
  52. data/prawn-2.5.0/lib/prawn/images.rb +195 -0
  53. data/prawn-2.5.0/lib/prawn/measurement_extensions.rb +82 -0
  54. data/prawn-2.5.0/lib/prawn/measurements.rb +129 -0
  55. data/prawn-2.5.0/lib/prawn/outline.rb +316 -0
  56. data/prawn-2.5.0/lib/prawn/repeater.rb +140 -0
  57. data/prawn-2.5.0/lib/prawn/security/arcfour.rb +54 -0
  58. data/prawn-2.5.0/lib/prawn/security.rb +308 -0
  59. data/prawn-2.5.0/lib/prawn/soft_mask.rb +105 -0
  60. data/prawn-2.5.0/lib/prawn/stamp.rb +147 -0
  61. data/prawn-2.5.0/lib/prawn/text/box.rb +192 -0
  62. data/prawn-2.5.0/lib/prawn/text/formatted/arranger.rb +396 -0
  63. data/prawn-2.5.0/lib/prawn/text/formatted/box.rb +725 -0
  64. data/prawn-2.5.0/lib/prawn/text/formatted/fragment.rb +373 -0
  65. data/prawn-2.5.0/lib/prawn/text/formatted/line_wrap.rb +335 -0
  66. data/prawn-2.5.0/lib/prawn/text/formatted/parser.rb +284 -0
  67. data/prawn-2.5.0/lib/prawn/text/formatted/wrap.rb +166 -0
  68. data/prawn-2.5.0/lib/prawn/text/formatted.rb +82 -0
  69. data/prawn-2.5.0/lib/prawn/text.rb +701 -0
  70. data/prawn-2.5.0/lib/prawn/transformation_stack.rb +63 -0
  71. data/prawn-2.5.0/lib/prawn/utilities.rb +34 -0
  72. data/prawn-2.5.0/lib/prawn/version.rb +6 -0
  73. data/prawn-2.5.0/lib/prawn/view.rb +116 -0
  74. data/prawn-2.5.0/lib/prawn.rb +83 -0
  75. metadata +114 -0
@@ -0,0 +1,791 @@
1
+ # frozen_string_literal: true
2
+
3
+ # graphics.rb : Implements PDF drawing primitives
4
+ #
5
+ # Copyright April 2008, Gregory Brown. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ require_relative 'graphics/blend_mode'
10
+ require_relative 'graphics/color'
11
+ require_relative 'graphics/dash'
12
+ require_relative 'graphics/cap_style'
13
+ require_relative 'graphics/join_style'
14
+ require_relative 'graphics/transparency'
15
+ require_relative 'graphics/transformation'
16
+ require_relative 'graphics/patterns'
17
+
18
+ module Prawn
19
+ # Implements the drawing facilities for {Prawn::Document}.
20
+ # Use this to draw the most beautiful imaginable things.
21
+ module Graphics
22
+ include BlendMode
23
+ include Color
24
+ include Dash
25
+ include CapStyle
26
+ include JoinStyle
27
+ include Transparency
28
+ include Transformation
29
+ include Patterns
30
+
31
+ # @group Stable API
32
+
33
+ #######################################################################
34
+ # Low level drawing operations must map the point to absolute coords! #
35
+ #######################################################################
36
+
37
+ # Moves the drawing position to a given point. The point can be specified as
38
+ # a tuple or a flattened argument list.
39
+ #
40
+ # @example
41
+ # pdf.move_to [100, 50]
42
+ # pdf.move_to(100, 50)
43
+ #
44
+ # @overload move_to(point)
45
+ # @param point [Array(Number, Number)]
46
+ # @return [void]
47
+ # @overload move_to(x, y)
48
+ # @param x [Number]
49
+ # @param y [Number]
50
+ # @return [void]
51
+ def move_to(*point)
52
+ xy = PDF::Core.real_params(map_to_absolute(point))
53
+ renderer.add_content("#{xy} m")
54
+ end
55
+
56
+ # Draws a line from the current drawing position to the specified point.
57
+ # The destination may be described as a tuple or a flattened list:
58
+ #
59
+ # @example
60
+ # pdf.line_to [50, 50]
61
+ # pdf.line_to(50, 50)
62
+ #
63
+ # @overload line_to(point)
64
+ # @param point [Array(Number, Number)]
65
+ # @return [void]
66
+ # @overload line_to(x, y)
67
+ # @param x [Number]
68
+ # @param y [Number]
69
+ # @return [void]
70
+ def line_to(*point)
71
+ xy = PDF::Core.real_params(map_to_absolute(point))
72
+ renderer.add_content("#{xy} l")
73
+ end
74
+
75
+ # Draws a Bezier curve from the current drawing position to the
76
+ # specified point, bounded by two additional points.
77
+ #
78
+ # @example
79
+ # pdf.curve_to [100, 100], bounds: [[90, 90], [75, 75]]
80
+ #
81
+ # @param dest [Array(Number, Number)]
82
+ # @param options [Hash]
83
+ # @option options :bounds [Array(Array(Number, Number), Array(Number, Number))]
84
+ # @return [void]
85
+ def curve_to(dest, options = {})
86
+ options[:bounds] || raise(
87
+ Prawn::Errors::InvalidGraphicsPath,
88
+ 'Bounding points for bezier curve must be specified as :bounds => [[x1,y1],[x2,y2]]',
89
+ )
90
+
91
+ curve_points = PDF::Core.real_params(
92
+ (options[:bounds] << dest).flat_map { |e| map_to_absolute(e) },
93
+ )
94
+
95
+ renderer.add_content("#{curve_points} c")
96
+ end
97
+
98
+ # Draws a rectangle given `point`, `width and `height`. The rectangle is
99
+ # bounded by its upper-left corner.
100
+ #
101
+ # @example
102
+ # pdf.rectangle [300, 300], 100, 200
103
+ #
104
+ # @param point [Array(Number, Number)]
105
+ # @param width [Number]
106
+ # @param height [Number]
107
+ # @return [void]
108
+ def rectangle(point, width, height)
109
+ x, y = map_to_absolute(point)
110
+ box = PDF::Core.real_params([x, y - height, width, height])
111
+
112
+ renderer.add_content("#{box} re")
113
+ end
114
+
115
+ # Draws a rounded rectangle given `point`, `width`, `height`, and `radius`
116
+ # for the rounded corner. The rectangle is bounded by its upper-left corner.
117
+ #
118
+ # @example
119
+ # pdf.rounded_rectangle [300, 300], 100, 200, 10
120
+ #
121
+ # @param point [Array(Number, Number)]
122
+ # @param width [Number]
123
+ # @param height [Number]
124
+ # @param radius [Number]
125
+ # @return [void]
126
+ def rounded_rectangle(point, width, height, radius)
127
+ x, y = point
128
+ rounded_polygon(
129
+ radius, point, [x + width, y], [x + width, y - height], [x, y - height],
130
+ )
131
+ end
132
+
133
+ ###########################################################
134
+ # Higher level functions: May use relative coords #
135
+ ###########################################################
136
+
137
+ # Sets line thickness to the `width` specified.
138
+ #
139
+ # @param width [Number]
140
+ # @return [void]
141
+ def line_width=(width)
142
+ self.current_line_width = width
143
+ write_line_width
144
+ end
145
+
146
+ # When called without an argument, returns the current line thickness.
147
+ # When called with an argument, sets the line thickness to the specified
148
+ # value (in PDF points).
149
+ #
150
+ # @example
151
+ # pdf.line_width #=> 1
152
+ # pdf.line_width(5)
153
+ # pdf.line_width #=> 5
154
+ #
155
+ # @overload line_width()
156
+ # @return [Number]
157
+ # @overload line_width(width)
158
+ # @param width [Number]
159
+ # @return [void]
160
+ def line_width(width = nil)
161
+ if width
162
+ self.line_width = width
163
+ else
164
+ current_line_width
165
+ end
166
+ end
167
+
168
+ # Draws a line from one point to another. Points may be specified as
169
+ # tuples or flattened argument list.
170
+ #
171
+ # @example
172
+ # pdf.line [100, 100], [200, 250]
173
+ # pdf.line(100, 100, 200, 250)
174
+ #
175
+ # @overload line(point1, point2)
176
+ # @param point1 [Array(Number, Number)]
177
+ # @param point2 [Array(Number, Number)]
178
+ # @return [void]
179
+ # @overload line(x1, y1, x2, y2)
180
+ # @param x1 [Number]
181
+ # @param y1 [Number]
182
+ # @param x2 [Number]
183
+ # @param y2 [Number]
184
+ # @return [void]
185
+ def line(*points)
186
+ x0, y0, x1, y1 = points.flatten
187
+ move_to(x0, y0)
188
+ line_to(x1, y1)
189
+ end
190
+
191
+ # Draws a horizontal line from `x1` to `x2` at the current {Document#y}
192
+ # position, or the position specified by the `:at` option.
193
+ #
194
+ # @example Draw a line from `[25, 75]` to `[100, 75]`
195
+ # horizontal_line 25, 100, at: 75
196
+ #
197
+ # @param x1 [Number]
198
+ # @param x2 [Number]
199
+ # @param options [Hash]
200
+ # @option options :at [Number]
201
+ # @return [void]
202
+ def horizontal_line(x1, x2, options = {})
203
+ y1 = options[:at] || (y - bounds.absolute_bottom)
204
+
205
+ line(x1, y1, x2, y1)
206
+ end
207
+
208
+ # Draws a horizontal line from the left border to the right border of the
209
+ # bounding box at the current {Document#y} position.
210
+ #
211
+ # @return [void]
212
+ def horizontal_rule
213
+ horizontal_line(bounds.left, bounds.right)
214
+ end
215
+
216
+ # Draws a vertical line at the x coordinate given by `:at` from `y1` to
217
+ # `y2`.
218
+ #
219
+ # @example Draw a line from `[25, 100]` to `[25, 300]`
220
+ # vertical_line 100, 300, at: 25
221
+ #
222
+ # @param y1 [Number]
223
+ # @param y2 [Number]
224
+ # @param params [Hash]
225
+ # @option params :at [Number]
226
+ # @return [void]
227
+ def vertical_line(y1, y2, params)
228
+ line(params[:at], y1, params[:at], y2)
229
+ end
230
+
231
+ # Draws a Bezier curve between two points, bounded by two additional
232
+ # points
233
+ #
234
+ # @example
235
+ # pdf.curve [50, 100], [100, 100], bounds: [[90, 90], [75, 75]]
236
+ #
237
+ # @param origin [Array(Number, Number)]
238
+ # @param dest [Array(Number, Number)]
239
+ # @param options [Hash]
240
+ # @option options :bounds [Array(Array(Number, Number), Array(Number, Number))]
241
+ # @return [void]
242
+ def curve(origin, dest, options = {})
243
+ move_to(*origin)
244
+ curve_to(dest, options)
245
+ end
246
+
247
+ # This constant is used to approximate a symmetrical arc using a cubic
248
+ # Bezier curve.
249
+ KAPPA = 4.0 * ((Math.sqrt(2) - 1.0) / 3.0)
250
+
251
+ # Draws a circle of radius `radius` with the centre-point at
252
+ # `point` as a complete subpath. The drawing point will be moved to
253
+ # the centre-point upon completion of the drawing the circle.
254
+ #
255
+ # @example
256
+ # pdf.circle [100, 100], 25
257
+ #
258
+ # @param center [Array(Number, Number)]
259
+ # @param radius [Number]
260
+ # @return [void]
261
+ def circle(center, radius)
262
+ ellipse(center, radius, radius)
263
+ end
264
+
265
+ # Draws an ellipse of `x` radius `radius1` and `y` radius `radius2` with the
266
+ # centre-point at `point` as a complete subpath. The drawing point will be
267
+ # moved to the centre-point upon completion of the drawing the ellipse.
268
+ #
269
+ # @example Draws an ellipse with x-radius 25 and y-radius 50
270
+ # pdf.ellipse [100, 100], 25, 50
271
+ #
272
+ # @param point [Array(Number, Number)]
273
+ # @param radius1 [Number]
274
+ # @param radius2 [Number]
275
+ # @return [void]
276
+ def ellipse(point, radius1, radius2 = radius1)
277
+ x, y = point
278
+ l1 = radius1 * KAPPA
279
+ l2 = radius2 * KAPPA
280
+
281
+ move_to(x + radius1, y)
282
+
283
+ # Upper right hand corner
284
+ curve_to(
285
+ [x, y + radius2],
286
+ bounds: [[x + radius1, y + l2], [x + l1, y + radius2]],
287
+ )
288
+
289
+ # Upper left hand corner
290
+ curve_to(
291
+ [x - radius1, y],
292
+ bounds: [[x - l1, y + radius2], [x - radius1, y + l2]],
293
+ )
294
+
295
+ # Lower left hand corner
296
+ curve_to(
297
+ [x, y - radius2],
298
+ bounds: [[x - radius1, y - l2], [x - l1, y - radius2]],
299
+ )
300
+
301
+ # Lower right hand corner
302
+ curve_to(
303
+ [x + radius1, y],
304
+ bounds: [[x + l1, y - radius2], [x + radius1, y - l2]],
305
+ )
306
+
307
+ move_to(x, y)
308
+ end
309
+
310
+ # Draws a polygon from the specified points.
311
+ #
312
+ # @example Draws a snazzy triangle
313
+ # pdf.polygon [100,100], [100,200], [200,200]
314
+ #
315
+ # @param points [Array<Array(Number, Number)>]
316
+ # @return [void]
317
+ def polygon(*points)
318
+ move_to(points[0])
319
+ (points[1..] << points[0]).each do |point|
320
+ line_to(*point)
321
+ end
322
+ # close the path
323
+ renderer.add_content('h')
324
+ end
325
+
326
+ # Draws a rounded polygon from specified points using the radius to define
327
+ # bezier curves.
328
+ #
329
+ # @example Draws a rounded filled in polygon
330
+ # pdf.fill_and_stroke_rounded_polygon(
331
+ # 10, [100, 250], [200, 300], [300, 250], [300, 150], [200, 100],
332
+ # [100, 150]
333
+ # )
334
+ #
335
+ # @param radius [Number]
336
+ # @param points [Array<Array(Number, Number)>]
337
+ # @return [void]
338
+ def rounded_polygon(radius, *points)
339
+ move_to(point_on_line(radius, points[1], points[0]))
340
+ sides = points.size
341
+ points << points[0] << points[1]
342
+ sides.times do |i|
343
+ rounded_vertex(radius, points[i], points[i + 1], points[i + 2])
344
+ end
345
+ # close the path
346
+ renderer.add_content('h')
347
+ end
348
+
349
+ # Creates a rounded vertex for a line segment used for building a rounded
350
+ # polygon requires a radius to define bezier curve and three points. The
351
+ # first two points define the line segment and the third point helps define
352
+ # the curve for the vertex.
353
+ #
354
+ # @param radius [Number]
355
+ # @param points [Array(Array(Number, Number), Array(Number, Number), Array(Number, Number))]
356
+ # @return [void]
357
+ def rounded_vertex(radius, *points)
358
+ radial_point1 = point_on_line(radius, points[0], points[1])
359
+ bezier_point1 = point_on_line(
360
+ (radius - (radius * KAPPA)),
361
+ points[0],
362
+ points[1],
363
+ )
364
+ radial_point2 = point_on_line(radius, points[2], points[1])
365
+ bezier_point2 = point_on_line(
366
+ (radius - (radius * KAPPA)),
367
+ points[2],
368
+ points[1],
369
+ )
370
+ line_to(radial_point1)
371
+ curve_to(radial_point2, bounds: [bezier_point1, bezier_point2])
372
+ end
373
+
374
+ # Strokes the current path. If a block is provided, yields to the block
375
+ # before closing the path. See {Graphics::Color} for color details.
376
+ #
377
+ # @yield
378
+ # @return [void]
379
+ def stroke
380
+ yield if block_given?
381
+ renderer.add_content('S')
382
+ end
383
+
384
+ # Closes and strokes the current path. If a block is provided, yields to the
385
+ # block before closing the path. See {Graphics::Color} for color details.
386
+ #
387
+ # @yield
388
+ # @return [void]
389
+ def close_and_stroke
390
+ yield if block_given?
391
+ renderer.add_content('s')
392
+ end
393
+
394
+ # Draws and strokes a rectangle represented by the current bounding box.
395
+ #
396
+ # @return [void]
397
+ def stroke_bounds
398
+ stroke_rectangle(bounds.top_left, bounds.width, bounds.height)
399
+ end
400
+
401
+ # Draws and strokes X and Y axes rulers beginning at the current bounding
402
+ # box origin (or at a custom location).
403
+ #
404
+ # @param options [Hash]
405
+ # @option options :at [Array(Number, Number)] ([0, 0], origin of the bounding box)
406
+ # Origin of the X and Y axes.
407
+ # @option options :width [Number] (width of the bounding box)
408
+ # Length of the X axis.
409
+ # @option options :height [Number] (height of the bounding box)
410
+ # Length of the Y axis.
411
+ # @option options :step_length [Number] (100)
412
+ # Length of the step between markers.
413
+ # @option options :negative_axes_length [Number] (20)
414
+ # Length of the negative parts of the axes.
415
+ # @option options :color [String, Array<Number>]
416
+ # The color of the axes and the text.
417
+ # @return [void]
418
+ def stroke_axis(options = {})
419
+ options = {
420
+ at: [0, 0],
421
+ height: bounds.height - (options[:at] || [0, 0])[1],
422
+ width: bounds.width - (options[:at] || [0, 0])[0],
423
+ step_length: 100,
424
+ negative_axes_length: 20,
425
+ color: '000000',
426
+ }.merge(options)
427
+
428
+ Prawn.verify_options(
429
+ %i[at width height step_length negative_axes_length color],
430
+ options,
431
+ )
432
+
433
+ save_graphics_state do
434
+ fill_color(options[:color])
435
+ stroke_color(options[:color])
436
+
437
+ dash(1, space: 4)
438
+ stroke_horizontal_line(
439
+ options[:at][0] - options[:negative_axes_length],
440
+ options[:at][0] + options[:width],
441
+ at: options[:at][1],
442
+ )
443
+ stroke_vertical_line(
444
+ options[:at][1] - options[:negative_axes_length],
445
+ options[:at][1] + options[:height],
446
+ at: options[:at][0],
447
+ )
448
+ undash
449
+
450
+ fill_circle(options[:at], 1)
451
+
452
+ (options[:step_length]..options[:width])
453
+ .step(options[:step_length]) do |point|
454
+ fill_circle([options[:at][0] + point, options[:at][1]], 1)
455
+ draw_text(
456
+ point,
457
+ at: [options[:at][0] + point - 5, options[:at][1] - 10],
458
+ size: 7,
459
+ )
460
+ end
461
+
462
+ (options[:step_length]..options[:height])
463
+ .step(options[:step_length]) do |point|
464
+ fill_circle([options[:at][0], options[:at][1] + point], 1)
465
+ draw_text(
466
+ point,
467
+ at: [options[:at][0] - 17, options[:at][1] + point - 2],
468
+ size: 7,
469
+ )
470
+ end
471
+ end
472
+ end
473
+
474
+ # Closes and fills the current path. See {Graphics::Color} for color details.
475
+ #
476
+ # If the option `fill_rule: :even_odd` is specified, Prawn will use the
477
+ # even-odd rule to fill the path. Otherwise, the nonzero winding number rule
478
+ # will be used. See the PDF reference, "Graphics -> Path Construction and
479
+ # Painting -> Clipping Path Operators" for details on the difference.
480
+ #
481
+ # @param options [Hash]
482
+ # @option options :fill_rule [Symbol]
483
+ # @yield
484
+ # @return [void]
485
+ def fill(options = {})
486
+ yield if block_given?
487
+ renderer.add_content(options[:fill_rule] == :even_odd ? 'f*' : 'f')
488
+ end
489
+
490
+ # Closes, fills, and strokes the current path. If a block is provided,
491
+ # yields to the block before closing the path. See {Graphics::Color} for
492
+ # color details.
493
+ #
494
+ # If the option `fill_rule: :even_odd` is specified, Prawn will use the
495
+ # even-odd rule to fill the path. Otherwise, the nonzero winding number rule
496
+ # will be used. See the PDF reference, "Graphics -> Path Construction and
497
+ # Painting -> Clipping Path Operators" for details on the difference.
498
+ #
499
+ # @param options [Hash]
500
+ # @option options :fill_rule [Symbol]
501
+ # @yield
502
+ # @return [void]
503
+ def fill_and_stroke(options = {})
504
+ yield if block_given?
505
+ renderer.add_content(options[:fill_rule] == :even_odd ? 'b*' : 'b')
506
+ end
507
+
508
+ # Closes the current path.
509
+ #
510
+ def close_path
511
+ renderer.add_content('h')
512
+ end
513
+
514
+ # @!method fill_rectangle(point, width, height)
515
+ # Draws and fills a rectangle given `point`, `width`, and `height`. The
516
+ # rectangle is bounded by its upper-left corner.
517
+ #
518
+ # @param point [Array(Number, Number)]
519
+ # @param width [Number]
520
+ # @param height [Number]
521
+ # @return [void]
522
+
523
+ # @!method stroke_rectangle(point, width, height)
524
+ # Draws and strokes a rectangle given `point`, `width`, and `height`. The
525
+ # rectangle is bounded by its upper-left corner.
526
+ #
527
+ # @param point [Array(Number, Number)]
528
+ # @param width [Number]
529
+ # @param height [Number]
530
+ # @return [void]
531
+
532
+ # @!method fill_and_stroke_rectangle(point, width, height)
533
+ # Draws, fills, and strokes a rectangle given `point`, `width`, and
534
+ # `height`. The rectangle is bounded by its upper-left corner.
535
+ #
536
+ # @param point [Array(Number, Number)]
537
+ # @param width [Number]
538
+ # @param height [Number]
539
+ # @return [void]
540
+
541
+ # @!method fill_rounded_rectangle(point, width, height, radius)
542
+ #
543
+ # Draws and fills a rounded rectangle given `point`, `width` and `height`,
544
+ # and `radius` for the rounded corner. The rectangle is bounded by its
545
+ # upper-left corner.
546
+ #
547
+ # @param point [Array(Number, Number)]
548
+ # @param width [Number]
549
+ # @param height [Number]
550
+ # @param radius [Number]
551
+ # @return [void]
552
+
553
+ # @!method stroke_rounded_rectangle(point, width, height, radius)
554
+ # Draws and strokes a rounded rectangle given `point`, `width` and
555
+ # `height`, and `radius` for the rounded corner. The rectangle is bounded
556
+ # by its upper-left corner.
557
+ #
558
+ # @param point [Array(Number, Number)]
559
+ # @param width [Number]
560
+ # @param height [Number]
561
+ # @param radius [Number]
562
+ # @return [void]
563
+
564
+ # @!method fill_and_stroke_rounded_rectangle(point, width, height, radius)
565
+ #
566
+ # Draws, fills, and strokes a rounded rectangle given `point`, `width`,
567
+ # and `height` and `radius` for the rounded corner. The rectangle is
568
+ # bounded by its upper-left corner.
569
+ #
570
+ # @param point [Array(Number, Number)]
571
+ # @param width [Number]
572
+ # @param height [Number]
573
+ # @param radius [Number]
574
+ # @return [void]
575
+
576
+ # @!method stroke_line(*points)
577
+ #
578
+ # Strokes a line from one point to another. Points may be specified as
579
+ # tuples or flattened argument list.
580
+ #
581
+ # @overload line(point1, point2)
582
+ # @param point1 [Array(Number, Number)]
583
+ # @param point2 [Array(Number, Number)]
584
+ # @return [void]
585
+ # @overload line(x1, y1, x2, y2)
586
+ # @param x1 [Number]
587
+ # @param y1 [Number]
588
+ # @param x2 [Number]
589
+ # @param y2 [Number]
590
+ # @return [void]
591
+
592
+ # @!method stroke_horizontal_line(x1, x2, options = {})
593
+ #
594
+ # Strokes a horizontal line from `x1` to `x2` at the current y position,
595
+ # or the position specified by the :at option.
596
+ #
597
+ # @param x1 [Number]
598
+ # @param x2 [Number]
599
+ # @param options [Hash]
600
+ # @option options :at [Number]
601
+ # @return [void]
602
+
603
+ # @!method stroke_horizontal_rule
604
+ #
605
+ # Strokes a horizontal line from the left border to the right border of
606
+ # the bounding box at the current y position.
607
+ #
608
+ # @return [void]
609
+
610
+ # @!method stroke_vertical_line(y1, y2, params)
611
+ #
612
+ # Strokes a vertical line at the x coordinate given by `:at` from `y1` to
613
+ # `y2`.
614
+ #
615
+ # @param y1 [Number]
616
+ # @param y2 [Number]
617
+ # @param params [Hash]
618
+ # @option params :at [Number]
619
+ # @return [void]
620
+
621
+ # @!method stroke_curve(origin, dest, options = {})
622
+ #
623
+ # Strokes a Bezier curve between two points, bounded by two additional
624
+ # points.
625
+ #
626
+ # @param origin [Array(Number, Number)]
627
+ # @param dest [Array(Number, Number)]
628
+ # @param options [Hash]
629
+ # @option options :bounds [Array(Array(Number, Number), Array(Number, Number))]
630
+ # @return [void]
631
+
632
+ # @!method: stroke_circle(center, radius)
633
+ #
634
+ # Draws and strokes a circle of radius `radius` with the centre-point at
635
+ # `point`.
636
+ #
637
+ # @param center [Array(Number, Number)]
638
+ # @param radius [Number]
639
+ # @return [void]
640
+
641
+ # @!method fill_circle(center, radius)
642
+ #
643
+ # Draws and fills a circle of radius `radius` with the centre-point at
644
+ # `point`.
645
+ #
646
+ # @param center [Array(Number, Number)]
647
+ # @param radius [Number]
648
+ # @return [void]
649
+
650
+ # @!method fill_and_stroke_circle(center, radius)
651
+ #
652
+ # Draws, strokes, and fills a circle of radius `radius` with the
653
+ # centre-point at `point`.
654
+ #
655
+ # @param center [Array(Number, Number)]
656
+ # @param radius [Number]
657
+ # @return [void]
658
+
659
+ # @!method stroke_ellipse(point, radius1, radius2 = radius1)
660
+ #
661
+ # Draws and strokes an ellipse of x radius `r1` and y radius `r2` with the
662
+ # centre-point at `point`.
663
+ #
664
+ # @param point [Array(Number, Number)]
665
+ # @param radius1 [Number]
666
+ # @param radius2 [Number]
667
+ # @return [void]
668
+
669
+ # @!method fill_ellipse(point, radius1, radius2 = radius1)
670
+ #
671
+ # Draws and fills an ellipse of x radius `r1` and y radius `r2` with the
672
+ # centre-point at `point`.
673
+ #
674
+ # @param point [Array(Number, Number)]
675
+ # @param radius1 [Number]
676
+ # @param radius2 [Number]
677
+ # @return [void]
678
+
679
+ # @!method fill_and_stroke_ellipse(point, radius1, radius2 = radius1)
680
+ #
681
+ # Draws, strokes, and fills an ellipse of x radius `r1` and y radius `r2`
682
+ # with the centre-point at `point`.
683
+ #
684
+ # @param point [Array(Number, Number)]
685
+ # @param radius1 [Number]
686
+ # @param radius2 [Number]
687
+ # @return [void]
688
+
689
+ # @!method stroke_polygon(*points)
690
+ #
691
+ # Draws and strokes a polygon from the specified points.
692
+ #
693
+ # @param points [Array<Array(Number, Number)>]
694
+ # @return [void]
695
+
696
+ # @!method fill_polygon(*points)
697
+ #
698
+ # Draws and fills a polygon from the specified points.
699
+ #
700
+ # @param points [Array<Array(Number, Number)>]
701
+ # @return [void]
702
+
703
+ # @!method fill_and_stroke_polygon(*points)
704
+ #
705
+ # Draws, strokes, and fills a polygon from the specified points.
706
+ #
707
+ # @param points [Array<Array(Number, Number)>]
708
+ # @return [void]
709
+
710
+ # @!method stroke_rounded_polygon(radius, *points)
711
+ #
712
+ # Draws and strokes a rounded polygon from specified points, using
713
+ # `radius` to define Bezier curves.
714
+ #
715
+ # @param radius [Number]
716
+ # @param points [Array<Array(Number, Number)>]
717
+ # @return [void]
718
+
719
+ # @!method fill_rounded_polygon(radius, *points)
720
+ #
721
+ # Draws and fills a rounded polygon from specified points, using `radius`
722
+ # to define Bezier curves.
723
+ #
724
+ # @param radius [Number]
725
+ # @param points [Array<Array(Number, Number)>]
726
+ # @return [void]
727
+
728
+ # @!method fill_and_stroke_rounded_polygon(radius, *points)
729
+ #
730
+ # Draws, strokes, and fills a rounded polygon from specified points, using
731
+ # `radius` to define Bezier curves.
732
+ #
733
+ # @param radius [Number]
734
+ # @param points [Array<Array(Number, Number)>]
735
+ # @return [void]
736
+
737
+ ops = %w[fill stroke fill_and_stroke]
738
+ shapes = %w[
739
+ line_to curve_to rectangle rounded_rectangle line horizontal_line
740
+ horizontal_rule vertical_line curve circle_at circle ellipse_at ellipse
741
+ polygon rounded_polygon rounded_vertex
742
+ ]
743
+
744
+ ops.product(shapes).each do |operation, shape|
745
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
746
+ def #{operation}_#{shape}(*args) # def fill_polygon(*args)
747
+ #{shape}(*args) # polygon(*args)
748
+ #{operation} # fill
749
+ end # end
750
+ METHOD
751
+ end
752
+
753
+ private
754
+
755
+ def current_line_width
756
+ graphic_state.line_width
757
+ end
758
+
759
+ def current_line_width=(width)
760
+ graphic_state.line_width = width
761
+ end
762
+
763
+ def write_line_width
764
+ renderer.add_content("#{current_line_width} w")
765
+ end
766
+
767
+ def map_to_absolute(*point)
768
+ x, y = point.flatten
769
+ [@bounding_box.absolute_left + x, @bounding_box.absolute_bottom + y]
770
+ end
771
+
772
+ def map_to_absolute!(point)
773
+ point.replace(map_to_absolute(point))
774
+ end
775
+
776
+ def degree_to_rad(angle)
777
+ angle * Math::PI / 180
778
+ end
779
+
780
+ # Returns the coordinates for a point on a line that is a given distance
781
+ # away from the second point defining the line segement
782
+ def point_on_line(distance_from_end, *points)
783
+ x0, y0, x1, y1 = points.flatten
784
+ length = Math.sqrt(((x1 - x0)**2) + ((y1 - y0)**2))
785
+ p = (length - distance_from_end) / length
786
+ xr = x0 + (p * (x1 - x0))
787
+ yr = y0 + (p * (y1 - y0))
788
+ [xr, yr]
789
+ end
790
+ end
791
+ end