usps_flags 0.1.26 → 0.2.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.
@@ -8,18 +8,18 @@ class USPSFlags::Generate
8
8
  # @param [Boolean] field Whether to generate the flag field (including any border).
9
9
  # @param [String] scale The image scale divisor factor.
10
10
  # @return [String] Returns the SVG data.
11
- def get(flag, outfile: nil, scale: nil, field: true)
11
+ def svg(flag, outfile: nil, scale: nil, field: true)
12
12
  flag = flag.upcase.delete("/", "_", "PENNANT")
13
13
  if ["CRUISE", "OIC"].include?(flag)
14
- pennant(type: flag, outfile: outfile, scale: scale)
14
+ USPSFlags::Generate::Flag.pennant(type: flag, outfile: outfile, scale: scale)
15
15
  elsif flag == "ENSIGN"
16
- ensign(outfile: outfile, scale: scale)
16
+ USPSFlags::Generate::Flag.ensign(outfile: outfile, scale: scale)
17
17
  elsif flag == "US"
18
- us(outfile: outfile, scale: scale)
18
+ USPSFlags::Generate::Flag.us(outfile: outfile, scale: scale)
19
19
  elsif flag == "WHEEL"
20
- wheel(outfile: outfile, scale: scale)
20
+ USPSFlags::Generate::Flag.wheel(outfile: outfile, scale: scale)
21
21
  else
22
- flag(rank: flag, outfile: outfile, scale: scale, field: field)
22
+ USPSFlags::Generate::Flag.officer(rank: flag, outfile: outfile, scale: scale, field: field)
23
23
  end
24
24
  end
25
25
 
@@ -55,13 +55,12 @@ class USPSFlags::Generate
55
55
  def all(svg: true, png: true, zips: true, reset: true)
56
56
  remove_static_files if reset
57
57
 
58
- max_length = USPSFlags::Helpers.valid_flags(:all).map(&:length).max
59
58
  puts "\nSVGs generate a single file.",
60
59
  "PNGs generate full-res, 1500w, 1000w, 500w, and thumbnail files.",
61
60
  "Corresponding rank insignia (including smaller sizes) are also generated, as appropriate."
62
61
  USPSFlags::Helpers.log "\n#{Time.now.strftime('%Y%m%d.%H%M%S%z')} – Generating static files...\n\n"
63
- USPSFlags::Helpers.log "Flag | SVG | PNG | Run time\n".rjust(max_length+31),
64
- "\n".rjust(max_length+32, "-")
62
+ USPSFlags::Helpers.log "Flag | SVG | PNG | Run time\n".rjust(USPSFlags::Helpers.max_flag_name_length+31),
63
+ "\n".rjust(USPSFlags::Helpers.max_flag_name_length+32, "-")
65
64
 
66
65
  overall_start_time = Time.now
67
66
 
@@ -113,234 +112,62 @@ class USPSFlags::Generate
113
112
  # @return [String] Returns the SVG data.
114
113
  def spec(outfile: nil, fly: nil, unit: nil, scale: nil)
115
114
  fly = fly.nil? ? USPSFlags::Config::BASE_FLY : fly
116
- final_svg = ""
117
- final_svg << USPSFlags::Core.headers(scale: scale, title: "USPS Trident Specifications")
118
- final_svg << USPSFlags::Core.trident_spec(fly: fly, unit: unit)
119
- final_svg << USPSFlags::Core.footer
115
+ svg = ""
116
+ svg << USPSFlags::Core.headers(scale: scale, title: "USPS Trident Specifications")
117
+ svg << USPSFlags::Core.trident_spec(fly: fly, unit: unit)
118
+ svg << USPSFlags::Core.footer
120
119
 
121
- if outfile.nil?
122
- puts final_svg, "\n"
123
- else
124
- f = ::File.new(outfile, "w+")
125
- f.write(final_svg)
126
- f.close
127
- end
128
- final_svg
120
+ USPSFlags::Helpers.output(svg, outfile: outfile)
129
121
  end
130
122
 
131
123
  private
