geo_pattern 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []