svgplot 0.0.1 → 0.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f323e9da91bcaf8ebcd7cd305a32004217aac217
4
- data.tar.gz: 3f9798e086362b17e653b3d4c334b82a0691b562
3
+ metadata.gz: e18768c73ada9428946371059e71d7d74b3748bd
4
+ data.tar.gz: d035ac8e2786d63be01c412004e72c280ea51d14
5
5
  SHA512:
6
- metadata.gz: 778f70e09d43817954b4073dacd64bc94655347f1ee01c91529c8a45ec23a0050c166da9f53554f1ad3d1218a547424307d15a9dab3207fe4863cacedd50cb2c
7
- data.tar.gz: b6cbe8c7f435de1594308ce2b3fa5e8b0596e49450311ede165c50ab386123b5c7f28b268e4c24684d97b233f4925c83409eb67537e0b46a07284ae7341977d2
6
+ metadata.gz: 871812ba7324ffcd641f1ff6acfe90c876c63ee12b5c33f19b499ad3cd5334897acbdc4459258ad3f9f63dc6db51a04c4901fe4eaa565c4eb12283d5799b84f9
7
+ data.tar.gz: a993173c4902c88ac7a0b821a72c68198b7857b5bf34b209875bd43b5263a643d694337483f806d22a235081f6c4ee6b38a5bef3f43a2cf650b4d7b0de8416cf
@@ -1,6 +1,8 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  rvm:
4
+ - 2.1.2
5
+ - 2.1.1
4
6
  - 2.1.0
5
7
  - 2.0.0
6
8
  - 1.9.3
data/Rakefile CHANGED
@@ -6,8 +6,8 @@ desc 'Run tests'
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
8
  desc 'Run Rubocop on the gem'
9
- Rubocop::RakeTask.new(:rubocop) do |task|
10
- task.patterns = ['lib/**/*.rb', 'spec/**/*.rb', 'dev/**/*.rb']
9
+ RuboCop::RakeTask.new(:rubocop) do |task|
10
+ task.patterns = ['lib/**/*.rb', 'spec/**/*.rb', 'dev/**/*.rb', 'bin/*']
11
11
  task.fail_on_error = true
12
12
  end
13
13
 
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'svgplot'
4
+
5
+ exit SVGPlot::Application.run!(*ARGV)
@@ -35,7 +35,7 @@ Nokogiri::HTML(open(version_url + 'eltindex.html')).css('li').each do |li|
35
35
  end
36
36
  puts
37
37
 
38
- xmlns = %w(svg cc dc rdf inkscape xlink].map! { |e| ('xmlns:' + e).to_sym )
38
+ xmlns = %w(svg cc dc rdf inkscape xlink).map! { |e| ('xmlns:' + e).to_sym }
39
39
  structure[:svg][:attributes].push(:xmlns, *xmlns)
40
40
 
41
41
  skipped_cops = %w(SpaceAroundOperators SpaceInsideHashLiteralBraces HashSyntax)
@@ -2,19 +2,16 @@
2
2
  # SVG generation module
3
3
  module SVGPlot
4
4
  class << self
5
- ##
6
- # Add .new() helper for creating a new Plot object
5
+ ##
6
+ # Add .new() helper for creating a new Plot object
7
7
 
8
- def new(*args)
9
- self::Plot.new(*args)
8
+ def new(*args, &block)
9
+ self::Plot.new(*args, &block)
10
10
  end
11
11
  end
12
-
13
- ##
14
- # Plot object (represents an SVG image)
15
- class Plot
16
- end
17
12
  end
18
13
 
19
14
  require 'svgplot/spec'
15
+ require 'svgplot/application'
20
16
  require 'svgplot/meta'
17
+ require 'svgplot/plot'
@@ -0,0 +1,32 @@
1
+ module SVGPlot
2
+ ##
3
+ # Application object for running .svgplot files
4
+ class Application
5
+ def initialize(*args)
6
+ @files = args.empty? ? Dir.glob(File.expand_path('*.svgplot')) : args
7
+ fail('No input files') if @files.empty?
8
+ end
9
+
10
+ def run!
11
+ @files.each do |file|
12
+ output = file.sub(/\.svgplot/, '') + '.svg'
13
+ File.open(output, 'w') do |fh|
14
+ build file, fh
15
+ end
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def build(file, fh)
22
+ SVGPlot::Plot.new({ width: '100%', height: '100%' }, fh) do
23
+ begin
24
+ instance_eval File.read(file), file
25
+ rescue StandardError => e
26
+ backtrace = e.backtrace.grep(Regexp.new(File.expand_path(file)))
27
+ raise e.class, e.message, backtrace
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -41,16 +41,6 @@ SVGPlot::SVG_EXPANSION = {
41
41
  end
42
42
  }