132
- def flag(rank: nil, width: USPSFlags::Config::BASE_FLY, outfile: nil, scale: nil, field: true)
133
- raise "Error: No rank specified." if rank.nil?
134
- rank = rank.to_s.upcase
135
-
136
- final_svg = ""
137
- final_svg << USPSFlags::Core.headers(scale: scale, title: rank)
138
-
139
- rank.slice!(0) if !field && USPSFlags::Helpers.valid_flags(:past).include?(rank)
140
- rank = "CDR" if rank == "C"
141
-
142
- flag_details = USPSFlags::Helpers.flag_details(rank)
143
- trident_color = field ? :white : flag_details[:color]
144
-
145
- final_svg << USPSFlags::Core.field(style: flag_details[:style], color: flag_details[:color]) if field
146
-
147
- final_svg << "<g transform=\"translate(-150, 400)\"><g transform=\"scale(0.58333)\">" if flag_details[:style] == :past
148
-
149
- if flag_details[:type] == :n && flag_details[:count] == 3
150
- # The side C/C tridents are angled 45 degrees, and intersect the central one at 1/3 up from the bottom
151
- trident = USPSFlags::Core.trident(flag_details[:type], color: trident_color)
152
- x_distance = USPSFlags::Config::BASE_FLY*4/39
153
- y_distance = USPSFlags::Config::BASE_FLY*5/78
154
- final_svg << "<g transform=\"translate(-#{x_distance}, #{y_distance})\"><g transform=\"rotate(-45, #{USPSFlags::Config::BASE_FLY/2}, #{USPSFlags::Config::BASE_HOIST/2})\">\n#{trident}</g></g>"
155
- final_svg << "\n#{trident}"
156
- final_svg << "<g transform=\"translate(#{x_distance}, #{y_distance})\"><g transform=\"rotate(45, #{USPSFlags::Config::BASE_FLY/2}, #{USPSFlags::Config::BASE_HOIST/2})\">\n#{trident}</g></g>"
157
- elsif flag_details[:type] == :n && flag_details[:count] == 2
158
- # V/C tridents are angled 45 degrees, and intersect at 15/32 up from the bottom
159
- trident = USPSFlags::Core.trident(flag_details[:type], color: trident_color)
160
- x_distance = USPSFlags::Config::BASE_FLY*4/55
161
- final_svg << "<g transform=\"translate(-#{x_distance})\"><g transform=\"rotate(-45, #{USPSFlags::Config::BASE_FLY/2}, #{USPSFlags::Config::BASE_HOIST/2})\">\n#{trident}</g></g>"
162
- final_svg << "<g transform=\"translate(#{x_distance})\"><g transform=\"rotate(45, #{USPSFlags::Config::BASE_FLY/2}, #{USPSFlags::Config::BASE_HOIST/2})\">\n#{trident}</g></g>"
163
- elsif [:s, :d].include?(flag_details[:type]) && flag_details[:count] == 3
164
- # Cdr and D/C tridents are spaced 1/2 the fly apart with the central one 1/4 the fly above the sides
165
- trident = USPSFlags::Core.trident(flag_details[:type], color: trident_color, field_color: flag_details[:color])
166
- x_distance = USPSFlags::Config::BASE_FLY/4
167
- y_distance = USPSFlags::Config::BASE_FLY/16
168
- final_svg << "<g transform=\"translate(-#{x_distance}, #{y_distance})\">\n#{trident}</g>"
169
- final_svg << "<g transform=\"translate(0, -#{y_distance+1})\">\n#{trident}</g>"
170
- final_svg << "<g transform=\"translate(#{x_distance}, #{y_distance})\">\n#{trident}</g>"
171
- elsif [:s, :d].include?(flag_details[:type]) && flag_details[:count] == 2
172
- # Lt/C and D/Lt/C tridents are spaced 1/3 the fly apart
173
- trident = USPSFlags::Core.trident(flag_details[:type], color: trident_color, field_color: flag_details[:color])
174
- x_distance = USPSFlags::Config::BASE_FLY/6
175
- final_svg << "<g transform=\"translate(-#{x_distance})\">\n#{trident}</g>"
176
- final_svg << "<g transform=\"translate(#{x_distance})\">\n#{trident}</g>"
177
- elsif [:s, :d, :stf, :n].include?(flag_details[:type]) && %w[LT DLT].include?(rank)
178
- # Swallowtail tridents need to move towards the hoist due to the tails
179
- x_distance = USPSFlags::Config::BASE_FLY/10 if field
180
- final_svg << "<g transform=\"translate(-#{x_distance})\">" if field
181
- final_svg << USPSFlags::Core.trident(flag_details[:type], field_color: flag_details[:color], color: :red)
182
- final_svg << "</g>" if field
183
- elsif [:s, :d, :stf, :n].include?(flag_details[:type])
184
- # All other tridents are centered on the field
185
- final_svg << USPSFlags::Core.trident(flag_details[:type], field_color: flag_details[:color])
186
- else
187
- # Special Flags
188
- # Paths were designed for a base fly of 3000 pixels, but the base was changed for more useful fractions.
189
- final_svg << "<g transform=\"translate(#{USPSFlags::Config::BASE_FLY/10})\">" unless field
190
- final_svg << "<g transform=\"scale(#{Rational(USPSFlags::Config::BASE_FLY,3000).to_f})\">"
191
- case flag_details[:type]
192
- when :a
193
- final_svg << USPSFlags::Core.binoculars(flag_details[:level])
194
- when :f
195
- final_svg << USPSFlags::Core.trumpet(flag_details[:level])
196
- when :fc
197
- final_svg << USPSFlags::Core.anchor
198
- when :pc
199
- final_svg << USPSFlags::Core.lighthouse
200
- end
201
- final_svg << "</g>"
202
- final_svg << "</g>" unless field
203
- end
204
-
205
- final_svg << "</g></g>" if flag_details[:style] == :past
206
-
207
- final_svg << USPSFlags::Core.footer
208
-
209
- if outfile.nil?
210
- puts final_svg, "\n"
211
- elsif outfile != ""
212
- f = ::File.new(outfile, "w+")
213
- f.write(final_svg)
214
- f.close
215
- end
216
- final_svg
217
- end
218
-
219
- def pennant(type: "CRUISE", outfile: nil, scale: nil)
220
- type = type.upcase
221
- final_svg = ""
222
- title = case type
223
- when "CRUISE"
224
- "Cruise Pennant"
225
- when "OIC"
226
- "Officer-in-Charge Pennant"
227
- end
228
- final_svg << USPSFlags::Core.headers(pennant: true, scale: scale, title: title)
229
- final_svg << USPSFlags::Core.pennant(type)
230
- final_svg << USPSFlags::Core.footer
231
-
232
- if outfile.nil?
233
- puts final_svg, "\n"
234
- elsif outfile != ""
235
- f = ::File.new(outfile, "w+")
236
- f.write(final_svg)
237
- f.close
238
- end
239
- final_svg
240
- end
241
-
242
- def ensign(outfile: nil, scale: nil)
243
- final_svg = ""
244
- final_svg << USPSFlags::Core.headers(scale: scale, title: "USPS Ensign")
245
- final_svg << USPSFlags::Core.ensign
246
- final_svg << USPSFlags::Core.footer
247
-
248
- if outfile.nil?
249
- puts final_svg, "\n"
250
- elsif outfile != ""
251
- f = ::File.new(outfile, "w+")
252
- f.write(final_svg)
253
- f.close
254
- end
255
- final_svg
256
- end
257
-
258
- def wheel(outfile: nil, scale: nil)
259
- width = 4327.4667
260
- height = 4286.9333
261
- final_svg = ""
262
- final_svg << USPSFlags::Core.headers(width: width, height: height, scale: scale, title: "USPS Ensign Wheel")
263
- final_svg << USPSFlags::Core.wheel
264
- final_svg << USPSFlags::Core.footer
265
-
266
- if outfile.nil?
267
- puts final_svg, "\n"
268
- elsif outfile != ""
269
- f = ::File.new(outfile, "w+")
270
- f.write(final_svg)
271
- f.close
272
- end
273
- final_svg
274
- end
275
-
276
- def us(outfile: nil, scale: nil)
277
- base_hoist = 2000.to_f
278
- base_fly = base_hoist * 1.91
279
- hoist = scale.nil? ? base_hoist : (base_hoist / scale)
280
- fly = hoist * 1.91
281
- final_svg = ""
282
- final_svg << USPSFlags::Core.headers(width: fly, height: hoist, scale: scale, title: "US Ensign")
283
- final_svg << USPSFlags::Core.us
284
- final_svg << USPSFlags::Core.footer
285
-
286
- if outfile.nil?
287
- puts final_svg, "\n"
288
- elsif outfile != ""
289
- f = ::File.new(outfile, "w+")
290
- f.write(final_svg)
291
- f.close
292
- end
293
- final_svg
294
- end
295
-
296
124
  def remove_static_files
