usps_flags 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,136 @@
1
+ # United States Power Squadrons® Flag Generator
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/usps_flags.svg)](https://badge.fury.io/rb/usps_flags)
4
+ [![Build Status](https://travis-ci.org/jfiander/usps-flags.svg)](https://travis-ci.org/jfiander/usps-flags)
5
+ [![Coverage Status](https://coveralls.io/repos/github/jfiander/usps-flags/badge.svg?branch=master)](https://coveralls.io/github/jfiander/usps-flags?branch=master)
6
+
7
+ This gem allows you to generate precise SVG and PNG flag images based on official specifications.
8
+
9
+ ## Installation
10
+
11
+ ### Rails
12
+
13
+ Add to your Gemfile:
14
+ ```ruby
15
+ gem 'usps_flags'
16
+ ```
17
+
18
+ Create the file `config/initializers/usps_flags.rb`:
19
+ ```ruby
20
+ USPSFlags::Config.flags_dir "#{Rails.root}/app/assets/images/flags"
21
+ ```
22
+
23
+ ### Other
24
+
25
+ Run `gem install usps_flags`.
26
+
27
+ Run `require 'usps_flags'` then `USPSFlags::Config.flags_dir "path/to/flags/dir"` to specify where to output all generated files and logs. (Otherwise, will default to `/output` in the gem directory.)
28
+
29
+ ## Available flags
30
+
31
+ - US Ensign
32
+ - USPS Ensign
33
+ - USPS Ensign Wheel logo
34
+ - Officer flags
35
+ - Officer insignia
36
+ - Official pennants
37
+
38
+ ## Generation
39
+
40
+ ### All files
41
+
42
+ To generate all static files, run:
43
+ ```ruby
44
+ USPSFlags::Generate.all svg: true, png: true, zips: true
45
+ ```
46
+
47
+ - Boolean arguments specify whether to process that set of files.
48
+
49
+ ### Zip archives
50
+
51
+ To re-generate zip files from current static files, run:
52
+ ```ruby
53
+ USPSFlags::Generate.zips svg: true, png: true
54
+ ```
55
+
56
+ - Boolean arguments specify whether to process that set of files.
57
+
58
+ ### Individual files
59
+
60
+ To generate an individual SVG file, run:
61
+ ```ruby
62
+ USPSFlags::Generate.get "flag", outfile: nil, scale: nil, field: true
63
+ ```
64
+
65
+ - `outfile` specifies where to save the file. If left as `nil`, this method will `puts` the generated SVG. Either way, the SVG code is returned.
66
+ - `scale` is a divisor scaling factor – the larger it is, the smaller the resulting SVG will be rendered. Accepted values are floats between 0 and 1, and integers above that.
67
+ - `field` specifies whether to render the field of a flag, or to only render the insignia. Setting this to `false` will invert some colors for visibility.
68
+
69
+ ### Trident spec sheet
70
+
71
+ To generate the trident spec sheet, run:
72
+ ```ruby
73
+ USPSFlags::Generate.spec outfile: nil, scale: nil, fly: 24, unit: "in"
74
+ ```
75
+
76
+ - `outfile` specifies where to save the file. If left as `nil`, this method will `puts` the generated SVG. Either way, the SVG code is returned.
77
+ - `scale` is a divisor scaling factor – the larger it is, the smaller the resulting SVG will be rendered. Accepted values are floats between 0 and 1, and integers above that.
78
+ - `fly` specifies the custom fly measurement to scale all trident labels to.
79
+ - `unit` specifies the custom fly measurement unit to append to all trident labels.
80
+
81
+ ### Convert SVG to PNG
82
+
83
+ To convert SVG data to a PNG image, run:
84
+ ```ruby
85
+ USPSFlags::Generate.png svg_data, outfile: nil, trim: false
86
+
87
+ # USPSFlags::Generate.png File.read("path/to/svg_image.svg"), outfile: "path/to/output.png", trim: false
88
+ # USPSFlags::Generate.png USPSFlags::Generate.get("LtC"), outfile: "path/to/output.png", trim: true
89
+ ```
90
+
91
+ - `outfile` is required, and specifies where to save the file.
92
+ - `trim` specifies whether to trim blank space from around the image. (This is ideal for generating insignia.)
93
+
94
+ ## Building
95
+
96
+ You can also build individual flags using the following DSL:
97
+
98
+ ```ruby
99
+ f = USPSFlags.new do
100
+ type "LtC"
101
+ scale 3
102
+ field false
103
+ trim true
104
+ svg_file "/path/to/svg/output.svg"
105
+ png_file "/path/to/png/output.png"
106
+ end
107
+
108
+ f.svg # Generate SVG file
109
+ f.png # Generate PNG file
110
+ ```
111
+
112
+ - Calling any DSL method without argument, or with `nil` as argument will return the current value.
113
+ - You can explicitly set `svg_file` to `""` to suppress printing the SVG content to console/log.
114
+ - Calling `.png` requires `png_file` to be set.
115
+
116
+ ## Security
117
+
118
+ This gem is cryptographically signed. To be sure the gem code hasn’t been tampered with:
119
+
120
+ Add my public key as a trusted certificate:
121
+
122
+ ```sh
123
+ gem cert --add <(curl -Ls https://raw.github.com/jfiander/usps-flags/master/certs/jfiander.pem)
124
+ ```
125
+
126
+ Then install the gem securely:
127
+
128
+ ```sh
129
+ gem install usps_flags -P HighSecurity
130
+ ```
131
+
132
+ ## License
133
+
134
+ Actual images generated (other than the US Ensign) are Copyright © United States Power Squadrons.
135
+
136
+ This gem is released under the [GPLv3](https://raw.github.com/jfiander/usps-flags/master/LICENSE).
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task default: :spec
7
+ task test: :spec
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MQ8wDQYDVQQDDAZqdWxp
3
+ YW4xFzAVBgoJkiaJk/IsZAEZFgdmaWFuZGVyMRMwEQYKCZImiZPyLGQBGRYDb25l
4
+ MB4XDTE3MTAxNzIwMzYwNVoXDTE4MTAxNzIwMzYwNVowPzEPMA0GA1UEAwwGanVs
5
+ aWFuMRcwFQYKCZImiZPyLGQBGRYHZmlhbmRlcjETMBEGCgmSJomT8ixkARkWA29u
6
+ ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKgyweLKJcXOZUJ/Y/fb
7
+ IjGIQzFgi0UUbIxc6BRP3BYCAr7MpflEq3sYaVsECs0ZyM27zLpyDN0oW73Wby6k
8
+ jaik/yBcsDMvrl58+6mjHnB3yIuk0BbEfQaijgMBzW2p0hToocMToMXigwZOGe4e
9
+ kPTAO6yTIIYLhhjWALA+nURCBcCNI8d1YAIjiEuF1lCr4pnV4aAq8tPBVrz7a8Fg
10
+ WpeLe0V1Blhkg9BDzNUmSrDxDxitO8oA5+A0z9Wm1xn8cJfn50103813SEK8gaXV
11
+ eb/zLRa/CNnTzQ8xUrySd10b1auLnKduXgewBhINcWYjDOT/C1FCjxpK5F6buJ6S
12
+ 1ukCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFI/F
13
+ wfSc4YJ3gO9EnkvjGcT6fE3WMB0GA1UdEQQWMBSBEmp1bGlhbkBmaWFuZGVyLm9u
14
+ ZTAdBgNVHRIEFjAUgRJqdWxpYW5AZmlhbmRlci5vbmUwDQYJKoZIhvcNAQEFBQAD
15
+ ggEBAHddpCbrFKtf02u/4MPzRQQO+uTP9vlbNDxseQsMvpjIIzMjJzANGBqPeI+V
16
+ HCjLEnKtnUi9br+RqjtQWWc2jGBdZwrlhOFglKUcTVn60ZvBNrByUj8PeBHQR3U2
17
+ vEKSi1v2i/jlVVvrk+9z4DZ4QdrfARBcPCZhUSZcZBsDbnzjMeX6lhoknnqKn/oi
18
+ op1Z8vhtFmvxNk4UfHMG1bdUoxl6DDXKfodqWM//9mARZwSyVX9oV7snFP0nKUaD
19
+ 3YzYAc+kXfD7kkzA2NMvLT6Q1v03qQyIZ8BS8SNk5wLGAdLM+IravFDLEs448fjz
20
+ lEAU0RHLFVbE+CXW6makIlWGHR0=
21
+ -----END CERTIFICATE-----
@@ -0,0 +1,37 @@
1
+ # Monkey patch to add some formatting methods to Rational.
2
+ #
3
+ # @author Julian Fiander
4
+ # @since 0.1.5
5
+ class Rational
6
+ # Converts Rational to String
7
+ #
8
+ # If Rational is an improper fraction, removes the integer part to convert to a mixed fraction.
9
+ #
10
+ # @example Mixed fraction
11
+ # Rational(4,3).to_simplified_s #=> "1 1/3"
12
+ # @return [String] If less than 1, fraction. If greater than 1, a mixed fraction.
13
+ def to_simplified_s
14
+ if self < 1
15
+ to_s
16
+ else
17
+ truncated = self.truncate
18
+ "#{truncated} #{self - truncated}"
19
+ end
20
+ end
21
+
22
+ # Converts Rational to Array
23
+ #
24
+ # If Rational is an improper fraction, removes the integer part to convert to a mixed fraction.
25
+ #
26
+ # @example Mixed fraction
27
+ # Rational(4,3).to_simplified_a #=> [1, Rational(1,3)]
28
+ # @return [Array] If less than 1, fraction. If greater than 1, a mixed fraction.
29
+ def to_simplified_a
30
+ if self < 1
31
+ to_s
32
+ else
33
+ truncated = self.truncate
34
+ [truncated, (self - truncated)]
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,140 @@
1
+ # Base class for the namespace. Provides a constructor DSL.
2
+ #
3
+ # @author Julian Fiander
4
+ # @since 0.1.5
5
+ class USPSFlags
6
+ require 'fileutils'
7
+ require 'zip'
8
+ require 'mini_magick'
9
+ require 'rational'
10
+ require 'usps_flags/config'
11
+ require 'usps_flags/helpers'
12
+ require 'usps_flags/core'
13
+ require 'usps_flags/generate'
14
+
15
+ # Constructor for individual flags.
16
+ #
17
+ # @example Generate insignia at default scale for Lt/C
18
+ # f = USPSFlags.new do
19
+ # type "LtC"
20
+ # scale 3
21
+ # field false
22
+ # trim true
23
+ # svg_file "/path/to/svg/output.svg"
24
+ # png_file "/path/to/png/output.png"
25
+ # end
26
+ #
27
+ # f.svg #=> Generates SVG file at "/path/to/svg/output.svg"
28
+ # f.png #=> Generates PNG file at "/path/to/png/output.png"
29
+ def initialize(&block)
30
+ @type = nil
31
+ @svg_file = nil
32
+ @png_file = nil
33
+ @scale = nil
34
+ @field = nil
35
+ @trim = nil
36
+ instance_eval(&block) if block_given?
37
+ end
38
+
39
+ # Constructor accessor for the flag type.
40
+ #
41
+ # @param [String] type If set, updates the constructor's flag type.
42
+ # @return [String] Returns the current (or updated) flag type.
43
+ def type(string = nil)
44
+ if string.nil?
45
+ @type
46
+ else
47
+ @type = string
48
+ self
49
+ end
50
+ end
51
+
52
+ # Constructor accessor for the SVG file output path.
53
+ #
54
+ # @param [String] svg_file If set, updates the constructor's SVG file output path.
55
+ # @return [String] Returns the current (or updated) SVG file output path.
56
+ def svg_file(string = nil)
57
+ if string.nil?
58
+ @svg_file
59
+ else
60
+ @svg_file = string
61
+ self
62
+ end
63
+ end
64
+
65
+ # Constructor accessor for the PNG file output path.
66
+ #
67
+ # @param [String] png_file If set, updates the constructor's PNG file output path.
68
+ # @return [String] Returns the current (or updated) PNG file output path.
69
+ def png_file(string = nil)
70
+ if string.nil?
71
+ @png_file
72
+ else
73
+ @png_file = string
74
+ self
75
+ end
76
+ end
77
+
78
+ # Constructor accessor for the image scale divisor factor.
79
+ #
80
+ # Available options are Float between 0 and 1, or Integer above 1.
81
+ #
82
+ # @param [Integer, Float] scale If set, updates the constructor's scale divisor factor.
83
+ # @return [Integer, Float] Returns the current (or updated) scaling factor.
84
+ def scale(num = nil)
85
+ if num.nil?
86
+ @scale
87
+ else
88
+ @scale = num
89
+ self
90
+ end
91
+ end
92
+
93
+ # Constructor accessor for whether to generate the flag field (including any border).
94
+ #
95
+ # @param [Boolean] field If set, updates the constructor's field setting.
96
+ # @return [Boolean] Returns the current (or updated) setting.
97
+ def field(bool = nil)
98
+ if bool.nil?
99
+ @field
100
+ else
101
+ @field = bool
102
+ self
103
+ end
104
+ end
105
+
106
+ # Constructor accessor for whether to trim the generated PNG file of excess transparency.
107
+ #
108
+ # @param [Boolean] trim If set, updates the constructor's trim setting.
109
+ # @return [String] Returns the current (or updated) setting.
110
+ def trim(bool = nil)
111
+ if bool.nil?
112
+ @trim
113
+ else
114
+ @trim = bool
115
+ self
116
+ end
117
+ end
118
+
119
+ # Generates the constructed file as SVG.
120
+ #
121
+ # @return [String] Returns the SVG file output path, or the svg data if no path was specified.
122
+ def svg
123
+ svg = USPSFlags::Generate.get(self.type, outfile: self.svg_file, scale: self.scale, field: self.field)
124
+ (self.svg_file.nil? || self.svg_file == "") ? svg : self.svg_file
125
+ end
126
+
127
+ # Generates the constructed file as PNG.
128
+ #
129
+ # Requires the constructor to have a value for png_file.
130
+ #
131
+ # @return [String] Returns the SVG file output path.
132
+ def png
133
+ raise "Error: png_file must be set." if self.png_file.nil?
134
+ svg_file_storage = self.svg_file
135
+ self.svg_file ""
136
+ USPSFlags::Generate.png(self.svg, outfile: self.png_file, trim: self.trim)
137
+ self.svg_file svg_file_storage
138
+ self.png_file
139
+ end
140
+ end
@@ -0,0 +1,115 @@
1
+ # Container class for configuration values.
2
+ class USPSFlags::Config
3
+ BLUE ||= "#041E42" # Old Glory Blue
4
+ RED ||= "#BF0D3E" # Old Glory Red
5
+
6
+ # Base measurements for most flags, before scaling
7
+ BASE_FLY ||= 3072
8
+ BASE_HOIST ||= BASE_FLY*2/3
9
+ FRACTION_SCALE ||= 85
10
+
11
+ @@flags_dir ||= "#{File.dirname(__dir__)}/output"
12
+ @@use_larger_tridents ||= true
13
+
14
+ # Accessor for the directory for storing generated flags.
15
+ #
16
+ # @param [String] init If set, updates the path to the directory for storing generated flags.
17
+ # @param [Boolean] reset Delete all files in the specified directory if found.
18
+ # @example Update flag storage directory
19
+ # # Rails.root => "/path/to"
20
+ # USPSFlags::Config.flags_dir "#{Rails.root}/app/assets/images/flags" #=> "/path/to/app/assets/images/flags"
21
+ # @example Update flag storage directory that already has some files in it
22
+ # # Rails.root => "/path/to"
23
+ # USPSFlags::Config.flags_dir "#{Rails.root}/app/assets/images/flags", reset: true #=> "/path/to/app/assets/images/flags"
24
+ # @return [String] Returns the current (or updated) path to the flags directory.
25
+ def self.flags_dir(init = nil, reset: false)
26
+ unless init.nil?
27
+ @@flags_dir = init
28
+ ::FileUtils.rm_rf(USPSFlags::Config.flags_dir) if reset
29
+ [
30
+ "#{USPSFlags::Config.flags_dir}/SVG/insignia",
31
+ "#{USPSFlags::Config.flags_dir}/PNG/insignia",
32
+ "#{USPSFlags::Config.flags_dir}/ZIP"
33
+ ].each do |dir|
34
+ ::FileUtils.mkdir_p(dir)
35
+ end
36
+ ::FileUtils.mkdir_p(USPSFlags::Config.log_path) unless defined?(Rails)
37
+ end
38
+ @@flags_dir
39
+ end
40
+
41
+ # Alias for the directory to store generated log files.
42
+ #
43
+ # @example Rails
44
+ # # Rails.root => "/path/to"
45
+ # USPSFlags::Config.logs_dir #=> "/path/to/log"
46
+ #
47
+ # @example Non-Rails
48
+ # USPSFlags::Config.logs_dir #=> "/app/root/log"
49
+ def self.log_path
50
+ if defined?(Rails)
51
+ "#{Rails.root}/log"
52
+ else
53
+ log_dir = "#{self.flags_dir}/log"
54
+ ::FileUtils.mkdir_p(log_dir)
55
+ log_dir
56
+ end
57
+ end
58
+
59
+ # Accessor for the boolean of whether to use the larger or smaller trident width.
60
+ #
61
+ # @param [Boolean] bool If set to a Boolean, specify whether to use the larger trident width.
62
+ # @return [Boolean] Returns the current (or updated) setting.
63
+ def self.use_larger_tridents(bool = nil)
64
+ # Smaller: 1/2 in width on 24in x 16in field
65
+ # Larger: 5/8 in width on 24in x 16in field
66
+ @@use_larger_tridents = bool unless bool.nil? || !([true, false].include?(bool))
67
+ @@use_larger_tridents
68
+ end
69
+
70
+ # Base configuration values for trident insignia.
71
+ #
72
+ # All other values are derived from these, or directly from the constant sizes.
73
+ #
74
+ # @return [Hash] Returns the configuration values for tridents.
75
+ def self.trident
76
+ point_height = USPSFlags::Config::BASE_FLY/48*17/8
77
+ bar_width = USPSFlags::Config::BASE_FLY/48
78
+ bar_width = bar_width*5/4 if self.use_larger_tridents
79
+ {
80
+ height: {
81
+ s: USPSFlags::Config::BASE_HOIST/2,
82
+ d: USPSFlags::Config::BASE_HOIST*5/8,
83
+ stf: USPSFlags::Config::BASE_HOIST*3/4,
84
+ n: USPSFlags::Config::BASE_HOIST*3/4
85
+ },
86
+
87
+ center_point: BASE_FLY/2,
88
+
89
+ width: USPSFlags::Config::BASE_FLY*5/32,
90
+
91
+ bar_width: bar_width,
92
+
93
+ point_height: point_height,
94
+
95
+ main_point_barb: USPSFlags::Config::BASE_HOIST/240,
96
+
97
+ crossbar_from_top: USPSFlags::Config::BASE_HOIST/4,
98
+
99
+ side_spike_height: USPSFlags::Config::BASE_HOIST/4-point_height-bar_width,
100
+
101
+ hash_width: USPSFlags::Config::BASE_FLY*3/32,
102
+
103
+ delta_height: USPSFlags::Config::BASE_FLY*2/15,
104
+ delta_gap_height: self.use_larger_tridents ? USPSFlags::Config::BASE_FLY*14/256 : USPSFlags::Config::BASE_FLY*17/256,
105
+ delta_gap_width: self.use_larger_tridents ? bar_width*5/4 : bar_width*7/4,
106
+ delta_width: USPSFlags::Config::BASE_FLY*43/768,
107
+ delta_from_bottom: USPSFlags::Config::BASE_HOIST*11/64,
108
+ delta_gap_scale: 0.40,
109
+ delta_gap_x: USPSFlags::Config::BASE_HOIST*144/128,
110
+ delta_gap_y: USPSFlags::Config::BASE_HOIST*221/256,
111
+
112
+ circle_height_adj: USPSFlags::Config::BASE_FLY/800
113
+ }
114
+ end
115
+ end