geo_pattern 1.2.1 → 1.3.0

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.
@@ -0,0 +1,93 @@
1
+ module GeoPattern
2
+ class TessellationPattern < BasePattern
3
+ def render_to_svg
4
+ # 3.4.6.4 semi-regular tessellation
5
+ side_length = map(hex_val(0, 1), 0, 15, 5, 40)
6
+ hex_height = side_length * Math.sqrt(3)
7
+ hex_width = side_length * 2
8
+ triangle_height = side_length/2 * Math.sqrt(3)
9
+ triangle = build_rotated_triangle_shape(side_length, triangle_height)
10
+ tile_width = side_length*3 + triangle_height*2
11
+ tile_height = (hex_height * 2) + (side_length * 2)
12
+
13
+ svg.set_width(tile_width)
14
+ svg.set_height(tile_height)
15
+
16
+ for i in 0..19
17
+ val = hex_val(i, 1)
18
+ opacity = opacity(val)
19
+ fill = fill_color(val)
20
+
21
+ styles = {
22
+ "stroke" => STROKE_COLOR,
23
+ "stroke-opacity" => STROKE_OPACITY,
24
+ "fill" => fill,
25
+ "fill-opacity" => opacity,
26
+ "stroke-width" => 1
27
+ }
28
+
29
+ case i
30
+ when 0 # all 4 corners
31
+ svg.rect(-side_length/2, -side_length/2, side_length, side_length, styles)
32
+ svg.rect(tile_width - side_length/2, -side_length/2, side_length, side_length, styles)
33
+ svg.rect(-side_length/2, tile_height-side_length/2, side_length, side_length, styles)
34
+ svg.rect(tile_width - side_length/2, tile_height-side_length/2, side_length, side_length, styles)
35
+ when 1 # center / top square
36
+ svg.rect(hex_width/2 + triangle_height, hex_height/2, side_length, side_length, styles)
37
+ when 2 # side squares
38
+ svg.rect(-side_length/2, tile_height/2-side_length/2, side_length, side_length, styles)
39
+ svg.rect(tile_width-side_length/2, tile_height/2-side_length/2, side_length, side_length, styles)
40
+ when 3 # center / bottom square
41
+ svg.rect(hex_width/2 + triangle_height, hex_height * 1.5 + side_length, side_length, side_length, styles)
42
+ when 4 # left top / bottom triangle
43
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{side_length/2}, #{-side_length/2}) rotate(0, #{side_length/2}, #{triangle_height/2})"}))
44
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{side_length/2}, #{tile_height--side_length/2}) rotate(0, #{side_length/2}, #{triangle_height/2}) scale(1, -1)"}))
45
+ when 5 # right top / bottom triangle
46
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{tile_width-side_length/2}, #{-side_length/2}) rotate(0, #{side_length/2}, #{triangle_height/2}) scale(-1, 1)"}))
47
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{tile_width-side_length/2}, #{tile_height+side_length/2}) rotate(0, #{side_length/2}, #{triangle_height/2}) scale(-1, -1)"}))
48
+ when 6 # center / top / right triangle
49
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{tile_width/2+side_length/2}, #{hex_height/2})"}))
50
+ when 7 # center / top / left triangle
51
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{tile_width-tile_width/2-side_length/2}, #{hex_height/2}) scale(-1, 1)"}))
52
+ when 8 # center / bottom / right triangle
53
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{tile_width/2+side_length/2}, #{tile_height-hex_height/2}) scale(1, -1)"}))
54
+ when 9 # center / bottom / left triangle
55
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{tile_width-tile_width/2-side_length/2}, #{tile_height-hex_height/2}) scale(-1, -1)"}))
56
+ when 10 # left / middle triangle
57
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{side_length/2}, #{tile_height/2 - side_length/2})"}))
58
+ when 11 # right / middle triangle
59
+ svg.polyline(triangle, styles.merge({"transform" => "translate(#{tile_width-side_length/2}, #{tile_height/2 - side_length/2}) scale(-1, 1)"}))
60
+ when 12 # left / top square
61
+ svg.rect(0, 0, side_length, side_length,
62
+ styles.merge({"transform" => "translate(#{side_length/2}, #{side_length/2}) rotate(-30, 0, 0)"}))
63
+ when 13 # right / top square
64
+ svg.rect(0, 0, side_length, side_length,
65
+ styles.merge({"transform" => "scale(-1, 1) translate(#{-tile_width+side_length/2}, #{side_length/2}) rotate(-30, 0, 0)" }))
66
+ when 14 # left / center-top square
67
+ svg.rect(0, 0, side_length, side_length,
68
+ styles.merge({"transform" => "translate(#{side_length/2}, #{tile_height/2-side_length/2-side_length}) rotate(30, 0, #{side_length})" }))
69
+ when 15 # right / center-top square
70
+ svg.rect(0, 0, side_length, side_length,
71
+ styles.merge({"transform" => "scale(-1, 1) translate(#{-tile_width+side_length/2}, #{tile_height/2-side_length/2-side_length}) rotate(30, 0, #{side_length})" }))
72
+ when 16 # left / center-top square
73
+ svg.rect(0, 0, side_length, side_length,
74
+ styles.merge({"transform" => "scale(1, -1) translate(#{side_length/2}, #{-tile_height+tile_height/2-side_length/2-side_length}) rotate(30, 0, #{side_length})" }))
75
+ when 17 # right / center-bottom square
76
+ svg.rect(0, 0, side_length, side_length,
77
+ styles.merge({"transform" => "scale(-1, -1) translate(#{-tile_width+side_length/2}, #{-tile_height+tile_height/2-side_length/2-side_length}) rotate(30, 0, #{side_length})" }))
78
+ when 18 # left / bottom square
79
+ svg.rect(0, 0, side_length, side_length,
80
+ styles.merge({"transform" => "scale(1, -1) translate(#{side_length/2}, #{-tile_height+side_length/2}) rotate(-30, 0, 0)"}))
81
+ when 19 # right / bottom square
82
+ svg.rect(0, 0, side_length, side_length,
83
+ styles.merge({"transform" => "scale(-1, -1) translate(#{-tile_width+side_length/2}, #{-tile_height+side_length/2}) rotate(-30, 0, 0)"}))
84
+ end
85
+ end
86
+ end
87
+
88
+ def build_rotated_triangle_shape(side_length, width)
89
+ half_height = side_length / 2
90
+ "0, 0, #{width}, #{half_height}, 0, #{side_length}, 0, 0"
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,51 @@
1
+ module GeoPattern
2
+ class TrianglePattern < BasePattern
3
+ def render_to_svg
4
+ scale = hex_val(0, 1)
5
+ side_length = map(scale, 0, 15, 15, 80)
6
+ triangle_height = side_length/2 * Math.sqrt(3)
7
+ triangle = build_triangle_shape(side_length, triangle_height)
8
+
9
+ svg.set_width(side_length * 3)
10
+ svg.set_height(triangle_height * 6)
11
+
12
+ i = 0
13
+ for y in 0..5
14
+ for x in 0..5
15
+ val = hex_val(i, 1)
16
+ opacity = opacity(val)
17
+ fill = fill_color(val)
18
+
19
+ styles = {
20
+ "fill" => fill,
21
+ "fill-opacity" => opacity,
22
+ "stroke" => STROKE_COLOR,
23
+ "stroke-opacity" => STROKE_OPACITY
24
+ }
25
+
26
+ rotation = ""
27
+ if y % 2 == 0
28
+ rotation = x % 2 == 0 ? 180 : 0
29
+ else
30
+ rotation = x % 2 != 0 ? 180 : 0
31
+ end
32
+
33
+ svg.polyline(triangle, styles.merge({
34
+ "transform" => "translate(#{x*side_length*0.5 - side_length/2}, #{triangle_height*y}) rotate(#{rotation}, #{side_length/2}, #{triangle_height/2})"}))
35
+
36
+ # Add an extra one at top-right, for tiling.
37
+ if (x == 0)
38
+ svg.polyline(triangle, styles.merge({
39
+ "transform" => "translate(#{6*side_length*0.5 - side_length/2}, #{triangle_height*y}) rotate(#{rotation}, #{side_length/2}, #{triangle_height/2})"}))
40
+ end
41
+ i += 1
42
+ end
43
+ end
44
+ end
45
+
46
+ def build_triangle_shape(side_length, height)
47
+ half_width = side_length / 2
48
+ "#{half_width}, 0, #{side_length}, #{height}, 0, #{height}, #{half_width}, 0"
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,58 @@
1
+ module GeoPattern
2
+ class XesPattern < BasePattern
3
+ def render_to_svg
4
+ square_size = map(hex_val(0, 1), 0, 15, 10, 25)
5
+ x_shape = build_plus_shape(square_size) # rotated later
6
+ x_size = square_size * 3 * 0.943
7
+
8
+ svg.set_width(x_size * 3)
9
+ svg.set_height(x_size * 3)
10
+
11
+ i = 0
12
+ for y in 0..5
13
+ for x in 0..5
14
+ val = hex_val(i, 1)
15
+ opacity = opacity(val)
16
+ dy = x % 2 == 0 ? y*x_size - x_size*0.5 : y*x_size - x_size*0.5 + x_size/4
17
+ fill = fill_color(val)
18
+
19
+ styles = {
20
+ "fill" => fill,
21
+ "style" => {
22
+ "opacity" => opacity
23
+ }
24
+ }
25
+
26
+ svg.group(x_shape, styles.merge({
27
+ "transform" => "translate(#{x*x_size/2 - x_size/2},#{dy - y*x_size/2}) rotate(45, #{x_size/2}, #{x_size/2})"}))
28
+
29
+ # Add an extra column on the right for tiling.
30
+ if (x == 0)
31
+ svg.group(x_shape, styles.merge({
32
+ "transform" => "translate(#{6*x_size/2 - x_size/2},#{dy - y*x_size/2}) rotate(45, #{x_size/2}, #{x_size/2})"}))
33
+ end
34
+
35
+ # Add an extra row on the bottom that matches the first row, for tiling.
36
+ if (y == 0)
37
+ dy = x % 2 == 0 ? 6*x_size - x_size/2 : 6*x_size - x_size/2 + x_size/4;
38
+ svg.group(x_shape, styles.merge({
39
+ "transform" => "translate(#{x*x_size/2 - x_size/2},#{dy - 6*x_size/2}) rotate(45, #{x_size/2}, #{x_size/2})"}))
40
+ end
41
+
42
+ # These can hang off the bottom, so put a row at the top for tiling.
43
+ if (y == 5)
44
+ svg.group(x_shape, styles.merge({
45
+ "transform" => "translate(#{x*x_size/2 - x_size/2},#{dy - 11*x_size/2}) rotate(45, #{x_size/2}, #{x_size/2})"}))
46
+ end
47
+
48
+ # Add an extra one at top-right and bottom-right, for tiling.
49
+ if (x == 0 && y == 0)
50
+ svg.group(x_shape, styles.merge({
51
+ "transform" => "translate(#{6*x_size/2 - x_size/2},#{dy - 6*x_size/2}) rotate(45, #{x_size/2}, #{x_size/2})"}))
52
+ end
53
+ i += 1
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,105 @@
1
+ require 'base64'
2
+ require 'digest/sha1'
3
+ require 'color'
4
+
5
+ module GeoPattern
6
+ class PatternGenerator
7
+ DEFAULTS = {
8
+ :base_color => '#933c3c'
9
+ }
10
+
11
+ PATTERNS = {
12
+ 'chevrons' => ChevronPattern,
13
+ 'concentric_circles' => ConcentricCirclesPattern,
14
+ 'diamonds' => DiamondPattern,
15
+ 'hexagons' => HexagonPattern,
16
+ 'mosaic_squares' => MosaicSquaresPattern,
17
+ 'nested_squares' => NestedSquaresPattern,
18
+ 'octagons' => OctagonPattern,
19
+ 'overlapping_circles' => OverlappingCirclesPattern,
20
+ 'overlapping_rings' => OverlappingRingsPattern,
21
+ 'plaid' => PlaidPattern,
22
+ 'plus_signs' => PlusSignPattern,
23
+ 'sine_waves' => SineWavePattern,
24
+ 'squares' => SquarePattern,
25
+ 'tessellation' => TessellationPattern,
26
+ 'triangles' => TrianglePattern,
27
+ 'xes' => XesPattern,
28
+ }.freeze
29
+
30
+ FILL_COLOR_DARK = "#222"
31
+ FILL_COLOR_LIGHT = "#ddd"
32
+ STROKE_COLOR = "#000"
33
+ STROKE_OPACITY = 0.02
34
+ OPACITY_MIN = 0.02
35
+ OPACITY_MAX = 0.15
36
+
37
+ attr_reader :opts, :hash, :svg
38
+
39
+ def initialize(string, opts={})
40
+ @opts = DEFAULTS.merge(opts)
41
+ @hash = Digest::SHA1.hexdigest string
42
+ @svg = SVG.new
43
+
44
+ generate_background
45
+ generate_pattern
46
+ end
47
+
48
+ def svg_string
49
+ svg.to_s
50
+ end
51
+ alias_method :to_s, :svg_string
52
+
53
+ def base64_string
54
+ Base64.strict_encode64(svg_string)
55
+ end
56
+
57
+ def uri_image
58
+ "url(data:image/svg+xml;base64,#{base64_string});"
59
+ end
60
+
61
+ def generate_background
62
+ if opts[:color]
63
+ rgb = Color::RGB.from_html(opts[:color])
64
+ else
65
+ hue_offset = PatternHelpers.map(PatternHelpers.hex_val(hash, 14, 3), 0, 4095, 0, 359)
66
+ sat_offset = PatternHelpers.hex_val(hash, 17, 1)
67
+ base_color = Color::RGB.from_html(opts[:base_color]).to_hsl
68
+ base_color.hue = base_color.hue - hue_offset;
69
+
70
+ if (sat_offset % 2 == 0)
71
+ base_color.saturation = base_color.saturation + sat_offset
72
+ else
73
+ base_color.saturation = base_color.saturation - sat_offset
74
+ end
75
+ rgb = base_color.to_rgb
76
+ end
77
+ r = (rgb.r * 255).round
78
+ g = (rgb.g * 255).round
79
+ b = (rgb.b * 255).round
80
+ svg.rect(0, 0, "100%", "100%", {"fill" => "rgb(#{r}, #{g}, #{b})"})
81
+ end
82
+
83
+ def generate_pattern
84
+ if opts[:generator].is_a? String
85
+ generator = PATTERNS[opts[:generator]]
86
+ puts SVG.as_comment("String pattern references are deprecated as of 1.3.0")
87
+ elsif opts[:generator] < BasePattern
88
+ if PATTERNS.values.include? opts[:generator]
89
+ generator = opts[:generator]
90
+ else
91
+ abort("Error: the requested generator is invalid")
92
+ generator = nil
93
+ end
94
+ end
95
+
96
+ if generator.nil?
97
+ generator = PATTERNS.values[[PatternHelpers.hex_val(hash, 20, 1), PATTERNS.length - 1].min]
98
+ end
99
+
100
+ # Instantiate the generator with the needed references
101
+ # and render the pattern to the svg object
102
+ generator.new(svg, hash).render_to_svg
103
+ end
104
+ end
105
+ end
@@ -63,5 +63,9 @@ module GeoPattern
63
63
  }