297
125
  ["SVG", "PNG", "ZIP"].each { |dir| ::FileUtils.rm_rf(Dir.glob("#{USPSFlags::Config.flags_dir}/#{dir}/*")) }
298
126
  ["SVG/insignia", "PNG/insignia"].each { |dir| ::FileUtils.mkdir_p("#{USPSFlags::Config.flags_dir}/#{dir}") }
299
127
  USPSFlags::Helpers.log "\n - Cleared previous files.\n"
300
128
  end
301
129
 
302
- def get_file_paths(flag)
303
- svg_file = "#{USPSFlags::Config.flags_dir}/SVG/#{flag}.svg"
304
- png_file = svg_file.gsub("/SVG/", "/PNG/").gsub(".svg", ".png")
305
- svg_ins_file = svg_file.gsub("/SVG/", "/SVG/insignia/")
306
- png_ins_file = png_file.gsub("/PNG/", "/PNG/insignia/")
130
+ def set_file_paths(flag)
131
+ @svg_file = "#{USPSFlags::Config.flags_dir}/SVG/#{flag}.svg"
132
+ @png_file = @svg_file.gsub("/SVG/", "/PNG/").gsub(".svg", ".png")
133
+ @svg_ins_file = @svg_file.gsub("/SVG/", "/SVG/insignia/")
134
+ @png_ins_file = @svg_file.gsub("/SVG/", "/PNG/insignia/").gsub(".svg", ".png")
135
+ [@svg_file, @png_file, @svg_ins_file, @png_ins_file]
307
136
  end
