magic_cloud 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b1860d8f71de2e71e7c779d8f9dcd5326787795a
4
- data.tar.gz: b76001d4c863abc162f8ae8785706d79e5acb753
2
+ SHA256:
3
+ metadata.gz: 3f49646844ea8dff390b90306511424e14e24fb898a1c7ea3a48e1d0f282da62
4
+ data.tar.gz: b1e962c6fd8bb07cf7be250f24b189441976b881fe9393091be172ec8d670678
5
5
  SHA512:
6
- metadata.gz: f7529be89769587062a2cf904e30f7eca6fa702cebf776ab53e58389602395402389f61c358639fde4f15ad89b0317ee78e4e41bef38d8afbacbc18745804803
7
- data.tar.gz: 731dd1fe569a22dbf40aafe3836508bff993b5f6b5ccf39bf342a69d176316780c673a63453897eaba6e2e7b78a4c297bfd1f80eed571b4c3cf1befb4290881b
6
+ metadata.gz: 9e79e0950a3f0a8c72b5ba8d8cdaa22dedc825f50a269a286bd7245635bf749ca090f843e3bf64f3634e16a1fd9164b8651f1e8dc400a874d3d7b28684f56972
7
+ data.tar.gz: 24e3cb62f96a6107cd5ff01c23f963db0427449bc68458d839778a98875bb954e53b81c43917aa83ca1a25bc58b6837f2fe31daf3164bdb6ff248c5218220a3d
data/README.md CHANGED
@@ -12,12 +12,16 @@ Usage
12
12
 
13
13
  ```ruby
14
14
  words = [
15
- [test, 50],
16
- [me, 40],
17
- [tenderly, 30],
15
+ ['test', 50],
16
+ ['me', 40],
17
+ ['tenderly', 30],
18
18
  # ....
19
19
  ]
20
20
  cloud = MagicCloud::Cloud.new(words, rotate: :free, scale: :log)
21
+
22
+ # To save to file, if not redering it for a page
23
+ img = cloud.draw(960, 600) #default height/width
24
+ img.write('test.png')
21
25
  ```
22
26
 
23
27
  Or from command-line:
@@ -61,7 +65,7 @@ References:
61
65
  Performance
62
66
  -----------
63
67
 
64
- It's reasonable for me. On my small Thinkpad E330, some 50-words cloud
68
+ It's reasonable for me. On my small Thinkpad E330, some 50-words cloud
65
69
  image, size 700×500, are typically generated in <3sec. It's not that cool,
66
70
  yet not too long for you to fell asleep.
67
71
 
@@ -74,8 +78,8 @@ out than sparse Tahoma.
74
78
 
75
79
  Major performance eater is perfect collision detection, which Wordle-like
76
80
  cloud needs. MagicCloud for now uses really dumb algorithm with some
77
- not-so-dumb optimizations. You can look into
78
- `lib/magic_cloud/collision_board.rb` - everything can be optimized is
81
+ not-so-dumb optimizations. You can look into
82
+ `lib/magic_cloud/collision_board.rb` - everything can be optimized is
79
83
  there; especially in `CollisionBoard#collides?` method.
80
84
 
81
85
  I assume, for example, that naive rewriting of code in there as a C
@@ -88,18 +92,18 @@ criss-cross intersection check, and memoizing of last crossed sprite).
88
92
  Memory effectiviness
89
93
  --------------------
90
94
 
91
- Basically: it's not.
95
+ Basically: it's not.
92
96
 
93
- Plain Ruby arrays are used to represent collision bitmasks (each array
94
- member stand for 1 bit), so, for example, 700×500 pixel cloud will requre
97
+ Plain Ruby arrays are used to represent collision bitmasks (each array
98
+ member stand for 1 bit), so, for example, 700×500 pixel cloud will requre
95
99
  collision board size `700*500` (i.e. 350k array items only for board, and
96
100
  slightly less for all sprites).
97
101
 