64
64
  str
65
65
  end
66
+
67
+ def self.as_comment(str)
68
+ "<!-- #{str} -->"
69
+ end
66
70
  end
67
71
  end
@@ -1,3 +1,3 @@
1
1
  module GeoPattern
2
- VERSION = "1.2.1"
2
+ VERSION = "1.3.0"
3
3
  end
metadata CHANGED
@@ -1,62 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geo_pattern
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
5
- prerelease:
4
+ version: 1.3.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Jason Long
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2014-03-10 00:00:00.000000000 Z
11
+ date: 2014-12-27 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: color
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '1.5'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.5'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: bundler
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
33
  version: '1.5'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
40
  version: '1.5'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rake
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - ">="
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  description: Generate SVG beautiful patterns
@@ -66,39 +59,56 @@ executables: []
66
59
  extensions: []
67
60
  extra_rdoc_files: []
68
61
  files:
69
- - .gitignore
62
+ - ".gitignore"
70
63
  - Gemfile
71
64
  - LICENSE.txt
72
65
  - README.md
73
66
  - Rakefile
74
67
  - geo_pattern.gemspec
75
68
  - lib/geo_pattern.rb
76
- - lib/geo_pattern/pattern.rb
69
+ - lib/geo_pattern/pattern/base_pattern.rb
70
+ - lib/geo_pattern/pattern/chevron_pattern.rb
71
+ - lib/geo_pattern/pattern/concentric_circles_pattern.rb
72
+ - lib/geo_pattern/pattern/diamond_pattern.rb
73
+ - lib/geo_pattern/pattern/hexagon_pattern.rb
74
+ - lib/geo_pattern/pattern/mosaic_squares_pattern.rb
75
+ - lib/geo_pattern/pattern/nested_squares_pattern.rb
76
+ - lib/geo_pattern/pattern/octagon_pattern.rb
77
+ - lib/geo_pattern/pattern/overlapping_circles_pattern.rb
78
+ - lib/geo_pattern/pattern/overlapping_rings_pattern.rb
79
+ - lib/geo_pattern/pattern/pattern_helpers.rb
80
+ - lib/geo_pattern/pattern/plaid_pattern.rb
81
+ - lib/geo_pattern/pattern/plus_sign_pattern.rb
82
+ - lib/geo_pattern/pattern/sine_wave_pattern.rb
83
+ - lib/geo_pattern/pattern/square_pattern.rb
84
+ - lib/geo_pattern/pattern/tessellation_pattern.rb
85
+ - lib/geo_pattern/pattern/triangle_pattern.rb
86
+ - lib/geo_pattern/pattern/xes_pattern.rb
87
+ - lib/geo_pattern/pattern_generator.rb
77
88
  - lib/geo_pattern/svg.rb
78
89
  - lib/geo_pattern/version.rb
79
90
  homepage: https://github.com/jasonlong/geo_pattern
80
91
  licenses:
81
92
  - MIT
93
+ metadata: {}
82
94
  post_install_message:
83
95
  rdoc_options: []
84
96
  require_paths:
85
97
  - lib
86
98
  required_ruby_version: !ruby/object:Gem::Requirement
87
- none: false
88
99
  requirements:
89
- - - ! '>='
100
+ - - ">="
90
101
  - !ruby/object:Gem::Version
91
102
  version: '0'
92
103
  required_rubygems_version: !ruby/object:Gem::Requirement
93
- none: false
94
104
  requirements:
95
- - - ! '>='
105
+ - - ">="
96
106
  - !ruby/object:Gem::Version
97
107
  version: '0'
98
108
  requirements: []
99
109
  rubyforge_project:
100
- rubygems_version: 1.8.23
110
+ rubygems_version: 2.2.0
101
111
  signing_key:
102
- specification_version: 3
112
+ specification_version: 4
103
113
  summary: Generate SVG beautiful patterns
104
114
  test_files: []