308
137
 
309
138
  def generate_static_images_for(flag, svg: true, png: true)
310
139
  start_time = Time.now
311
- USPSFlags::Helpers.log " | | _ _ _ _ _ | \r".rjust(max_length+31, " ")
140
+ USPSFlags::Helpers.log " | | _ _ _ _ _ | \r".rjust(USPSFlags::Helpers.max_flag_name_length+31, " ")
312
141
  flag = flag.upcase
313
- USPSFlags::Helpers.log "#{flag.rjust(max_length)} |"
142
+ USPSFlags::Helpers.log "#{flag.rjust(USPSFlags::Helpers.max_flag_name_length)} |"
314
143
 
315
- svg_file, png_file, svg_ins_file, png_ins_file = get_file_paths(flag)
316
-
317
- past = (flag[0] == "P" && flag != "PORTCAP")
144
+ set_file_paths(flag)
318
145
 
319
146
  if svg
320
- generate_static_svg(flag, svg_file)
147
+ generate_static_svg(flag)
321
148
  else
322
149
  USPSFlags::Helpers.log "-"
323
150
  end
324
151
 
325
152
  if png
326
- generate_static_png(flag, png_file)
153
+ generate_static_png(flag)
327
154
  else
328
155
  USPSFlags::Helpers.log "- "
329
156
  end
157
+
330
158
  run_time = (Time.now - start_time).round(4).to_s[(0..5)].ljust(6, "0")
331
159
  USPSFlags::Helpers.log " | #{run_time} s\n"
332
160
  end
333
161
 
334
162
  def generate_static_svg(flag)
335
- svg_file, png_file, svg_ins_file, png_ins_file = get_file_paths(flag)
336
163
  begin
337
164
  USPSFlags::Helpers.log " "
338
- get flag, outfile: svg_file, scale: 1
165
+ svg flag, outfile: @svg_file, scale: 1
339
166
  USPSFlags::Helpers.log "S"
340
- if past || !USPSFlags::Helpers.valid_flags(:insignia).include?(flag)
167
+ if USPSFlags::Helpers.valid_flags(:past).include?(flag) || !USPSFlags::Helpers.valid_flags(:insignia).include?(flag)
341
168
  USPSFlags::Helpers.log "-"
342
169
  else
343
- get flag, field: false, outfile: svg_ins_file, scale: 1
170
+ svg flag, field: false, outfile: @svg_ins_file, scale: 1
344
171
  USPSFlags::Helpers.log "I"
345
172
  end
346
173
  rescue => e