98
102
  It should be wise to use some packing (considering each Ruby Fixmnum can
99
- represent not one, but whole 32 bits). Unfortunately, all bit array
100
- libraries I've tried are causing major slowdown of cloud computation.
101
- With, say, 50 words we'll have literally millions of operation
102
- `bitmask#[]` and `bitmask#[]=`, so, even methods
103
+ represent not one, but whole 32 bits). Unfortunately, all bit array
104
+ libraries I've tried are causing major slowdown of cloud computation.
105
+ With, say, 50 words we'll have literally millions of operation
106
+ `bitmask#[]` and `bitmask#[]=`, so, even methods
103
107
  like `Fixnum#&` and `Fixnum#|` (typically used for bit array representation)
104
108
  are causing significant overload.
105
109
 
@@ -111,10 +115,10 @@ cloud = MagicCloud.new(words, palette: palette, rotate: rotate)
111
115
  ```
112
116
 
113
117
  * `:palette` (default is `:color20`):
114
- * `:category10`, `:category20`, ... - from (d3)[https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors]
118
+ * `:category10`, `:category20`, ... - from [D3.js](https://github.com/d3/d3-scale/blob/master/README.md#category-scales)
115
119
  * `[array, of, colors]` - each color should be hex color, or any other RMagick color string (See "Color names at http://www.imagemagick.org/RMagick/doc/imusage.html)
116
120
  * any lambda, accepting `(word, index)` and returning color string
117
- * any object, responding to `color(word, index)` - so, you can make color
121
+ * any object, responding to `color(word, index)` - so, you can make color
118
122
  depend on tag text, not only on its number in tags list
119
123
  * `:rotate` - rotation algorithm:
120
124
  * `:square` (only horizontal and vertical words) - it's default
@@ -129,7 +133,8 @@ cloud = MagicCloud.new(words, palette: palette, rotate: rotate)
129
133
  * `:linear` - linear scaling (default);
130
134
  * `:log` - logarithmic scaling;
131
135
  * `:sqrt` - square root scaling;
132
- * `:font_family` (Impact is default).
136
+ * `:font_family` (Impact is default, ex. Arial, Helvetica, Futura).
137
+ * `:font` - Full path to custom font file. Overwrite `:font_family`.
133
138
 
134
139
  Current state
135
140
  -------------
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module MagicCloud
3
4
  # Dead simple 2-dimensional "bit matrix", storing 1s and 0s.
4
5
  # Not memory effectife at all, but the fastest pure-Ruby solution
@@ -25,8 +26,8 @@ module MagicCloud
25
26
  end
26
27
 
27
28
  def dump
28
- (0...height).map{|y|
29
- (0...width).map{|x| at(x, y) ? ' ' : 'x'}.join
29
+ (0...height).map { |y|
30
+ (0...width).map { |x| at(x, y) ? ' ' : 'x' }.join
30
31
  }.join("\n")
31
32
  end
32
33
  end
@@ -1,5 +1,6 @@
1
- # encoding: utf-8
2
- require 'RMagick'
1
+ # frozen_string_literal: true
2
+
3
+ require 'rmagick'
3
4
 
4
5
  module MagicCloud
5
6
  # Thin wrapper around RMagick, incapsulating ALL the real drawing.
@@ -9,16 +10,18 @@ module MagicCloud
9
10
  class Canvas
10
11
  def initialize(w, h, back = 'transparent')
11
12
  @width, @height = w, h
12
- @internal = Magick::Image.new(w, h){|i| i.background_color = back}
13
+ @internal = Magick::Image.new(w, h) { |i| i.background_color = back }
13
14
  end
14
15
 
15
16
  attr_reader :internal, :width, :height
16
17
 
17
18
  RADIANS = Math::PI / 180
18
19
 
19
- def draw_text(text, options = {})
20
+ def draw_text(text, options = {}) # rubocop:todo Metrics/AbcSize
21
+ return nil if text.empty?
22
+
20
23
  draw = Magick::Draw.new # FIXME: is it necessary every time?
21
-
24
+
22
25
  x = options.fetch(:x, 0)
23
26
  y = options.fetch(:y, 0)
24
27
  rotate = options.fetch(:rotate, 0)
@@ -47,16 +50,16 @@ module MagicCloud
47
50
  @internal.export_pixels(x, y, w, h, 'RGBA')
48
51
  end
49
52
 
50
- # rubocop:disable TrivialAccessors
51
53
  def render
52
54
  @internal
53
55
  end
54
- # rubocop:enable TrivialAccessors
55
56
 
56
57
  private
57
58
 
58
59
  def set_text_options(draw, options)
59
60
  draw.font_family = options[:font_family]
61
+ draw.font = options[:font] if options[:font]
62
+
60
63
  draw.font_weight = Magick::NormalWeight
61
64
  draw.font_style = Magick::NormalStyle
62
65
 
@@ -67,13 +70,13 @@ module MagicCloud
67
70
  end
68
71
 
69
72
  def _measure_text(draw, text, rotate)
70
- metrics = draw.get_type_metrics('"' + text + 'm"')
73
+ metrics = draw.get_type_metrics(%("#{validate_text(text)}m"))
71
74
  w, h = rotated_metrics(metrics.width, metrics.height, rotate)
72
75
 
73
76
  Rect.new(0, 0, w, h)
74
77
  end
75
78
 
76
- def rotated_metrics(w, h, degrees)
79
+ def rotated_metrics(w, h, degrees) # rubocop:todo Metrics/AbcSize
77
80
  radians = degrees * Math::PI / 180
78
81
 
79
82
  # FIXME: not too clear, just straightforward from d3.cloud
@@ -89,5 +92,11 @@ module MagicCloud
89
92
 
90
93
  [w, h]
91
94
  end
95
+
96
+ def validate_text(text)
97
+ return text +=' ' if text[-1] == '%'
98
+
99
+ text
100
+ end
92
101
  end
93
102
  end
@@ -1,18 +1,19 @@
1
- # encoding: utf-8
2
- require_relative './rect'
3
- require_relative './canvas'
4
- require_relative './palettes'
1
+ # frozen_string_literal: true
5
2
 
6
- require_relative './word'
3
+ require_relative 'rect'
4
+ require_relative 'canvas'
5
+ require_relative 'palettes'
7
6
 
8
- require_relative './layouter'
9
- require_relative './spriter'
7
+ require_relative 'word'
10
8
 
11
- require_relative './debug'
9
+ require_relative 'layouter'
10
+ require_relative 'spriter'
11
+
12
+ require_relative 'debug'
12
13
 
13
14
  module MagicCloud
14
15
  # Main word-cloud class. Takes words with sizes, returns image
15
- class Cloud
16
+ class Cloud # rubocop:todo Metrics/ClassLength
16
17
  def initialize(words, options = {})
17
18
  @words = words.sort_by(&:last).reverse
18
19
  @options = options
@@ -23,15 +24,21 @@ module MagicCloud
23
24
 
24
25
  DEFAULT_FAMILY = 'Impact'
25
26
 
26
- def draw(width, height)
27
+ # rubocop:todo Metrics/MethodLength
28
+ def draw(width, height) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
27
29
  # FIXME: do it in init, for specs would be happy
28
- shapes = @words.each_with_index.map{|(word, size), i|
29
- Word.new(
30
- word,
30
+ shapes = @words.each_with_index.map { |(word, size), i|
31
+ word_options = {
31
32
  font_family: @options[:font_family] || DEFAULT_FAMILY,
32
33
  font_size: scaler.call(word, size, i),
33
34
  color: palette.call(word, i),
34
35
  rotate: rotator.call(word, i)
36
+ }
37
+ word_options[:font] = @options[:font] if @options[:font]
38
+
39
+ Word.new(
40
+ word,
41
+ word_options
35
42
  )
36
43
  }
37
44
 
@@ -44,10 +51,11 @@ module MagicCloud
44
51
  visible = layouter.layout!(shapes)
45
52
 
46
53
  canvas = Canvas.new(width, height, 'white')
47
- visible.each{|sh| sh.draw(canvas)}
54
+ visible.each { |sh| sh.draw(canvas) }
48
55
 
49
56
  canvas.render
50
57
  end
58
+ # rubocop:enable Metrics/MethodLength
51
59
 
52
60
  private
53
61
 
@@ -61,11 +69,11 @@ module MagicCloud
61
69
  when Symbol
62
70
  make_const_palette(source)
63
71
  when Array
64
- ->(_, index){source[index % source.size]}
72
+ ->(_, index) { source[index % source.size] }
65
73
  when Proc
66
74
  source
67
- when ->(s){s.respond_to?(:color)}
68
- ->(word, index){source.color(word, index)}
75
+ when ->(s) { s.respond_to?(:color) }
76
+ ->(word, index) { source.color(word, index) }
69
77
  else
70
78
  fail ArgumentError, "Unknown palette: #{source.inspect}"
71
79
  end
@@ -75,29 +83,29 @@ module MagicCloud
75
83
  palette = PALETTES[sym] or
76
84
  fail(ArgumentError, "Unknown palette: #{sym.inspect}")
77
85
 
78
- ->(_, index){palette[index % palette.size]}
86
+ ->(_, index) { palette[index % palette.size] }
79
87
  end
80
88
 
81
89
  def make_rotator(source)
82
90
  case source
83
91
  when :none
84
- ->(*){0}
92
+ ->(*) { 0 }
85
93
  when :square
86
- ->(*){
94
+ ->(*) {
87
95
  (rand * 2).to_i * 90
88
96
  }
89
97
  when :free
90
- ->(*){
98
+ ->(*) {
91
99
  (((rand * 6) - 3) * 30).round
92
100
  }
93
101
  when Array
94
- ->(*){
102
+ ->(*) {
95
103
  source.sample
96
104
  }
97
105
  when Proc
98
106
  source
99
- when ->(s){s.respond_to?(:rotate)}
100
- ->(word, index){source.rotate(word, index)}
107
+ when ->(s) { s.respond_to?(:rotate) }
108
+ ->(word, index) { source.rotate(word, index) }
101
109
  else
102
110
  fail ArgumentError, "Unknown rotation algo: #{source.inspect}"
103
111
  end
@@ -111,27 +119,31 @@ module MagicCloud
111
119
  norm =
112
120
  case algo
113
121
  when :no
114
- # no normalization, treat tag weights as font size
115
- return ->(_word, size, _index){size}
122
+ return ->(_word, size, _index) { size }
116
123
  when :linear
117
- ->(x){x}
124
+ ->(x) { x }
118
125
  when :log
119
- ->(x){Math.log(x) / Math.log(10)}
126
+ ->(x) { Math.log(x) / Math.log(10) }
120
127
  when :sqrt
121
- ->(x){Math.sqrt(x)}
128
+ ->(x) { Math.sqrt(x) }
122
129
  else
123
130
  fail ArgumentError, "Unknown scaling algo: #{algo.inspect}"
124
131
  end
125
-
132
+
126
133
  smin = norm.call(words.map(&:last).min)
127
134
  smax = norm.call(words.map(&:last).max)
128
- koeff = (FONT_MAX - FONT_MIN).to_f / (smax - smin)
129
-
130
- ->(_word, size, _index){
131
- ssize = norm.call(size)
132
- ((ssize - smin).to_f * koeff + FONT_MIN).to_i
133
- }
135
+
136
+ if smin == smax
137
+ ->(_word, _size, _index) { FONT_MIN } # Return the minimum font size if no scaling is needed
138
+ else
139
+ koeff = (FONT_MAX - FONT_MIN).to_f / (smax - smin)
140
+ ->(_word, size, _index) {
141
+ ssize = norm.call(size)
142
+ ((ssize - smin).to_f * koeff + FONT_MIN).to_i
143
+ }
144
+ end
134
145
  end
146
+
135
147
  # rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity,Metrics/AbcSize
136
148
  end
137
149
  end
@@ -1,5 +1,6 @@
1
- # encoding: utf-8
2
- require_relative './bit_matrix'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'bit_matrix'
3
4
 
4
5
  module MagicCloud
5
6
  # Pixel-by-pixel collision board
@@ -17,7 +18,7 @@ module MagicCloud
17
18
  attr_reader :rects, :intersections_cache
18
19
 
19
20
  def criss_cross_collision?(rect)
20
- if rects.any?{|r| r.criss_cross?(rect)}
21
+ if rects.any? { |r| r.criss_cross?(rect) }
21
22
  Debug.stats[:criss_cross] += 1
22
23
  true
23
24
  else
@@ -25,6 +26,7 @@ module MagicCloud
25
26
  end
26
27
  end
27
28
 
29
+ # rubocop:disable Lint/HashCompareByIdentity -- probably should be followed, but don't have time to test it now
28
30
  def collides_previous?(shape, intersections)
29
31
  prev_idx = intersections_cache[shape.object_id]
30
32
 
@@ -52,6 +54,7 @@ module MagicCloud
52
54
 
53
55
  false
54
56
  end
57
+ # rubocop:enable Lint/HashCompareByIdentity
55
58
 
56
59
  def collides?(shape)
57
60
  Debug.stats[:collide_total] += 1
@@ -64,7 +67,7 @@ module MagicCloud
64
67
  return true if criss_cross_collision?(shape.rect)
65
68
 
66
69
  # then find which of placed sprites rectangles tag intersects
67
- intersections = rects.map{|r| r.intersect(shape.rect)}
70
+ intersections = rects.map { |r| r.intersect(shape.rect) }
68
71
 
69
72
  # no need to further check: this tag is not inside any others' rectangle
70
73
  if intersections.compact.empty?
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  require 'forwardable'
3
4
  require 'logger'
4
5
 
@@ -15,14 +16,14 @@ module MagicCloud
15
16
  end
16
17
 
17
18
  def initialize
18
- @logger = Logger.new(STDOUT).tap{|l| l.level = Logger::FATAL}
19
- @stats = Hash.new{|h, k| h[k] = 0}
19
+ @logger = Logger.new($stdout).tap { |l| l.level = Logger::FATAL }
20
+ @stats = Hash.new { |h, k| h[k] = 0 }
20
21
  end
21
22
 
22
23
  attr_reader :logger, :stats
23
24
 
24
25
  def reset!
25
- @stats = Hash.new{|h, k| h[k] = 0}
26
+ @stats = Hash.new { |h, k| h[k] = 0 }
26
27
  end
27
28
  end
28
29
  end
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module MagicCloud
3
4
  class Layouter
4
5
  class PlaceNotFound < RuntimeError
@@ -9,7 +10,7 @@ module MagicCloud
9
10
  # 2. at each step, shift in spiral from the previous place
10
11
  # 3. always knows, if the place "ready" for shape (empty and inside board)
11
12
  class Place
12
- def initialize(layouter, shape)
13
+ def initialize(layouter, shape) # rubocop:todo Metrics/AbcSize
13
14
  @layouter, @shape = layouter, shape
14
15
 
15
16
  # initial position
@@ -60,10 +61,9 @@ module MagicCloud
60
61
  rectangular_spiral(step)
61
62
  end
62
63
 
63
- # rubocop:disable Metrics/AbcSize
64
64
  def archimedean_spiral(size)
65
65
  e = width / height
66
- ->(t){
66
+ ->(t) {
67
67
  t1 = t * size * 0.01
68
68
 
69
69
  [
@@ -78,7 +78,7 @@ module MagicCloud
78
78
  dx = dy * @layouter.width / @layouter.height
79
79
  x = 0
80
80
  y = 0
81
- ->(t){
81
+ ->(t) {
82
82
  sign = t < 0 ? -1 : 1
83
83
 
84
84
  # zverok: this is original comment & code from d3.layout.cloud.js
@@ -95,7 +95,6 @@ module MagicCloud
95
95
  [x, y].map(&:round)
96
96
  }
97
97
  end
98
- # rubocop:enable Metrics/AbcSize
99
98
  end
100
99
  end
101
100
  end
@@ -1,5 +1,6 @@
1
- # encoding: utf-8
2
- require_relative './collision_board'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'collision_board'
3
4
 
4
5
  module MagicCloud
5
6
  # Main magic of magic cloud - layouting shapes without collisions.
@@ -49,7 +50,7 @@ module MagicCloud
49
50
 
50
51
  board.add(shape)
51
52
  Debug.logger.info 'Place for %p found in %i steps (%.2f sec)' %
52
- [shape, steps, Time.now-start]
53
+ [shape, steps, Time.now-start]
53
54
 
54
55
  break
55
56
  end
@@ -57,11 +58,11 @@ module MagicCloud
57
58
  true
58
59
  rescue PlaceNotFound
59
60
  Debug.logger.warn 'No place for %p found in %i steps (%.2f sec)' %
60
- [shape, steps, Time.now-start]
61
+ [shape, steps, Time.now-start]
61
62
 
62
63
  false
63
64
  end
64
65
  end
65
66
  end
66
67
 
67
- require_relative './layouter/place'
68
+ require_relative 'layouter/place'
@@ -1,9 +1,10 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module MagicCloud
3
4
  PALETTES = {
4
5
  # Categorical colors from d3
5
- # Source: https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors
6
-
6
+ # Source: https://github.com/d3/d3-scale/blob/master/README.md#category-scales
7
+
7
8
  category10: %w[
8
9
  #1f77b4 #ff7f0e #2ca02c #d62728 #9467bd
9
10
  #8c564b #e377c2 #7f7f7f #bcbd22 #17becf
@@ -15,7 +16,7 @@ module MagicCloud
15
16
  #8c564b #c49c94 #e377c2 #f7b6d2 #7f7f7f
16
17
  #c7c7c7 #bcbd22 #dbdb8d #17becf #9edae5
17
18
  ],
18
-
19
+
19
20
  category20b: %w[
20
21
  #393b79 #5254a3 #6b6ecf #9c9ede #637939
21
22
  #8ca252 #b5cf6b #cedb9c #8c6d31 #bd9e39
@@ -29,5 +30,5 @@ module MagicCloud
29
30
  #a1d99b #c7e9c0 #756bb1 #9e9ac8 #bcbddc
30
31
  #dadaeb #636363 #969696 #bdbdbd #d9d9d9
31
32
  ]
32
- }
33
+ }.freeze
33
34
  end
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module MagicCloud
3
4
  # Utility geometrical rectangle, implementing arithmetic interactions
4
5
  # with other rectangles
@@ -9,6 +10,7 @@ module MagicCloud
9
10
  end
10
11
 
11
12
  attr_accessor :x0, :y0, :x1, :y1
13
+
12
14
  # NB: we are trying to use instance variables instead of accessors
13
15
  # inside this class methods, because they are called so many
14
16
  # times that accessor overhead IS significant.
@@ -36,20 +38,18 @@ module MagicCloud
36
38
  @y0 = y
37
39
  end
38
40
 
39
- # rubocop:disable Metrics/AbcSize
40
41
  def adjust!(other)
41
42
  @x0 = other.x0 if other.x0 < @x0
42
43
  @y0 = other.y0 if other.y0 < @y0
43
44
  @x1 = other.x1 if other.x1 > @x1
44
45
  @y1 = other.y1 if other.y1 > @y1
45
46
  end
46
- # rubocop:enable Metrics/AbcSize
47
47
 
48
48
  def adjust(other)
49
- dup.tap{|d| d.adjust!(other)}
49
+ dup.tap { |d| d.adjust!(other) }
50
50
  end
51
51
 
52
- # rubocop:disable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/AbcSize
52
+ # rubocop:disable Metrics/CyclomaticComplexity
53
53
  def criss_cross?(other)
54
54
  # case 1: this one is horizontal:
55
55
  # overlaps other by x, to right and left, and goes inside it by y
@@ -60,15 +60,17 @@ module MagicCloud
60
60
  @y0 < other.y0 && @y1 > other.y1 &&
61
61
  @x0 > other.x0 && @x1 < other.x1
62
62
  end
63
- # rubocop:enable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity,Metrics/AbcSize
63
+ # rubocop:enable Metrics/CyclomaticComplexity
64
64
 
65
65
  def intersect(other)
66
66
  # direct comparison is dirtier, yet significantly faster than
67
67
  # something like [@x0, other.x0].max
68
+ # rubocop:disable Style/MinMaxComparison
68
69
  ix0 = @x0 > other.x0 ? @x0 : other.x0
69
70
  ix1 = @x1 < other.x1 ? @x1 : other.x1
70
71
  iy0 = @y0 > other.y0 ? @y0 : other.y0
71
72
  iy1 = @y1 < other.y1 ? @y1 : other.y1
73
+ # rubocop:enable Style/MinMaxComparison
72
74
 
73
75
  if ix0 > ix1 || iy0 > iy1
74
76
  nil # rectangles are not intersected, in fact
@@ -1,4 +1,5 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
2
3
  module MagicCloud
3
4
  # Basic "abstract shape" class, with all primitive functionality
4
5
  # necessary for use it in Spriter and Layouter.
@@ -1,5 +1,6 @@
1
- # encoding: utf-8
2
- require_relative './bit_matrix'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'bit_matrix'
3
4
 
4
5
  module MagicCloud
5
6
  # Incapsulates sprite maker for any Shape, able to draw itself.
@@ -21,14 +22,14 @@ module MagicCloud
21
22
  end
22
23
 
23
24
  Debug.logger.info 'Sprites ready: %i sec, %i canvases' %
24
- [Time.now - start, Debug.stats[:canvases]]
25
+ [Time.now - start, Debug.stats[:canvases]]
25
26
  end
26
27
 
27
28
  private
28
29
 
29
30
  attr_reader :canvas, :cur_x, :cur_y, :row_height
30
31
 
31
- def make_sprite(shape)
32
+ def make_sprite(shape) # rubocop:todo Metrics/AbcSize
32
33
  rect = shape.measure(canvas)
33
34
  ensure_position(rect)
34
35
 
@@ -42,10 +43,10 @@ module MagicCloud
42
43
  shift_position(rect)
43
44
 
44
45
  Debug.logger.debug 'Sprite for %p ready: %i×%i' %
45
- [shape, shape.sprite.width, shape.sprite.height]
46
+ [shape, shape.sprite.width, shape.sprite.height]
46
47
  end
47
48
 
48
- CANVAS_SIZE = [1024, 1024]
49
+ CANVAS_SIZE = [1024, 1024].freeze
49
50
 
50
51
  def restart_canvas!
51
52
  Debug.stats[:canvases] += 1
@@ -1,6 +1,6 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # Wordle-like word cloud main module
4
4
  module MagicCloud
5
- VERSION = '0.0.4' # aka Better initial layout
5
+ VERSION = '0.0.5' # aka 2024 update for new Rubies compatibility.
6
6
  end
@@ -1,5 +1,6 @@
1
- # encoding: utf-8
2
- require_relative './shape'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'shape'
3
4
 
4
5
  module MagicCloud
5
6
  # Class representing individual word in word cloud
data/lib/magic_cloud.rb CHANGED
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  # Wordle-like word cloud main module
4
4
  module MagicCloud
data/magic_cloud.gemspec CHANGED
@@ -37,4 +37,6 @@ Gem::Specification.new do |s|
37
37
  s.add_development_dependency 'rubocop'
38
38
  s.add_development_dependency 'bundler'
39
39
  s.add_development_dependency 'ruby-prof'
40
+ s.add_development_dependency 'rake'
41
+ s.add_development_dependency 'rubygems-tasks'
40
42
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magic_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Shepelev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-08 00:00:00.000000000 Z
11
+ date: 2024-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rmagick
@@ -80,6 +80,34 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubygems-tasks
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
83
111
  description: |2
84
112
  Simple, pure-ruby library for making pretty Wordle-like clouds.
85
113
  It uses RMagick as graphic backend.
@@ -128,8 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
156
  - !ruby/object:Gem::Version
129
157
  version: '0'
130
158
  requirements: []
131
- rubyforge_project:
132
- rubygems_version: 2.4.8
159
+ rubygems_version: 3.4.10
133
160
  signing_key:
134
161
  specification_version: 4
135
162
  summary: Pretty word cloud maker for Ruby