43
43
 
44
- SVGPlot::SVG_DEFAULTS = {
45
- text: { fill: 'black' },
46
- line: { stroke: 'black' },
47
- rect: { stroke: 'black' },
48
- circle: { stroke: 'black' },
49
- ellipse: { stroke: 'black' },
50
- polygon: { stroke: 'black' },
51
- polyline: { stroke: 'black' }
52
- }
53
-
54
44
  # TODO: move to documentation?
55
45
  SVGPlot::SVG_TRANSFORM = [
56
46
  :matrix, # expects an array of 6 elements
@@ -67,5 +57,9 @@ SVGPlot::CSS_STYLE = [
67
57
  :stroke,
68
58
  :fill_opacity,
69
59
  :stroke_opacity,
70
- :opacity
60
+ :opacity,
61
+ :'text-align',
62
+ :font,
63
+ :'white-space',
64
+ :display
71
65
  ]
@@ -0,0 +1,636 @@
1
+ # rubocop:disable all
2
+ module SVGPlot
3
+ class SVGTag
4
+ attr_reader :tag, :attributes, :children
5
+
6
+ def initialize(tag, attributes={}, &block)
7
+ @tag = validate_tag(tag)
8
+ @attributes = validate_attributes(attributes)
9
+ @children = []
10
+
11
+ if block
12
+ instance_exec &block
13
+ end
14
+ end
15
+
16
+ ##
17
+ # Provide methods for SVG transformations
18
+ ##
19
+
20
+ def translate(tx, ty = 0)
21
+ add_transform(:translate, "#{tx}, #{ty}")
22
+ self
23
+ end
24
+
25
+ def scale(sx, sy = 1)
26
+ add_transform(:scale, "#{sx}, #{sy}")
27
+ self
28
+ end
29
+
30
+ def rotate(angle, cx = nil, cy = nil)
31
+ add_transform(:rotate, "#{angle}#{(cx.nil? or cy.nil?) ? "" : ", #{cx}, #{cy}"}")
32
+ self
33
+ end
34
+
35
+ def skewX(angle)
36
+ add_transform(:skewX, "#{angle}")
37
+ self
38
+ end
39
+
40
+ def skewY(angle)
41
+ add_transform(:skewY, "#{angle}")
42
+ self
43
+ end
44
+
45
+ def matrix(a, b, c, d, e, f)
46
+ add_transform(:matrix, "#{a}, #{b}, #{c}, #{d}, #{e}, #{f}")
47
+ self
48
+ end
49
+
50
+ def validate_tag(tag)
51
+ raise "#{tag} is not a valid tag" unless SVGPlot::SVG_ELEMENTS.include?(tag.to_sym)
52
+ tag.to_sym
53
+ end
54
+
55
+ def validate_attributes(attributes)
56
+ clean_attributes = {}
57
+ transforms = {}
58
+ styles = {}
59
+
60
+ attributes.each do |attribute, value|
61
+ if SVGPlot::SVG_TRANSFORM.include? attribute
62
+ transforms[attribute] = value
63
+ elsif SVGPlot::CSS_STYLE.include? attribute
64
+ styles[attribute] = value
65
+ else
66
+ clean_attributes[validate_attribute(attribute)] = value
67
+ end
68
+ end
69
+
70
+ #always prefer more verbose definition.
71
+ unless transforms.empty?
72
+ transforms.merge!(clean_attributes[:transform]) if clean_attributes[:transform]
73
+ str = ""
74
+ write_transforms(transforms, str)
75
+ clean_attributes[validate_attribute(:transform)] = str
76
+ end
77
+
78
+ unless styles.empty?
79
+ styles.merge!(clean_attributes[:style]) if clean_attributes[:style]
80
+ clean_attributes[validate_attribute(:style)] = styles
81
+ end
82
+ clean_attributes
83
+ end
84
+
85
+ def validate_attribute(attribute)
86
+ raise "#{@tag} does not support attribute #{attribute}" unless SVGPlot::SVG_STRUCTURE[@tag.to_sym][:attributes].include?(attribute.to_sym)
87
+ attribute.to_sym
88
+ end
89
+
90
+ def write_styles(styles, output)
91
+ styles.each do |attribute, value|
92
+ attribute = attribute.to_s
93
+ attribute.gsub!('_','-')
94
+ output << "#{attribute}:#{value};"
95
+ end
96
+ end
97
+
98
+ def write_transforms(transforms, output)
99
+ transforms.each do |attribute, value|
100
+ value = [value] unless value.is_a?(Array)
101
+ output << "#{attribute.to_s}(#{value.join(',')}) "
102
+ end
103
+ end
104
+
105
+ def write_points(points, output)
106
+ points.each_with_index do |value, index|
107
+ output << value.to_s
108
+ output << ',' if index.even?
109
+ output << ' ' if (index.odd? and (index != points.size-1))
110
+ end
111
+ end
112
+
113
+ #special case for raw blocks.
114
+ def raw(data)
115
+ append_child SVGPlot::SVGRaw.new(@img, data)
116
+ end
117
+
118
+ #special case for path block
119
+ def path(attributes = {}, &block)
120
+ append_child SVGPlot::SVGPath.new(@img, attributes, &block)
121
+ end
122
+
123
+ #special case for use block
124
+ def use(id, attributes = {})
125
+ id = id.attributes[:id] if id.is_a? SVGPlot::SVGTag
126
+ append_child SVGPlot::SVGTagWithParent.new(@img, "use", attributes.merge("xlink:href" => "##{id}"))
127
+ end
128
+
129
+
130
+ #special case for linearGradient
131
+ def linearGradient(id, attributes={}, if_exists = :skip, &block)
132
+ raise "image reference isn't set, cannot use 'defs' (and thus linearGradient) !" if @img.nil?
133
+ @img.add_def(id, SVGPlot::SVGLinearGradient.new(@img, attributes), if_exists, &block)
134
+ end
135
+
136
+
137
+ #special case for radialGradient
138
+ def radialGradient(id, attributes={}, if_exists = :skip, &block)
139
+ raise "image reference isn't set, cannot use 'defs' (and thus radialGradient) !" if @img.nil?
140
+ @img.add_def(id, SVGPlot::SVGRadialGradient.new(@img, attributes), if_exists, &block)
141
+ end
142
+
143
+
144
+
145
+
146
+ def spawn_child(tag, *args, &block)
147
+ #expected args: nil, [hash], [...]
148
+ parameters = {} if args.size == 0
149
+
150
+ unless parameters #are empty
151
+ parameters = args[0] if args[0].is_a? Hash
152
+ end
153
+
154
+ unless parameters #are set
155
+ #try to find args expansion rule
156
+ expansion = SVGPlot::SVG_EXPANSION[tag.to_sym]
157
+ raise "Unnamed parameters for #{tag} are not allowed!" unless expansion
158
+
159
+ if expansion.is_a? Array
160
+ raise "Bad unnamed parameter count for #{tag}, expecting #{expansion.size} got #{if args.last.is_a? Hash then args.size-1 else args.size end}" unless (args.size == expansion.size and not args.last.is_a? Hash) or (args.size - 1 == expansion.size and args.last.is_a? Hash)
161
+ parameters = Hash[expansion.zip(args)]
162
+ if args.last.is_a? Hash
163
+ parameters.merge! args.last
164
+ end
165
+ elsif expansion.is_a? Proc
166
+ hash = args.pop if args.last.is_a? Hash
167
+ parameters = expansion.call(args)
168
+ parameters.merge! hash if hash
169
+ else
170
+ raise "Unexpected expansion mechanism: #{expansion.class}"
171
+ end
172
+ end
173
+
174
+ # add default parameters if they are not overwritten
175
+ merge_defaults().each do |key, value|
176
+ parameters[key] = value unless parameters[key]
177
+ end if @defaults
178
+
179
+ append_child(SVGPlot::SVGTagWithParent.new(@img, tag, parameters, &block))
180
+ end
181
+
182
+
183
+ def append_child(child)
184
+ @children.push(child)
185
+ child.push_defaults(merge_defaults()) if @defaults
186
+ child
187
+ end
188
+
189
+
190
+ def merge_defaults()
191
+ result = {}
192
+ return result if @defaults.empty?
193
+ @defaults.each { |d| result.merge!(d) }
194
+ result
195
+ end
196
+
197
+
198
+ def push_defaults(defaults)
199
+ @defaults = [] unless @defaults
200
+ @defaults.push(defaults)
201
+ end
202
+
203
+
204
+ def pop_defaults()
205
+ @defaults.pop()
206
+ end
207
+
208
+
209
+ def with_style(style={}, &proc)
210
+ push_defaults(style)
211
+ # Call the block
212
+ self.instance_exec(&proc)
213
+ # Pop style again to revert changes
214
+ pop_defaults()
215
+ end
216
+
217
+
218
+ def validate_child_name(name)
219
+ #aliases the name (like, group instead of g)
220
+ name = SVGPlot::SVG_ALIAS[name.to_sym] if SVGPlot::SVG_ALIAS[name.to_sym]
221
+
222
+ #raises only if given name is an actual svg tag. In other case -- assumes user just mistyped.
223
+ if SVGPlot::SVG_STRUCTURE[@tag.to_sym][:elements].include?(name.to_sym)
224
+ name.to_sym
225
+ elsif SVGPlot::SVG_ELEMENTS.include?(name.to_sym)
226
+ raise "#{@tag} should not contain child #{name}"
227
+ end
228
+ end
229
+
230
+
231
+ def method_missing(meth, *args, &block)
232
+ #if method is a setter or a getter, check valid attributes:
233
+ check = /^(?<name>.*)(?<op>=|\?)$/.match(meth)
234
+ if check
235
+ raise "Passing a code block to setter or getter is not permited!" if block
236
+ name = validate_attribute(check[:name].to_sym)
237
+ if check[:op] == '?'
238
+ @attributes[name]
239
+ elsif check[:op] == '='
240
+ raise "Setting an attribute with multiple values is not permited!" if args.size > 1
241
+ @attributes[name] = args[0]
242
+ end
243
+ elsif child = validate_child_name(meth)
244
+ spawn_child(child, *args, &block)
245
+ else
246
+ super
247
+ end
248
+ end
249
+
250
+
251
+ def write(output)
252
+ raise "Can not write to given output!" unless output.respond_to?(:<<)
253
+ output << "<#{@tag.to_s}"
254
+ @attributes.each do
255
+ |attribute, value|
256
+ output << " #{attribute.to_s}=\""
257
+ if attribute == :style
258
+ write_styles(value, output)
259
+ elsif attribute == :points
260
+ write_points(value, output)
261
+ else
262
+ output << "#{value.to_s}"
263
+ end
264
+ output << "\""
265
+ end
266
+
267
+ if @children.empty?
268
+ output << "/>"
269
+ else
270
+ output << ">"
271
+ @children.each { |c| c.write(output) }
272
+ output << "</#{@tag.to_s}>"
273
+ end
274
+ end
275
+
276
+ def to_s
277
+ str = ""
278
+ write(str)
279
+ return str
280
+ end
281
+
282
+
283
+ private
284
+
285
+ def add_transform(type, params)
286
+ attr_name = validate_attribute(:transform)
287
+ @attributes[attr_name] = "" if @attributes[attr_name].nil?
288
+ @attributes[attr_name] = @attributes[attr_name] + "#{type}(#{params})"
289
+ end
290
+
291
+ end
292
+ end
293
+
294
+
295
+ #Extension of SVGTag to provide a reference to the parent img (used for defs)
296
+ module SVGPlot
297
+ class SVGTagWithParent < SVGPlot::SVGTag
298
+ attr_reader :img
299
+
300
+ def initialize(img, tag, params = {}, output=nil, &block)
301
+ @img = img
302
+ super(tag, params, &block)
303
+ end
304
+ end
305
+ end
306
+
307
+
308
+
309
+ #inherit from tag for basic functionality, control raw data using the write method
310
+ module SVGPlot
311
+ class SVGRaw < SVGPlot::SVGTagWithParent
312
+
313
+ def initialize(img, data)
314
+ @img = img
315
+ @data = data
316
+ end
317
+
318
+ def write(output)
319
+ output << @data.to_s
320
+ end
321
+ end
322
+ end
323
+
324
+
325
+
326
+ module SVGPlot
327
+ class Plot < SVGPlot::SVGTagWithParent
328
+ def initialize(params = {}, output=nil, &block)
329
+ @defs = nil
330
+ @defs_ids = {}
331
+
332
+ params[:"version"] = "1.1" unless params[:"version"]
333
+ params[:"xmlns"] = "http://www.w3.org/2000/svg" unless params[:"xmlns"]
334
+ params[:"xmlns:xlink"] = "http://www.w3.org/1999/xlink" unless params[:"xmlns:xlink"]
335
+ super(self, "svg", params, &block)
336
+
337
+ @output = (output or "")
338
+ validate_output(@output) if output
339
+
340
+ if block
341
+ write(@output)
342
+ end
343
+ end
344
+
345
+ def add_def(id, child, if_exists = :skip, &block)
346
+ #init on the fly if needed
347
+ @defs = SVGPlot::SVGTagWithParent.new(@img, "defs") if @defs.nil?
348
+
349
+ #raise an error if id is already present and if_exists is :fail
350
+ raise "Definition '#{id}' already exists" if @defs_ids.has_key? id and if_exists == :fail
351
+
352
+ #return the existing element if id is already present and if_exists is :skip
353
+ return @defs_ids[id] if if_exists == :skip and @defs_ids.has_key? id
354
+
355
+ #search for the existing element
356
+ if @defs_ids[id]
357
+ old_idx = nil
358
+ @defs.children.each_with_index { |c,i| if c.attributes[:id] == id then old_idx = i ; break end }
359
+ end
360
+
361
+ #force the id, append the child to definitions and call the given block to fill the group
362
+ child.attributes[:id] = id
363
+ @defs.append_child child
364
+ @defs_ids[id] = child
365
+ child.instance_exec block
366
+
367
+ #remove the old element if present
368
+ @defs.children.delete_at old_idx if old_idx
369
+
370
+ return child
371
+ end
372
+
373
+ def def_group(id, if_exists = :skip, &block)
374
+ g = SVGPlot::SVGTagWithParent.new(@img, "g", :id => id)
375
+ return add_def(id, g, if_exists, &block)
376
+ end
377
+
378
+ #def text(x, y, text, style=DefaultStyles[:text])
379
+ # @output << %Q{<text x="#{x}" y="#{y}"}
380
+ # style = fix_style(default_style.merge(style))
381
+ # @output << %Q{ font-family="#{style.delete "font-family"}"} if style["font-family"]
382
+ # @output << %Q{ font-size="#{style.delete "font-size"}"} if style["font-size"]
383
+ # write_style style
384
+ # @output << ">"
385
+ # dy = 0 # First line should not be shifted
386
+ # text.each_line do |line|
387
+ # @output << %Q{<tspan x="#{x}" dy="#{dy}em">}
388
+ # dy = 1 # Next lines should be shifted
389
+ # @output << line.rstrip
390
+ # @output << "</tspan>"
391
+ # end
392
+ # @output << "</text>"
393
+ #end
394
+
395
+
396
+ def write(output)
397
+ validate_output(output)
398
+ write_header(output)
399
+
400
+ @children.unshift @defs if @defs
401
+ super(output)
402
+ @children.shift if @defs
403
+ end
404
+
405
+
406
+ # how to define output << image ?
407
+ #def <<(output)
408
+ # write(output)
409
+ #end
410
+
411
+ private
412
+
413
+ def validate_output(output)
414
+ raise "Illegal output object: #{output.inspect}" unless output.respond_to?(:<<)
415
+ end
416
+
417
+ # Writes file header
418
+ def write_header(output)
419
+ output << <<-HEADER
420
+ <?xml version="1.0" standalone="no"?>
421
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
422
+ HEADER
423
+ end
424
+ end
425
+ end
426
+
427
+ #SVG Path element, with ruby methods to describe the path
428
+ class SVGPlot::SVGPath < SVGPlot::SVGTagWithParent
429
+ def initialize(img = nil, attributes={}, &block)
430
+ attributes.merge!(:d => "") unless attributes.has_key? :d
431
+ super(img, "path", attributes)
432
+ end
433
+
434
+ ##
435
+ # moveTo commands
436
+ #
437
+ # Moves pen to specified point x,y without drawing.
438
+ #
439
+ ##
440
+ def moveTo(x, y)
441
+ add_d("m#{x},#{y}")
442
+ end
443
+
444
+
445
+ def moveToA(x, y)
446
+ add_d("M#{x},#{y}")
447
+ end
448
+
449
+
450
+ ##
451
+ # lineTo commands
452
+ #
453
+ # Draws a line from current pen location to specified point x,y.
454
+ #
455
+ ##
456
+ def lineTo(x, y)
457
+ add_d("l#{x},#{y}")
458
+ end
459
+
460
+
461
+ def lineToA(x, y)
462
+ add_d("L#{x},#{y}")
463
+ end
464
+
465
+
466
+ ##
467
+ # horizontal lineTo commands
468
+ #
469
+ # Draws a horizontal line to the point defined by x.
470
+ #
471
+ ##
472
+ def hlineTo(x)
473
+ add_d("h#{x}")
474
+ end
475
+
476
+
477
+ def hlineToA(x)
478
+ add_d("H#{x}")
479
+ end
480
+
481
+
482
+ ##
483
+ # vertical lineTo commands
484
+ #
485
+ # Draws a vertical line to the point defined by y.
486
+ #
487
+ ##
488
+ def vlineTo(y)
489
+ add_d("v#{y}")
490
+ end
491
+
492
+
493
+ def vlineToA(y)
494
+ add_d("V#{y}")
495
+ end
496
+
497
+
498
+ ##
499
+ # curveTo commands
500
+ #
501
+ # Draws a cubic Bezier curve from current pen point to dx,dy. x1,y1 and x2,y2
502
+ # are start and end control points of the curve, controlling how it bends.
503
+ #
504
+ ##
505
+ def curveTo(dx, dy, x1, y1, x2, y2)
506
+ add_d("c#{x1},#{y1} #{x2},#{y2} #{dx},#{dy}")
507
+ end
508
+
509
+
510
+ def curveToA(dx, dy, x1, y1, x2, y2)
511
+ add_d("C#{x1},#{y1} #{x2},#{y2} #{dx},#{dy}")
512
+ end
513
+
514
+
515
+ ##
516
+ # smooth curveTo commands
517
+ #
518
+ # Draws a cubic Bezier curve from current pen point to dx,dy. x2,y2 is the
519
+ # end control point. The start control point is is assumed to be the same
520
+ # as the end control point of the previous curve.
521
+ #
522
+ ##
523
+ def scurveTo(dx, dy, x2, y2)
524
+ add_d("s#{x2},#{y2} #{dx},#{dy}")
525
+ end
526
+
527
+
528
+ def scurveToA(dx, dy, x2, y2)
529
+ add_d("S#{x2},#{y2} #{dx},#{dy}")
530
+ end
531
+
532
+
533
+ ##
534
+ # quadratic Bezier curveTo commands
535
+ #
536
+ # Draws a quadratic Bezier curve from current pen point to dx,dy. x1,y1 is the
537
+ # control point controlling how the curve bends.
538
+ #
539
+ ##
540
+ def qcurveTo(dx, dy, x1, y1)
541
+ add_d("q#{x1},#{y1} #{dx},#{dy}")
542
+ end
543
+
544
+
545
+ def qcurveToA(dx, dy, x1, y1)
546
+ add_d("Q#{x1},#{y1} #{dx},#{dy}")
547
+ end
548
+
549
+
550
+ ##
551
+ # smooth quadratic Bezier curveTo commands
552
+ #
553
+ # Draws a quadratic Bezier curve from current pen point to dx,dy. The control
554
+ # point is assumed to be the same as the last control point used.
555
+ #
556
+ ##
557
+ def sqcurveTo(dx, dy)
558
+ add_d("t#{dx},#{dy}")
559
+ end
560
+
561
+
562
+ def sqcurveToA(dx, dy)
563
+ add_d("T#{dx},#{dy}")
564
+ end
565
+
566
+
567
+ ##
568
+ # elliptical arc commands
569
+ #
570
+ # Draws an elliptical arc from the current point to the point x,y. rx and ry
571
+ # are the elliptical radius in x and y direction.
572
+ # The x-rotation determines how much the arc is to be rotated around the
573
+ # x-axis. It only seems to have an effect when rx and ry have different values.
574
+ # The large-arc-flag doesn't seem to be used (can be either 0 or 1). Neither
575
+ # value (0 or 1) changes the arc.
576
+ # The sweep-flag determines the direction to draw the arc in.
577
+ #
578
+ ##
579
+ def arcTo(dx, dy, rx, ry, axis_rotation, large_arc_flag, sweep_flag)
580
+ add_d("a#{rx},#{ry} #{axis_rotation} #{large_arc_flag},#{sweep_flag} #{dx},#{dy}")
581
+ end
582
+
583
+
584
+ def arcToA(dx, dy, rx, ry, axis_rotation, large_arc_flag, sweep_flag)
585
+ add_d("A#{rx},#{ry} #{axis_rotation} #{large_arc_flag},#{sweep_flag} #{dx},#{dy}")
586
+ end
587
+
588
+
589
+ ##
590
+ # close path command
591
+ #
592
+ # Closes the path by drawing a line from current point to first point.
593
+ #
594
+ ##
595
+ def close
596
+ add_d("Z")
597
+ end
598
+
599
+
600
+ private
601
+ def add_d(op)
602
+ @attributes[:d] = @attributes[:d] + " " + op
603
+ end
604
+ end
605
+
606
+ #SVG base gradient element, with ruby methods to describe the gradient
607
+ class SVGPlot::SVGGradient < SVGPlot::SVGTagWithParent
608
+
609
+ def fill
610
+ "url(##{@attributes[:id]})"
611
+ end
612
+
613
+
614
+ def stop(offset, color, opacity)
615
+ append_child(SVGPlot::SVGTag.new("stop", "offset" => offset, "stop-color" => color, "stop-opacity" => opacity))
616
+ end
617
+
618
+ end
619
+
620
+ #SVG linear gradient element
621
+ class SVGPlot::SVGLinearGradient < SVGPlot::SVGGradient
622
+
623
+ def initialize(img, attributes={}, &block)
624
+ super(img, "linearGradient", attributes, &block)
625
+ end
626
+
627
+ end
628
+
629
+ #SVG radial gradient element
630
+ class SVGPlot::SVGRadialGradient < SVGPlot::SVGGradient
631
+
632
+ def initialize(img, attributes={}, &block)
633
+ super(img, "radialGradient", attributes, &block)
634
+ end
635
+
636
+ end
@@ -2,6 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe SVGPlot do
4
4
  it 'works' do
5
- expect(true).to be_true
5
+ expect(true).to be true
6
6
  end
7
7
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'svgplot'
3
- s.version = '0.0.1'
3
+ s.version = '0.0.2'
4
4
  s.date = Time.now.strftime("%Y-%m-%d")
5
5
 
6
6
  s.summary = 'SVG Generation Library'
@@ -17,10 +17,12 @@ Gem::Specification.new do |s|
17
17
 
18
18
  s.files = `git ls-files`.split
19
19
  s.test_files = `git ls-files spec/*`.split
20
+ s.executables = ['svgplot']
20
21
 
21
- s.add_development_dependency 'rubocop', '~> 0.19.0'
22
- s.add_development_dependency 'rake', '~> 10.1.1'
23
- s.add_development_dependency 'coveralls', '~> 0.7.0'
24
- s.add_development_dependency 'rspec', '~> 2.14.1'
25
- s.add_development_dependency 'fuubar', '~> 1.3.2'
22
+ s.add_development_dependency 'rubocop', '~> 0.28.0'
23
+ s.add_development_dependency 'rake', '~> 10.4.0'
24
+ s.add_development_dependency 'coveralls', '~> 0.7.1'
25
+ s.add_development_dependency 'rspec', '~> 3.1.0'
26
+ s.add_development_dependency 'fuubar', '~> 2.0.0'
27
+ s.add_development_dependency 'nokogiri', '~> 1.6.5'
26
28
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svgplot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Les Aker
@@ -11,95 +11,113 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2014-03-23 00:00:00.000000000 Z
14
+ date: 2015-01-04 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rubocop
18
18
  requirement: !ruby/object:Gem::Requirement
19
19
  requirements:
20
- - - ~>
20
+ - - "~>"
21
21
  - !ruby/object:Gem::Version
22
- version: 0.19.0
22
+ version: 0.28.0
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ~>
27
+ - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: 0.19.0
29
+ version: 0.28.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  requirements:
34
- - - ~>
34
+ - - "~>"
35
35
  - !ruby/object:Gem::Version
36
- version: 10.1.1
36
+ version: 10.4.0
37
37
  type: :development
38
38
  prerelease: false
39
39
  version_requirements: !ruby/object:Gem::Requirement
40
40
  requirements:
41
- - - ~>
41
+ - - "~>"
42
42
  - !ruby/object:Gem::Version
43
- version: 10.1.1
43
+ version: 10.4.0
44
44
  - !ruby/object:Gem::Dependency
45
45
  name: coveralls
46
46
  requirement: !ruby/object:Gem::Requirement
47
47
  requirements:
48
- - - ~>
48
+ - - "~>"
49
49
  - !ruby/object:Gem::Version
50
- version: 0.7.0
50
+ version: 0.7.1
51
51
  type: :development
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - ~>
55
+ - - "~>"
56
56
  - !ruby/object:Gem::Version
57
- version: 0.7.0
57
+ version: 0.7.1
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rspec
60
60
  requirement: !ruby/object:Gem::Requirement
61
61
  requirements:
62
- - - ~>
62
+ - - "~>"
63
63
  - !ruby/object:Gem::Version
64
- version: 2.14.1
64
+ version: 3.1.0
65
65
  type: :development
66
66
  prerelease: false
67
67
  version_requirements: !ruby/object:Gem::Requirement
68
68
  requirements:
69
- - - ~>
69
+ - - "~>"
70
70
  - !ruby/object:Gem::Version
71
- version: 2.14.1
71
+ version: 3.1.0
72
72
  - !ruby/object:Gem::Dependency
73
73
  name: fuubar
74
74
  requirement: !ruby/object:Gem::Requirement
75
75
  requirements:
76
- - - ~>
76
+ - - "~>"
77
77
  - !ruby/object:Gem::Version
78
- version: 1.3.2
78
+ version: 2.0.0
79
79
  type: :development
80
80
  prerelease: false
81
81
  version_requirements: !ruby/object:Gem::Requirement
82
82
  requirements:
83
- - - ~>
83
+ - - "~>"
84
84
  - !ruby/object:Gem::Version
85
- version: 1.3.2
85
+ version: 2.0.0
86
+ - !ruby/object:Gem::Dependency
87
+ name: nokogiri
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - "~>"
91
+ - !ruby/object:Gem::Version
92
+ version: 1.6.5
93
+ type: :development
94
+ prerelease: false
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - "~>"
98
+ - !ruby/object:Gem::Version
99
+ version: 1.6.5
86
100
  description: Ruby interface for creating SVG images
87
101
  email: EMAIL_ADDRESS
88
- executables: []
102
+ executables:
103
+ - svgplot
89
104
  extensions: []
90
105
  extra_rdoc_files: []
91
106
  files:
92
- - .gitignore
93
- - .rspec
94
- - .rubocop.yml
95
- - .travis.yml
107
+ - ".gitignore"
108
+ - ".rspec"
109
+ - ".rubocop.yml"
110
+ - ".travis.yml"
96
111
  - Gemfile
97
112
  - LICENSE
98
113
  - README.md
99
114
  - Rakefile
115
+ - bin/svgplot
100
116
  - dev/update_spec.rb
101
117
  - lib/svgplot.rb
118
+ - lib/svgplot/application.rb
102
119
  - lib/svgplot/meta.rb
120
+ - lib/svgplot/plot.rb
103
121
  - lib/svgplot/spec.rb
104
122
  - spec/spec_helper.rb
105
123
  - spec/svgplot_spec.rb
@@ -114,17 +132,17 @@ require_paths:
114
132
  - lib
115
133
  required_ruby_version: !ruby/object:Gem::Requirement
116
134
  requirements:
117
- - - '>='
135
+ - - ">="
118
136
  - !ruby/object:Gem::Version
119
137
  version: '0'
120
138
  required_rubygems_version: !ruby/object:Gem::Requirement
121
139
  requirements:
122
- - - '>='
140
+ - - ">="
123
141
  - !ruby/object:Gem::Version
124
142
  version: '0'
125
143
  requirements: []
126
144
  rubyforge_project:
127
- rubygems_version: 2.0.14
145
+ rubygems_version: 2.2.2
128
146
  signing_key:
129
147
  specification_version: 4
130
148
  summary: SVG Generation Library