@@ -349,38 +176,35 @@ class USPSFlags::Generate
349
176
  end
350
177
 
351
178
  def generate_static_png(flag)
352
- svg_file, png_file, svg_ins_file, png_ins_file = get_file_paths(flag)
353
179
  USPSFlags::Helpers.log " | "
354
180
  begin
355
181
  USPSFlags::Helpers.log "…\b"
356
- png(File.read(svg_file), outfile: png_file) unless ::File.exist?(png_file)
182
+ png(File.read(@svg_file), outfile: @png_file) unless ::File.exist?(@png_file)
357
183
  USPSFlags::Helpers.log "F"
358
- if past || !insignia_flags.include?(flag)
184
+ if USPSFlags::Helpers.valid_flags(:past).include?(flag) || !USPSFlags::Helpers.valid_flags(:insignia).include?(flag)
359
185
  USPSFlags::Helpers.log "-"
360
186
  else
361
187
  USPSFlags::Helpers.log "…\b"
362
- png(File.read(svg_ins_file), outfile: png_ins_file, trim: true) unless ::File.exist?(png_ins_file)
188
+ png(File.read(@svg_ins_file), outfile: @png_ins_file, trim: true) unless ::File.exist?(@png_ins_file)
363
189
  USPSFlags::Helpers.log "I"
364
190
  end
365
191
  USPSFlags::Helpers.png_sizes.keys.each do |size|
366
- if ::File.exist?("#{USPSFlags::Config.flags_dir}/PNG/#{flag}.#{size}.png")
192
+ USPSFlags::Helpers.log(".") and next if ::File.exist?("#{USPSFlags::Config.flags_dir}/PNG/#{flag}.#{size}.png")
193
+
194
+ USPSFlags::Helpers.log "…\b"
195
+ size, size_key = USPSFlags::Helpers.size_and_key(size: size, flag: flag)
196
+ USPSFlags::Helpers.resize_png(@png_ins_file, flag: flag, size: size, size_key: size_key) if USPSFlags::Helpers.valid_flags(:insignia).include?(flag)
197
+ USPSFlags::Helpers.log USPSFlags::Helpers.png_sizes[size_key]
198
+ if ::File.exist?(@png_ins_file) && ::File.exist?("#{USPSFlags::Config.flags_dir}/PNG/insignia/#{flag}.#{size}.png")
367
199
  USPSFlags::Helpers.log "."
368
- else
200
+ elsif ::File.exist?(@png_ins_file) && MiniMagick::Image.open(@png_ins_file)[:width] > size && USPSFlags::Helpers.valid_flags(:insignia).include?(flag)
369
201
  USPSFlags::Helpers.log "…\b"
370
- size, size_key = USPSFlags::Helpers.size_and_key(size: size, flag: flag)
371
- USPSFlags::Helpers.resize_png(png_ins_file, flag: flag, size: size, size_key: size_key)
372
- USPSFlags::Helpers.log USPSFlags::Helpers.png_sizes[size_key]
373
- if ::File.exist?(png_ins_file) && ::File.exist?("#{USPSFlags::Config.flags_dir}/PNG/insignia/#{flag}.#{size}.png")
374
- USPSFlags::Helpers.log "."
375
- elsif ::File.exist?(png_ins_file) && MiniMagick::Image.open(png_ins_file)[:width] > size
376
- USPSFlags::Helpers.log "…\b"
377
- USPSFlags::Helpers.resize_png(png_ins_file, flag: flag, size: size, size_key: size_key)
378
- USPSFlags::Helpers.log "i"
379
- elsif ::File.exist?(png_ins_file)
380
- USPSFlags::Helpers.log "+"
381
- else
382
- USPSFlags::Helpers.log "-"
383
- end
202
+ USPSFlags::Helpers.resize_png(@png_ins_file, flag: flag, size: size, size_key: size_key)
203
+ USPSFlags::Helpers.log "i"
204
+ elsif ::File.exist?(@png_ins_file)
205
+ USPSFlags::Helpers.log "+"
206
+ else
207
+ USPSFlags::Helpers.log "-"
384
208
  end
385
209
  end
386
210
  rescue => e
