laser-cutter 0.5.0 → 0.5.1
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.
- checksums.yaml +4 -4
- data/README.md +45 -21
- data/bin/laser-cutter +26 -18
- data/lib/laser-cutter.rb +1 -0
- data/lib/laser-cutter/configuration.rb +1 -38
- data/lib/laser-cutter/page_manager.rb +43 -0
- data/lib/laser-cutter/renderer.rb +3 -8
- data/lib/laser-cutter/renderer/base.rb +27 -0
- data/lib/laser-cutter/renderer/box_renderer.rb +12 -78
- data/lib/laser-cutter/renderer/layout_renderer.rb +40 -0
- data/lib/laser-cutter/renderer/line_renderer.rb +4 -1
- data/lib/laser-cutter/renderer/meta_renderer.rb +77 -0
- data/lib/laser-cutter/renderer/rect_renderer.rb +2 -3
- data/lib/laser-cutter/version.rb +1 -1
- data/spec/configuration_spec.rb +2 -36
- data/spec/page_manager_spec.rb +45 -0
- data/spec/renderer_spec.rb +8 -5
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 06711815bb7563755b270427de4acb6dc2208777
|
4
|
+
data.tar.gz: 8daa7da0e30ed501f04b5786cf0b31c8b62ec823
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 267e0cc220e9e83a0f8a8570429d3f11207d677b5d876831544ac33871fef9ce14daaab7f2594784d4d0a6da1e5161e8299d205d177543a3408ad3ccec42a2b5
|
7
|
+
data.tar.gz: f5c49c5f68fc71df0e84af028086f9a231cf9abfd42c07350bdfc175f3df31bf40469032c30c33ca49a000f5e82764d1e5788db5d42c90de65e6ed91936e71d9
|
data/README.md
CHANGED
@@ -18,7 +18,14 @@ command line options, and perhaps a light weight web application. If you are in
|
|
18
18
|
contributing to the project, please see [contributing](CONTRIBUTING.md) for more details.
|
19
19
|
|
20
20
|
```laser-cutter``` supports many flexible command line options that allow setting dimensions,
|
21
|
-
stroke width, page size, layout, margins, padding (spacing between the boxes), and many more.
|
21
|
+
stroke width, page size, layout, margins, padding (spacing between the boxes), and many more.
|
22
|
+
|
23
|
+
## Web Front-End
|
24
|
+
|
25
|
+
There is a web online application that uses this gem and allows you to generate PDFs with
|
26
|
+
a friendly UI.
|
27
|
+
|
28
|
+
Please visit [http://makeabox.io](http://makeabox.io).
|
22
29
|
|
23
30
|
## Dependencies
|
24
31
|
|
@@ -42,25 +49,24 @@ Or install it yourself as:
|
|
42
49
|
|
43
50
|
```bash
|
44
51
|
Usage: laser-cutter [options] -o filename.pdf
|
45
|
-
eg: laser-cutter -
|
52
|
+
eg: laser-cutter -s 1x1.5x2/0.125/0.125 -O -o box.pdf
|
46
53
|
|
47
54
|
Specific Options:
|
48
|
-
|
55
|
+
-w, --width WIDTH Internal width of the box
|
49
56
|
-h, --height HEIGHT Internal height of the box
|
50
57
|
-d, --depth DEPTH Internal depth of the box
|
51
|
-
|
58
|
+
-t, --thickness THICKNESS Thickness of the box material
|
52
59
|
-n, --notch NOTCH Preferred notch length (used only as a guide)
|
53
60
|
|
54
61
|
-m, --margin MARGIN Margins from the edge of the document
|
55
62
|
-p, --padding PADDING Space between the boxes on the page
|
56
|
-
-
|
63
|
+
-k, --stroke WIDTH Numeric stroke width of the line
|
57
64
|
-z, --page_size LETTER Page size, see --list-all-page-sizes for more info.
|
58
65
|
-y, --page_layout portrait Page layout, other option is 'landscape'
|
59
66
|
|
60
67
|
-O, --open Open generated file with system viewer before exiting
|
61
|
-
-
|
62
|
-
-
|
63
|
-
-u, --units UNITS Either 'mm' (default) or 'in'
|
68
|
+
-W, --write FILE Save provided configuration to a file, use '-' for STDOUT
|
69
|
+
-R, --read FILE Read configuration from a file, or use '-' for STDIN
|
64
70
|
|
65
71
|
-l, --list-all-page-sizes Print all available page sizes with dimensions and exit
|
66
72
|
-M, --no-metadata Do not print box metadata on the PDF
|
@@ -75,24 +81,43 @@ Common Options:
|
|
75
81
|
-s, --size WxHxD/T/N Combined internal dimensions: W = width, H = height,
|
76
82
|
D = depth, T = thickness, N = notch length
|
77
83
|
|
78
|
-
-
|
84
|
+
-u, --units UNITS Either 'in' for inches (default) or 'mm'
|
85
|
+
```
|
86
|
+
|
87
|
+
### Examples
|
79
88
|
|
80
|
-
|
81
|
-
1. Create a box defined in inches, and open PDF in preview right after:
|
89
|
+
Create a box defined in inches, and open PDF in preview right after:
|
82
90
|
|
83
|
-
|
91
|
+
```bash
|
92
|
+
laser-cutter -s 3x2x2/0.125/0.5 -O -o box.pdf
|
93
|
+
```
|
84
94
|
|
85
|
-
|
86
|
-
|
95
|
+
Create a box defined in millimeters, print verbose info, and set
|
96
|
+
page size to A3, and layout to landscape, and stroke width to 1/2mm:
|
87
97
|
|
88
|
-
|
98
|
+
```bash
|
99
|
+
laser-cutter -u mm -w70 -h20 -d50 -t4.3 -n5 -zA3 -y landscape -k0.5 -v -O -o box.pdf
|
100
|
+
```
|
89
101
|
|
90
|
-
|
102
|
+
List all possible page sizes in metric system:
|
91
103
|
|
92
|
-
|
93
|
-
|
104
|
+
```bash
|
105
|
+
laser-cutter -l -u mm
|
94
106
|
```
|
95
107
|
|
108
|
+
Create a box with provided dimensions, and save the config to a file for later use:
|
109
|
+
|
110
|
+
```bash
|
111
|
+
laser-cutter -s 1.1x2.5x1.5/0.125/0.125 -p 0.1 -O -o box.pdf -W box-settings.json
|
112
|
+
```
|
113
|
+
|
114
|
+
Read settings from a previously saved file:
|
115
|
+
|
116
|
+
```bash
|
117
|
+
laser-cutter -O -o box.pdf -R box-settings.json
|
118
|
+
cat box-settings.json | laser-cutter -O -o box.pdf -R -
|
119
|
+
```
|
120
|
+
|
96
121
|
## Future Features
|
97
122
|
|
98
123
|
* Extensibility with various layout strategies, notch drawing strategies, basically plug and play
|
@@ -100,7 +125,6 @@ Examples:
|
|
100
125
|
* Support more shapes than just box
|
101
126
|
* Create T-style joins, using various standard sizes of nuts and bolts (such as common #4-40 and M2 sizes)
|
102
127
|
* Supporting lids and front panels, that are larger than the box itself and have holes for notches.
|
103
|
-
* A web-app that uses the gem and renders box live in CSS using CSS 2D to show preview.
|
104
128
|
* Your brilliant idea can be here too! Please see [contributing](CONTRIBUTING.md) for more info.
|
105
129
|
|
106
130
|
## Comparison with BoxMaker
|
@@ -137,14 +161,14 @@ niceties):
|
|
137
161
|
```bash
|
138
162
|
git clone https://github.com/aphelps/boxmaker && cd boxmaker && ant
|
139
163
|
java -cp BOX.jar com.rahulbotics.boxmaker.BoxMaker \
|
140
|
-
-
|
164
|
+
-W 1 -H 2 -D 1.5 -T 0.125 -n 0.125 -o box.pdf
|
141
165
|
```
|
142
166
|
|
143
167
|
And laser-cutter:
|
144
168
|
|
145
169
|
```bash
|
146
170
|
gem install laser-cutter
|
147
|
-
laser-cutter -
|
171
|
+
laser-cutter -s 1x1.5x2/0.125/0.125 -O -o box.pdf
|
148
172
|
```
|
149
173
|
|
150
174
|
.
|
data/bin/laser-cutter
CHANGED
@@ -18,7 +18,7 @@ module Laser
|
|
18
18
|
#{('Laser-Cutter v'+ Laser::Cutter::VERSION).bold}
|
19
19
|
|
20
20
|
Usage: laser-cutter [options] -o filename.pdf
|
21
|
-
eg: laser-cutter -
|
21
|
+
eg: laser-cutter -s 1x1.5x2/0.125/0.125 -O -o box.pdf
|
22
22
|
EOF
|
23
23
|
|
24
24
|
examples = <<-EOF
|
@@ -26,21 +26,31 @@ Usage: laser-cutter [options] -o filename.pdf
|
|
26
26
|
Examples:
|
27
27
|
1. Create a box defined in inches, and open PDF in preview right after:
|
28
28
|
|
29
|
-
laser-cutter -
|
29
|
+
laser-cutter -s 3x2x2/0.125/0.5 -O -o box.pdf
|
30
30
|
|
31
|
-
2. Create a box defined in millimeters, print verbose info and set
|
31
|
+
2. Create a box defined in millimeters, print verbose info, and set
|
32
32
|
page size to A3, and layout to landscape, and stroke width to 1/2mm:
|
33
33
|
|
34
|
-
laser-cutter -w70 -h20 -d50 -t4.3 -n5 -
|
34
|
+
laser-cutter -u mm -w70 -h20 -d50 -t4.3 -n5 -zA3 -y landscape -k0.5 -v -O -o box.pdf
|
35
35
|
|
36
|
-
3. List all possible page sizes in metric
|
36
|
+
3. List all possible page sizes in metric systems:
|
37
|
+
|
38
|
+
laser-cutter -l -u mm
|
39
|
+
|
40
|
+
4. Create a box with provided dimensions, and save the config to a file
|
41
|
+
for later use:
|
42
|
+
|
43
|
+
laser-cutter -s 1.1x2.5x1.5/0.125/0.125 -p 0.1 -O -o box.pdf -W box-settings.json
|
44
|
+
|
45
|
+
5. Read settings from a previously saved file:
|
46
|
+
|
47
|
+
laser-cutter -O -o box.pdf -R box-settings.json
|
48
|
+
cat box-settings.json | laser-cutter -O -o box.pdf -R -
|
37
49
|
|
38
|
-
laser-cutter --list-all-page-sizes
|
39
|
-
laser-cutter --list-all-page-sizes --inches
|
40
50
|
EOF
|
41
51
|
options = Hashie::Mash.new
|
42
52
|
options.verbose = false
|
43
|
-
options.units = '
|
53
|
+
options.units = 'in'
|
44
54
|
|
45
55
|
opt_parser = OptionParser.new do |opts|
|
46
56
|
opts.banner = banner_text.blue
|
@@ -53,14 +63,13 @@ Examples:
|
|
53
63
|
opts.separator ""
|
54
64
|
opts.on("-m", "--margin MARGIN", "Margins from the edge of the document") { |value| options.margin = value }
|
55
65
|
opts.on("-p", "--padding PADDING", "Space between the boxes on the page") { |value| options.padding = value }
|
56
|
-
opts.on("-
|
66
|
+
opts.on("-k", "--stroke WIDTH", "Numeric stroke width of the line") { |value| options.stroke = value }
|
57
67
|
opts.on("-z", "--page_size LETTER", "Page size, see --list-all-page-sizes for more info.") { |value| options.page_size = value }
|
58
68
|
opts.on("-y", "--page_layout portrait", "Page layout, other option is 'landscape' ") { |value| options.page_layout = value }
|
59
69
|
opts.separator ""
|
60
70
|
opts.on("-O", "--open", "Open generated file with system viewer before exiting") { |v| options.open = v }
|
61
|
-
opts.on("-
|
62
|
-
opts.on("-
|
63
|
-
opts.on("-u", "--units UNITS", "Either 'mm' (default) or 'in'") { |value| options.units = value }
|
71
|
+
opts.on("-W", "--write FILE", "Save provided configuration to a file, use '-' for STDOUT") { |v| options.write_file = v }
|
72
|
+
opts.on("-R", "--read FILE", "Read configuration from a file, or use '-' for STDIN") { |v| options.read_file = v }
|
64
73
|
opts.separator ""
|
65
74
|
opts.on("-l", "--list-all-page-sizes", "Print all available page sizes with dimensions and exit") { |v| options.list_all_page_sizes = true }
|
66
75
|
opts.on("-M", "--no-metadata", "Do not print box metadata on the PDF") { |value| options.metadata = value }
|
@@ -76,7 +85,7 @@ Examples:
|
|
76
85
|
"Combined internal dimensions: W = width, H = height,\n#{" " * 37}D = depth, T = thickness, N = notch length\n\n") do |size|
|
77
86
|
options.size = size
|
78
87
|
end
|
79
|
-
opts.on_tail("-
|
88
|
+
opts.on_tail("-u", "--units UNITS", "Either 'in' for inches (default) or 'mm'") { |value| options.units = value }
|
80
89
|
end
|
81
90
|
|
82
91
|
opt_parser.parse!(args)
|
@@ -87,7 +96,7 @@ Examples:
|
|
87
96
|
|
88
97
|
config = Laser::Cutter::Configuration.new(options.to_hash)
|
89
98
|
if config.list_all_page_sizes
|
90
|
-
puts config.all_page_sizes
|
99
|
+
puts PageManager.new(config.units).all_page_sizes
|
91
100
|
exit 0
|
92
101
|
end
|
93
102
|
|
@@ -150,14 +159,13 @@ end # class OptParse
|
|
150
159
|
config = Laser::Cutter::OptParse.parse(ARGV)
|
151
160
|
|
152
161
|
begin
|
153
|
-
Laser::Cutter::Renderer::
|
162
|
+
Laser::Cutter::Renderer::LayoutRenderer.new(config).render
|
154
163
|
if config.open
|
155
164
|
`open #{config.file}`
|
156
165
|
end
|
157
166
|
rescue Exception => e
|
158
|
-
|
159
|
-
if
|
160
|
-
STDERR.puts "Exception: #{e.inspect}".red
|
167
|
+
STDERR.puts "#{e.inspect}".red
|
168
|
+
if config.verbose
|
161
169
|
STDERR.puts e.backtrace.join("\n").red
|
162
170
|
end
|
163
171
|
end
|
data/lib/laser-cutter.rb
CHANGED
@@ -10,8 +10,7 @@ module Laser
|
|
10
10
|
end
|
11
11
|
class Configuration < Hashie::Mash
|
12
12
|
DEFAULTS = {
|
13
|
-
units: '
|
14
|
-
page_size: 'LETTER',
|
13
|
+
units: 'in',
|
15
14
|
page_layout: 'portrait',
|
16
15
|
metadata: true
|
17
16
|
}
|
@@ -64,42 +63,6 @@ module Laser
|
|
64
63
|
raise ZeroValueNotAllowed.new("#{zeros.join(', ')} #{zeros.size > 1 ? 'are' : 'is'} required, but is zero.") unless zeros.empty?
|
65
64
|
end
|
66
65
|
|
67
|
-
def page_size_values
|
68
|
-
h = PDF::Core::PageGeometry::SIZES
|
69
|
-
array = []
|
70
|
-
h.keys.sort.each do |k|
|
71
|
-
array << [k, value_from_units(h[k][0].to_f), value_from_units(h[k][1].to_f)]
|
72
|
-
end
|
73
|
-
array
|
74
|
-
end
|
75
|
-
|
76
|
-
# if from_units is nil, we expect it to be in dots per inch (default
|
77
|
-
# measurements for Prawn
|
78
|
-
def value_from_units value, from_units = nil
|
79
|
-
multiplier = if from_units.nil?
|
80
|
-
if units.eql?('in')
|
81
|
-
1.0 / 72.0 # PDF units per inch
|
82
|
-
else
|
83
|
-
25.4 * 1.0 / 72.0
|
84
|
-
end
|
85
|
-
elsif self.units.eql?(from_units)
|
86
|
-
1.0
|
87
|
-
elsif self.units.eql?('in') && from_units.eql?('mm')
|
88
|
-
(1.0 / 25.4)
|
89
|
-
else
|
90
|
-
25.4
|
91
|
-
end
|
92
|
-
value.to_f * multiplier
|
93
|
-
end
|
94
|
-
|
95
|
-
def all_page_sizes
|
96
|
-
output = ""
|
97
|
-
page_size_values.each do |k|
|
98
|
-
output << sprintf("\t%10s:\t%6.1f x %6.1f\n", *k)
|
99
|
-
end
|
100
|
-
output
|
101
|
-
end
|
102
|
-
|
103
66
|
def change_units(new_units)
|
104
67
|
return if (self.units.eql?(new_units) || !UNIT_SPECIFIC_DEFAULTS.keys.include?(new_units))
|
105
68
|
k = (self.units == 'in') ? 25.4 : 0.039370079
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'hashie/mash'
|
2
|
+
require 'prawn/measurement_extensions'
|
3
|
+
require 'pdf/core/page_geometry'
|
4
|
+
|
5
|
+
class Laser::Cutter::PageManager < Struct.new(:units)
|
6
|
+
SIZES = PDF::Core::PageGeometry::SIZES.clone.freeze
|
7
|
+
|
8
|
+
def all_page_sizes
|
9
|
+
output = ""
|
10
|
+
page_size_values.each do |k|
|
11
|
+
output << sprintf("\t%10s:\t%6.1f x %6.1f\n", *k)
|
12
|
+
end
|
13
|
+
output
|
14
|
+
end
|
15
|
+
|
16
|
+
# if from_units is nil, we expect it to be in dots per inch (default
|
17
|
+
# measurements for Prawn
|
18
|
+
def value_from_units value, from_units = nil
|
19
|
+
multiplier = if from_units.nil?
|
20
|
+
if units.eql?('in')
|
21
|
+
1.0 / 72.0 # PDF units per inch
|
22
|
+
else
|
23
|
+
25.4 * 1.0 / 72.0
|
24
|
+
end
|
25
|
+
elsif self.units.eql?(from_units)
|
26
|
+
1.0
|
27
|
+
elsif self.units.eql?('in') && from_units.eql?('mm')
|
28
|
+
(1.0 / 25.4)
|
29
|
+
else
|
30
|
+
25.4
|
31
|
+
end
|
32
|
+
value.to_f * multiplier
|
33
|
+
end
|
34
|
+
|
35
|
+
def page_size_values
|
36
|
+
h = SIZES
|
37
|
+
array = []
|
38
|
+
h.keys.sort.each do |k|
|
39
|
+
array << [k, value_from_units(h[k][0].to_f), value_from_units(h[k][1].to_f)]
|
40
|
+
end
|
41
|
+
array
|
42
|
+
end
|
43
|
+
end
|
@@ -1,19 +1,14 @@
|
|
1
1
|
module Laser
|
2
2
|
module Cutter
|
3
3
|
module Renderer
|
4
|
-
class AbstractRenderer < Struct.new(:subject, :options)
|
5
|
-
def render pdf = nil
|
6
|
-
raise 'Abstract method'
|
7
|
-
end
|
8
4
|
|
9
|
-
def units
|
10
|
-
options.units.to_sym || :mm
|
11
|
-
end
|
12
|
-
end
|
13
5
|
end
|
14
6
|
end
|
15
7
|
end
|
16
8
|
|
9
|
+
require 'laser-cutter/renderer/base'
|
17
10
|
require 'laser-cutter/renderer/line_renderer'
|
18
11
|
require 'laser-cutter/renderer/rect_renderer'
|
19
12
|
require 'laser-cutter/renderer/box_renderer'
|
13
|
+
require 'laser-cutter/renderer/meta_renderer'
|
14
|
+
require 'laser-cutter/renderer/layout_renderer'
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Laser
|
2
|
+
module Cutter
|
3
|
+
module Renderer
|
4
|
+
class Base
|
5
|
+
BLACK = "000000"
|
6
|
+
BLUE = "4090E0"
|
7
|
+
|
8
|
+
attr_accessor :config, :subject, :enclosure, :page_manager
|
9
|
+
|
10
|
+
def initialize(config, subject = nil)
|
11
|
+
self.config = config
|
12
|
+
self.subject = subject
|
13
|
+
self.page_manager = Laser::Cutter::PageManager.new(config.units)
|
14
|
+
end
|
15
|
+
|
16
|
+
def render
|
17
|
+
raise 'Abstract method'
|
18
|
+
end
|
19
|
+
|
20
|
+
def units
|
21
|
+
config.units.to_sym || :mm
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -3,96 +3,30 @@ require 'json'
|
|
3
3
|
module Laser
|
4
4
|
module Cutter
|
5
5
|
module Renderer
|
6
|
-
class BoxRenderer <
|
6
|
+
class BoxRenderer < Base
|
7
7
|
alias_method :box, :subject
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
self.options = options
|
13
|
-
self.subject = Laser::Cutter::Box.new(options)
|
9
|
+
def initialize(config)
|
10
|
+
super(config)
|
11
|
+
self.subject = Laser::Cutter::Box.new(config)
|
14
12
|
end
|
15
13
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
header = <<-EOF
|
21
|
-
|
22
|
-
Made with Laser Cutter Ruby Gem (v#{Laser::Cutter::VERSION})
|
23
|
-
Credits to Prawn for ruby PDF generation,
|
24
|
-
and BoxMaker for inspiration.
|
14
|
+
def ensure_space_for(rect)
|
15
|
+
coords = [ rect.p2.x, rect.p2.y ].map{|a| page_manager.value_from_units(a)}
|
16
|
+
box.metadata = Geometry::Point.new(coords)
|
17
|
+
end
|
25
18
|
|
26
|
-
Online: http://makeabox.io/
|
27
|
-
https://github.com/kigster/laser-cutter
|
28
|
-
EOF
|
29
19
|
|
20
|
+
def render pdf = nil
|
30
21
|
renderer = self
|
31
|
-
|
32
|
-
meta_color = "4090E0"
|
33
|
-
meta_top_height = 50
|
34
|
-
metadata = renderer.options.to_hash
|
35
|
-
metadata.delete_if { |k| %w(verbose metadata open file).include?(k) }
|
36
|
-
if options.metadata
|
37
|
-
coords = [ META_RECT.p2.x, META_RECT.p2.y ].map{|a| options.value_from_units(a)}
|
38
|
-
box.metadata = Geometry::Point.new(coords)
|
39
|
-
end
|
40
22
|
pdf.instance_eval do
|
41
|
-
self.line_width = renderer.
|
42
|
-
|
43
|
-
float do
|
44
|
-
bounding_box([0, META_RECT.h], :width => META_RECT.w, :height => META_RECT.h) do
|
45
|
-
stroke_color meta_color
|
46
|
-
stroke_bounds
|
47
|
-
indent 10 do
|
48
|
-
font('Helvetica', :size => 6) do
|
49
|
-
text header, :color => meta_color
|
50
|
-
end
|
51
|
-
end
|
52
|
-
float do
|
53
|
-
bounding_box([0, META_RECT.h - meta_top_height],
|
54
|
-
:width => META_RECT.w,
|
55
|
-
:height => META_RECT.h - meta_top_height) do
|
56
|
-
stroke_color meta_color
|
57
|
-
stroke_bounds
|
58
|
-
float do
|
59
|
-
bounding_box([0, META_RECT.h - meta_top_height], :width => 70, :height => META_RECT.h - meta_top_height) do
|
60
|
-
indent 10 do
|
61
|
-
font('Helvetica', :size => 6) do
|
62
|
-
out = JSON.pretty_generate(metadata).gsub(/[\{\}",]/, '').gsub(/:.*\n/x, "\n")
|
63
|
-
text out, :color => meta_color, align: :right
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
float do
|
69
|
-
bounding_box([60, META_RECT.h - meta_top_height], :width => 70, :height => META_RECT.h - meta_top_height) do
|
70
|
-
indent 10 do
|
71
|
-
font('Helvetica', :size => 6) do
|
72
|
-
out = JSON.pretty_generate(metadata).gsub(/[\{\}",]/, '').gsub(/\n?.*:/x, "\n:")
|
73
|
-
text out, :color => meta_color
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
stroke_color "000000"
|
23
|
+
self.line_width = renderer.config.stroke.send(renderer.config.units.to_sym)
|
24
|
+
stroke_color BLACK
|
84
25
|
renderer.box.notches.each do |notch|
|
85
|
-
LineRenderer.new(
|
26
|
+
LineRenderer.new(renderer.config, notch).render(self)
|
86
27
|
end
|
87
|
-
|
88
|
-
render_file(renderer.options.file)
|
89
|
-
end
|
90
|
-
|
91
|
-
if options.verbose
|
92
|
-
puts "file #{options.file} has been written."
|
93
28
|
end
|
94
29
|
end
|
95
|
-
|
96
30
|
end
|
97
31
|
end
|
98
32
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'json'
|
3
|
+
module Laser
|
4
|
+
module Cutter
|
5
|
+
module Renderer
|
6
|
+
class LayoutRenderer < Base
|
7
|
+
def initialize(config)
|
8
|
+
self.config = config
|
9
|
+
end
|
10
|
+
|
11
|
+
def render
|
12
|
+
renderer = self
|
13
|
+
|
14
|
+
meta_renderer = MetaRenderer.new(config)
|
15
|
+
box_renderer = BoxRenderer.new(config)
|
16
|
+
box_renderer.ensure_space_for(meta_renderer.enclosure) if config.metadata
|
17
|
+
|
18
|
+
page_size = config.page_size || 'LETTER' # TODO: auto-detect page size based on box dimensions.
|
19
|
+
|
20
|
+
pdf = Prawn::Document.new(:margin => config.margin.to_f.send(config.units.to_sym),
|
21
|
+
:page_size => page_size,
|
22
|
+
:page_layout => config.page_layout.to_sym)
|
23
|
+
|
24
|
+
pdf.instance_eval do
|
25
|
+
if renderer.config.metadata
|
26
|
+
meta_renderer.render(self)
|
27
|
+
end
|
28
|
+
box_renderer.render(self)
|
29
|
+
render_file(renderer.config.file)
|
30
|
+
end
|
31
|
+
|
32
|
+
if config.verbose
|
33
|
+
puts "PDF saved to #{config.file}."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
module Laser
|
2
2
|
module Cutter
|
3
3
|
module Renderer
|
4
|
-
class LineRenderer <
|
4
|
+
class LineRenderer < Base
|
5
5
|
alias_method :line, :subject
|
6
6
|
def render pdf = nil
|
7
7
|
pdf.stroke { pdf.line [line.p1.x, line.p1.y].map{ |p| p.send(units) },
|
8
8
|
[line.p2.x, line.p2.y].map{ |p| p.send(units) }}
|
9
|
+
end
|
9
10
|
|
11
|
+
def enclosure
|
12
|
+
self.line
|
10
13
|
end
|
11
14
|
end
|
12
15
|
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'json'
|
3
|
+
class Laser::Cutter::Renderer::MetaRenderer < Laser::Cutter::Renderer::Base
|
4
|
+
|
5
|
+
def initialize(config = {})
|
6
|
+
self.config = config
|
7
|
+
self.enclosure = Laser::Cutter::Geometry::Rect.create(Laser::Cutter::Geometry::Point[1, 1], 140, 150)
|
8
|
+
end
|
9
|
+
|
10
|
+
def render pdf = nil
|
11
|
+
banner = <<-EOF
|
12
|
+
|
13
|
+
Made with Laser Cutter Ruby Gem (v#{Laser::Cutter::VERSION})
|
14
|
+
Credits to Prawn for ruby PDF generation,
|
15
|
+
and BoxMaker for inspiration.
|
16
|
+
|
17
|
+
Online: http://makeabox.io/
|
18
|
+
Source: https://github.com/kigster/laser-cutter
|
19
|
+
EOF
|
20
|
+
|
21
|
+
meta_color = BLUE
|
22
|
+
meta_top_height = 50
|
23
|
+
|
24
|
+
metadata = config.to_hash
|
25
|
+
metadata.delete_if { |k| %w(verbose metadata open file).include?(k) }
|
26
|
+
|
27
|
+
rect = self.enclosure
|
28
|
+
|
29
|
+
pdf.instance_eval do
|
30
|
+
self.line_width = 0.5.mm
|
31
|
+
float do
|
32
|
+
bounding_box([rect.p1.x, rect.h + rect.p1.y], :width => rect.w, :height => rect.h) do
|
33
|
+
stroke_color meta_color
|
34
|
+
stroke_bounds
|
35
|
+
|
36
|
+
# Print banner
|
37
|
+
indent 10 do
|
38
|
+
font('Helvetica', :size => 6) do
|
39
|
+
text banner, :color => meta_color
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# print values of the config, in two parts – keys right aligned first,
|
44
|
+
# values left aligned second.
|
45
|
+
float do
|
46
|
+
# parse out meta keys and then values
|
47
|
+
meta_fields = JSON.pretty_generate(metadata).gsub(/[\{\}",]/, '').gsub(/:.*\n/x, "\n")
|
48
|
+
meta_values = JSON.pretty_generate(metadata).gsub(/[\{\}",]/, '').gsub(/\n?.*:/x, "\n:")
|
49
|
+
|
50
|
+
bounding_box([0, rect.h - meta_top_height],
|
51
|
+
:width => rect.w,
|
52
|
+
:height => rect.h - meta_top_height) do
|
53
|
+
float do
|
54
|
+
bounding_box([0, rect.h - meta_top_height], :width => 70, :height => rect.h - meta_top_height) do
|
55
|
+
indent 10 do
|
56
|
+
font('Helvetica', :size => 7) do
|
57
|
+
text meta_fields, :color => meta_color, align: :right
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
float do
|
63
|
+
bounding_box([60, rect.h - meta_top_height], :width => 70, :height => rect.h - meta_top_height) do
|
64
|
+
indent 10 do
|
65
|
+
font('Helvetica', :size => 7) do
|
66
|
+
text meta_values, :color => meta_color
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -1,12 +1,11 @@
|
|
1
1
|
module Laser
|
2
2
|
module Cutter
|
3
3
|
module Renderer
|
4
|
-
class RectRenderer <
|
4
|
+
class RectRenderer < Base
|
5
5
|
alias_method :rect, :subject
|
6
|
-
|
7
6
|
def render pdf
|
8
7
|
rect.sides.each do |side|
|
9
|
-
LineRenderer.new(
|
8
|
+
LineRenderer.new(config, side).render(pdf)
|
10
9
|
end
|
11
10
|
end
|
12
11
|
end
|
data/lib/laser-cutter/version.rb
CHANGED
data/spec/configuration_spec.rb
CHANGED
@@ -31,49 +31,15 @@ module Laser
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
end
|
34
|
-
context '#list_page_sizes' do
|
35
|
-
context 'formatting of output' do
|
36
|
-
context 'when using inches' do
|
37
|
-
let(:opts) { {"units" => "in"} }
|
38
|
-
it 'should return the list in inches' do
|
39
|
-
expect(config.all_page_sizes).to match %r(.*B10\:\s+1\.2\s+x\s+1\.7)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
context 'when using mm' do
|
43
|
-
let(:opts) { {"units" => "mm"} }
|
44
|
-
it 'should return the list in mm' do
|
45
|
-
expect(config.all_page_sizes).to match %r(.*B10\:\s+31\.0\s+x\s+44\.0)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
34
|
|
51
35
|
context 'when invalid units are provided' do
|
52
36
|
let(:opts) { {"size" => "2x3x2/0.125/0.5", "units" => 'xx'} }
|
53
|
-
it 'should default to
|
54
|
-
expect(config.units).to eql('
|
37
|
+
it 'should default to inches' do
|
38
|
+
expect(config.units).to eql('in')
|
55
39
|
end
|
56
40
|
end
|
57
41
|
|
58
42
|
context 'when converting between units' do
|
59
|
-
context 'a single value' do
|
60
|
-
context 'to inches' do
|
61
|
-
let(:opts) { {'units' => 'in'} }
|
62
|
-
it 'should be correct' do
|
63
|
-
expect(config.value_from_units(150)).to be_within(0.0001).of(150.0/72.0)
|
64
|
-
expect(config.value_from_units(150, 'mm')).to be_within(0.0001).of(150.0/25.4)
|
65
|
-
expect(config.value_from_units(150, 'in')).to be_within(0.0001).of(150.0)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
context 'to mm' do
|
69
|
-
let(:opts) { {'units' => 'mm'} }
|
70
|
-
it 'should be correct' do
|
71
|
-
expect(config.value_from_units(150)).to be_within(0.0001).of(25.4 * 150.0 / 72.0)
|
72
|
-
expect(config.value_from_units(150, 'in')).to be_within(0.0001).of(150.0 * 25.4)
|
73
|
-
expect(config.value_from_units(150, 'mm')).to be_within(0.0001).of(150.0)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
43
|
context 'all config values' do
|
78
44
|
context "to mm" do
|
79
45
|
let(:opts) { {'size' => "2.0x3x2/0.125/0.5", 'padding' => '4.2', "units" => 'in'} }
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
module Laser
|
4
|
+
module Cutter
|
5
|
+
describe PageManager do
|
6
|
+
let(:pm) { Laser::Cutter::PageManager.new(units) }
|
7
|
+
|
8
|
+
context 'a single value' do
|
9
|
+
context 'to inches' do
|
10
|
+
let(:units) { 'in' }
|
11
|
+
it 'should be correct' do
|
12
|
+
expect(pm.value_from_units(150)).to be_within(0.0001).of(150.0/72.0)
|
13
|
+
expect(pm.value_from_units(150, 'mm')).to be_within(0.0001).of(150.0/25.4)
|
14
|
+
expect(pm.value_from_units(150, 'in')).to be_within(0.0001).of(150.0)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
context 'to mm' do
|
18
|
+
let(:units) { 'mm' }
|
19
|
+
it 'should be correct' do
|
20
|
+
expect(pm.value_from_units(150)).to be_within(0.0001).of(25.4 * 150.0 / 72.0)
|
21
|
+
expect(pm.value_from_units(150, 'in')).to be_within(0.0001).of(150.0 * 25.4)
|
22
|
+
expect(pm.value_from_units(150, 'mm')).to be_within(0.0001).of(150.0)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context '#list_page_sizes' do
|
28
|
+
context 'formatting of output' do
|
29
|
+
context 'when using inches' do
|
30
|
+
let(:units) { "in" }
|
31
|
+
it 'should return the list in inches' do
|
32
|
+
expect(pm.all_page_sizes).to match %r(.*B10\:\s+1\.2\s+x\s+1\.7)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
context 'when using mm' do
|
36
|
+
let(:units) { "mm" }
|
37
|
+
it 'should return the list in mm' do
|
38
|
+
expect(pm.all_page_sizes).to match %r(.*B10\:\s+31\.0\s+x\s+44\.0)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/spec/renderer_spec.rb
CHANGED
@@ -3,19 +3,22 @@ require_relative 'spec_helper'
|
|
3
3
|
module Laser
|
4
4
|
module Cutter
|
5
5
|
module Renderer
|
6
|
-
describe
|
6
|
+
describe LayoutRenderer do
|
7
7
|
context '#render' do
|
8
|
-
let(:
|
9
|
-
let(:renderer) { BoxRenderer.new(config) }
|
8
|
+
let(:renderer) { LayoutRenderer.new(config) }
|
10
9
|
let(:file) { File.expand_path("../../laser-cutter-pdf-test.#{$$}.pdf", __FILE__) }
|
11
10
|
|
12
11
|
def render_file filename
|
12
|
+
config.validate!
|
13
13
|
expect(!File.exists?(filename))
|
14
14
|
renderer.render
|
15
15
|
expect(File.exist?(filename))
|
16
16
|
expect(File.size(filename) > 0)
|
17
|
+
rescue Exception => e
|
18
|
+
STDERR.puts e.backtrace.join("\n")
|
19
|
+
fail e.message
|
17
20
|
ensure
|
18
|
-
File.delete(filename)
|
21
|
+
File.delete(filename) rescue nil
|
19
22
|
expect(!File.exists?(filename))
|
20
23
|
end
|
21
24
|
|
@@ -38,7 +41,7 @@ module Laser
|
|
38
41
|
|
39
42
|
it 'should be able to generate a PDF file' do
|
40
43
|
render_file file
|
41
|
-
|
44
|
+
end
|
42
45
|
end
|
43
46
|
|
44
47
|
context 'margins and padding are defaults' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: laser-cutter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Gredeskoul
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prawn
|
@@ -158,15 +158,20 @@ files:
|
|
158
158
|
- lib/laser-cutter/geometry/shape/line.rb
|
159
159
|
- lib/laser-cutter/geometry/shape/rect.rb
|
160
160
|
- lib/laser-cutter/geometry/tuple.rb
|
161
|
+
- lib/laser-cutter/page_manager.rb
|
161
162
|
- lib/laser-cutter/renderer.rb
|
163
|
+
- lib/laser-cutter/renderer/base.rb
|
162
164
|
- lib/laser-cutter/renderer/box_renderer.rb
|
165
|
+
- lib/laser-cutter/renderer/layout_renderer.rb
|
163
166
|
- lib/laser-cutter/renderer/line_renderer.rb
|
167
|
+
- lib/laser-cutter/renderer/meta_renderer.rb
|
164
168
|
- lib/laser-cutter/renderer/rect_renderer.rb
|
165
169
|
- lib/laser-cutter/version.rb
|
166
170
|
- spec/box_spec.rb
|
167
171
|
- spec/configuration_spec.rb
|
168
172
|
- spec/dimensions_spec.rb
|
169
173
|
- spec/line_spec.rb
|
174
|
+
- spec/page_manager_spec.rb
|
170
175
|
- spec/path_generator_spec.rb
|
171
176
|
- spec/point_spec.rb
|
172
177
|
- spec/rect_spec.rb
|
@@ -202,8 +207,10 @@ test_files:
|
|
202
207
|
- spec/configuration_spec.rb
|
203
208
|
- spec/dimensions_spec.rb
|
204
209
|
- spec/line_spec.rb
|
210
|
+
- spec/page_manager_spec.rb
|
205
211
|
- spec/path_generator_spec.rb
|
206
212
|
- spec/point_spec.rb
|
207
213
|
- spec/rect_spec.rb
|
208
214
|
- spec/renderer_spec.rb
|
209
215
|
- spec/spec_helper.rb
|
216
|
+
has_rdoc:
|