@@ -0,0 +1,71 @@
1
+ # SVG building helpers.
2
+ #
3
+ # These methods should never need to be called directly, except when designing new flags.
4
+ # @private
5
+ class USPSFlags::Helpers::Builders
6
+ class << self
7
+ # Displays an overlay grid with regularly spaced locator markers.
8
+ #
9
+ # This is useful for adjusting or creating new SVG data generators, but should not otherwise need to be called.
10
+ # @private
11
+ def grid(width: USPSFlags::Config::BASE_FLY, height: USPSFlags::Config::BASE_HOIST)
12
+ <<~SVG
13
+ <circle cx="0" cy="0" r="#{width/60}" fill="#000000" fill-opacity="0.4" />
14
+ <circle cx="#{width}" cy="0" r="#{width/60}" fill="#000000" fill-opacity="0.4" />
15
+ <circle cx="#{width}" cy="#{height}" r="#{width/60}" fill="#000000" fill-opacity="0.4" />
16
+ <circle cx="0" cy="#{height}" r="#{width/60}" fill="#000000" fill-opacity="0.4" />
17
+
18
+ <circle cx="#{width*1/4}" cy="#{height/2}" r="#{width/60}" fill="#999999" fill-opacity="0.4" />
19
+ <circle cx="#{width*3/4}" cy="#{height/2}" r="#{width/60}" fill="#999999" fill-opacity="0.4" />
20
+
21
+ <circle cx="#{width/2}" cy="#{height*1/4}" r="#{width/60}" fill="#999999" fill-opacity="0.4" />
22
+ <circle cx="#{width/2}" cy="#{height/2}" r="#{width/60}" fill="#000000" fill-opacity="0.4" />
23
+ <circle cx="#{width/2}" cy="#{height/2}" r="#{width/75}" fill="#CCCCCC" fill-opacity="0.4" />
24
+ <circle cx="#{width/2}" cy="#{height/2}" r="#{width/100}" fill="#000000" fill-opacity="0.4" />
25
+ <circle cx="#{width/2}" cy="#{height*3/4}" r="#{width/60}" fill="#999999" fill-opacity="0.4" />
26
+
27
+ <line x1="0" y1="0" x2="#{width}" y2="0" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
28
+ <line x1="0" y1="#{height*1/4}" x2="#{width}" y2="#{height*1/4}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
29
+ <line x1="0" y1="#{height/2}" x2="#{width}" y2="#{height/2}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
30
+ <line x1="0" y1="#{height*3/4}" x2="#{width}" y2="#{height*3/4}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
31
+ <line x1="0" y1="#{height}" x2="#{width}" y2="#{height}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
32
+
33
+ <line y1="0" x1="0" y2="#{height}" x2="0" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
34
+ <line y1="0" x1="#{width*1/6}" y2="#{height}" x2="#{width*1/6}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
35
+ <line y1="0" x1="#{width*2/6}" y2="#{height}" x2="#{width*2/6}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
36
+ <line y1="0" x1="#{width*3/6}" y2="#{height}" x2="#{width*3/6}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
37
+ <line y1="0" x1="#{width*4/6}" y2="#{height}" x2="#{width*4/6}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
38
+ <line y1="0" x1="#{width*5/6}" y2="#{height}" x2="#{width*5/6}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
39
+ <line y1="0" x1="#{width}" y2="#{height}" x2="#{width}" stroke="#333333" stroke-width="#{width/600}" stroke-opacity="0.5" />
40
+
41
+ <line x1="#{width/2}" y1="#{height*1/4}" x2="#{width*3/4}" y2="#{height/2}" stroke="#999999" stroke-width="#{width/600}" stroke-opacity="0.5" />
42
+ <line x1="#{width*3/4}" y1="#{height/2}" x2="#{width/2}" y2="#{height*3/4}" stroke="#999999" stroke-width="#{width/600}" stroke-opacity="0.5" />
43
+ <line x1="#{width/2}" y1="#{height*3/4}" x2="#{width*1/4}" y2="#{height/2}" stroke="#999999" stroke-width="#{width/600}" stroke-opacity="0.5" />
44
+ <line x1="#{width*1/4}" y1="#{height/2}" x2="#{width/2}" y2="#{height*1/4}" stroke="#999999" stroke-width="#{width/600}" stroke-opacity="0.5" />
45
+
46
+ SVG
47
+ end
48
+
49
+ # Displays an overlay indicator of concentric circles and radiating lines.
50
+ #
51
+ # This is useful for adjusting or creating new SVG data generators, but should not otherwise need to be called.
52
+ # @private
53
+ def locator
54
+ <<~SVG
55
+ <circle cx="0" cy="0" r="#{USPSFlags::Config::BASE_FLY*2}" fill="#000000" fill-opacity="0.4" />
56
+ <circle cx="0" cy="0" r="#{USPSFlags::Config::BASE_FLY}" fill="#333333" fill-opacity="0.4" />
57
+ <circle cx="0" cy="0" r="#{USPSFlags::Config::BASE_FLY/2}" fill="#666666" fill-opacity="0.4" />
58
+ <circle cx="0" cy="0" r="#{USPSFlags::Config::BASE_FLY/4}" fill="#999999" fill-opacity="0.4" />
59
+ <circle cx="0" cy="0" r="#{USPSFlags::Config::BASE_FLY/8}" fill="#CCCCCC" fill-opacity="0.4" />
60
+ <circle cx="0" cy="0" r="#{USPSFlags::Config::BASE_FLY/16}" fill="#FFFFFF" fill-opacity="0.4" />
61
+
62
+ <line x1="-#{USPSFlags::Config::BASE_FLY}" y1="-#{USPSFlags::Config::BASE_HOIST}" x2="#{USPSFlags::Config::BASE_FLY}" y2="#{USPSFlags::Config::BASE_HOIST}" stroke="#FFFFFF" stroke-width="#{USPSFlags::Config::BASE_FLY/600}" />
63
+ <line x1="-#{USPSFlags::Config::BASE_FLY}" y1="#{USPSFlags::Config::BASE_HOIST}" x2="#{USPSFlags::Config::BASE_FLY}" y2="-#{USPSFlags::Config::BASE_HOIST}" stroke="#FFFFFF" stroke-width="#{USPSFlags::Config::BASE_FLY/600}" />
64
+ <line x1="0" y1="#{USPSFlags::Config::BASE_HOIST}" x2="0" y2="-#{USPSFlags::Config::BASE_HOIST}" stroke="#FFFFFF" stroke-width="#{USPSFlags::Config::BASE_FLY/600}" />
65
+ <line x1="-#{USPSFlags::Config::BASE_FLY}" y1="0" x2="#{USPSFlags::Config::BASE_FLY}" y2="0" stroke="#FFFFFF" stroke-width="#{USPSFlags::Config::BASE_FLY/600}" />
66
+
67
+ <rect x="0" y="0" width="#{USPSFlags::Config::BASE_FLY/30}" height="#{USPSFlags::Config::BASE_FLY/30}" fill="#333333" fill-opacity="0.6" />
68
+ SVG
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,81 @@
1
+ # Trident specification sheet arrows.
2
+ #
3
+ # These methods should never need to be called directly.
4
+ # @private
5
+ class USPSFlags::Helpers::SpecArrows
6
+ class << self
7
+ # Creates a vertical arrow for the trident spec sheet.
8
+ #
9
+ # This is used USPSFlags::Core.trident_spec, and should never need to be called directly.
10
+ # @private
11
+ def vertical(x, top, bottom, pointer_top = nil, pointer_bottom = nil, label: nil, label_offset: (USPSFlags::Config::BASE_FLY/120), label_offset_y: 0, label_align: "left", color: "#CCCCCC", stroke_width: (USPSFlags::Config::BASE_FLY/600), stroke_dash: "10, 10", font_size: (USPSFlags::Config::BASE_FLY/60), arrow_size: (USPSFlags::Config::BASE_FLY/120), fly: USPSFlags::Config::BASE_FLY, unit: nil)
12
+ label = bottom - top if label.nil?
13
+ label = label.to_i if label - label.to_i == 0
14
+ label = Rational(label) * fly / USPSFlags::Config::BASE_FLY
15
+ if label == label.to_i
16
+ label = label.to_i
17
+ label_fraction = ""
18
+ else
19
+ label, label_fraction = label.to_simplified_a
20
+ end
21
+ svg = ""
22
+ unless pointer_top.nil?
23
+ svg << <<~SVG
24
+ <line x1="#{x}" y1="#{top}" x2="#{pointer_top}" y2="#{top}" stroke="#{color}" stroke-width="#{stroke_width}" stroke-dasharray="#{stroke_dash}" />
25
+ SVG
26
+ end
27
+ unless pointer_bottom.nil?
28
+ svg << <<~SVG
29
+ <line x1="#{x}" y1="#{bottom}" x2="#{pointer_bottom}" y2="#{bottom}" stroke="#{color}" stroke-width="#{stroke_width}" stroke-dasharray="#{stroke_dash}" />
30
+ SVG
31
+ end
32
+
33
+ svg << <<~SVG
34
+ <path d="M#{x} #{top} l #{arrow_size} #{arrow_size} M#{x} #{top} l -#{arrow_size} #{arrow_size} M#{x} #{top} l 0 #{bottom - top} l #{arrow_size} -#{arrow_size} M#{x} #{bottom} l -#{arrow_size} -#{arrow_size}" stroke="#{color}" stroke-width="#{stroke_width}" fill="none" />
35
+ <g>
36
+ <style><![CDATA[tspan{font-size: #{USPSFlags::Config::FRACTION_SCALE}%;}]]></style>
37
+ <text x="#{x + label_offset}" y="#{(top+bottom)/2+(USPSFlags::Config::BASE_HOIST/150)+label_offset_y}" font-family="sans-serif" font-size="#{font_size}px" fill="#041E42" text-anchor="#{label_align}">#{label} <tspan>#{label_fraction}</tspan> #{unit}</text>
38
+ </g>
39
+ SVG
40
+
41
+ svg
42
+ end
43
+
44
+ # Creates a horizontal arrow for the trident spec sheet.
45
+ #
46
+ # This is used USPSFlags::Core.trident_spec, and should never need to be called directly.
47
+ # @private
48
+ def horizontal(y, left, right, pointer_left = nil, pointer_right = nil, label: nil, label_offset: (USPSFlags::Config::BASE_FLY/45), label_offset_x: 0, label_align: "middle", color: "#CCCCCC", stroke_width: (USPSFlags::Config::BASE_FLY/600), stroke_dash: "10, 10", font_size: (USPSFlags::Config::BASE_FLY/60), arrow_size: (USPSFlags::Config::BASE_FLY/120), fly: USPSFlags::Config::BASE_FLY, unit: nil)
49
+ label = right - left if label.nil?
50
+ label = label.to_i if label - label.to_i == 0
51
+ label = Rational(label) * fly / USPSFlags::Config::BASE_FLY
52
+ if label == label.to_i
53
+ label = label.to_i
54
+ label_fraction = ""
55
+ else
56
+ label, label_fraction = label.to_simplified_a
57
+ end
58
+ svg = ""
59
+ unless pointer_left.nil?
60
+ svg << <<~SVG
61
+ <line x1="#{left}" y1="#{y}" x2="#{left}" y2="#{pointer_left}" stroke="#{color}" stroke-width="#{stroke_width}" stroke-dasharray="#{stroke_dash}" />
62
+ SVG
63
+ end
64
+ unless pointer_right.nil?
65
+ svg << <<~SVG
66
+ <line x1="#{right}" y1="#{y}" x2="#{right}" y2="#{pointer_right}" stroke="#{color}" stroke-width="#{stroke_width}" stroke-dasharray="#{stroke_dash}" />
67
+ SVG
68
+ end
69
+
70
+ svg << <<~SVG
71
+ <path d="M#{left} #{y} l #{arrow_size} #{arrow_size} M#{left} #{y} l #{arrow_size} -#{arrow_size} M#{left} #{y} l #{right - left} 0 l -#{arrow_size} -#{arrow_size} M#{right} #{y} l -#{arrow_size} #{arrow_size}" stroke="#{color}" stroke-width="#{stroke_width}" fill="none" />
72
+ <g>
73
+ <style><![CDATA[tspan{font-size: #{USPSFlags::Config::FRACTION_SCALE}%;}]]></style>
74
+ <text x="#{(left+right)/2+label_offset_x}" y="#{y + label_offset}" font-family="sans-serif" font-size="#{font_size}px" fill="#041E42" text-anchor="#{label_align}">#{label} <tspan>#{label_fraction}</tspan> #{unit}</text>
75
+ </g>
76
+ SVG
77
+
78
+ svg
79
+ end
80
+ end
81
+ end