minicomic 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +106 -0
- data/Rakefile +39 -0
- data/lib/minicomic.rb +447 -0
- data/test/test_all.rb +0 -0
- metadata +49 -0
data/README
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
= minicomic
|
2
|
+
|
3
|
+
+minicomic+ is a library providing a set of rake rules for building
|
4
|
+
print and web-ready files for minicomics from a set of SVG files.
|
5
|
+
|
6
|
+
Currently, it is hard-coded for generating 5.5x8.5in format black-and-white
|
7
|
+
comics of the sort most suitable for inexpensive photocopying.
|
8
|
+
|
9
|
+
== requirements
|
10
|
+
|
11
|
+
In addition to the obvious requirements for Ruby and Rake, +minicomic+
|
12
|
+
requires the following software to be installed and available on your
|
13
|
+
shell's path:
|
14
|
+
|
15
|
+
* Inkscape
|
16
|
+
* psutils
|
17
|
+
* Ghostscript
|
18
|
+
* ImageMagick
|
19
|
+
* pngcrush
|
20
|
+
|
21
|
+
If you're on Ubuntu, these correspond to the +inkscape+, +psutils+,
|
22
|
+
+gs-gpl+, +imagemagick+ and +pngcrush+ packages, respectively.
|
23
|
+
|
24
|
+
== usage
|
25
|
+
|
26
|
+
The simplest way to use +minicomic+ is to create a +Rakefile+ as follows:
|
27
|
+
|
28
|
+
require 'minicomic'
|
29
|
+
|
30
|
+
minicomic '.'
|
31
|
+
|
32
|
+
+minicomic+ will look for pages in a +pages/+ folder in the given directory
|
33
|
+
(in this particular case, '.' meaning the directory where the +Rakefile+ lives).
|
34
|
+
|
35
|
+
+minicomic+ looks for SVG files in +pages/+ named according to the following
|
36
|
+
conventions:
|
37
|
+
|
38
|
+
+page-NN.svg+:: page NN
|
39
|
+
+front-cover.svg+:: the front cover of the comic (optional)
|
40
|
+
+back-cover.svg+:: the back cover of the comic (optional)
|
41
|
+
+inside-front.svg+:: the inside front cover of the comic (optional)
|
42
|
+
+inside-back.svg+:: the inside back cover of the comic (optional)
|
43
|
+
|
44
|
+
It is also possible to have two-page spreads in single files:
|
45
|
+
|
46
|
+
+pages-NN-MM.svg+:: the spread spanning pages NN-MM
|
47
|
+
+cover.svg+:: the cover (back and front together in one file; optional)
|
48
|
+
|
49
|
+
Page numbers start at 1 (page 1 is a right-handed page, and the first
|
50
|
+
interior page). Page documents should be 5.5x8.5in or smaller for single
|
51
|
+
pages, and 11x8.5in for two-page spreads.
|
52
|
+
|
53
|
+
== print output
|
54
|
+
|
55
|
+
When generating output for print, +minicomic+ will round the number of
|
56
|
+
interior pages up to the next multiple of four, padding with blank pages
|
57
|
+
as needed. The page graphics will be scaled down slightly from their full
|
58
|
+
size, and smaller graphics will be centered.
|
59
|
+
|
60
|
+
To generate a "proof" PDF that you can examine to see what spreads will
|
61
|
+
look like in the assembled comic, use:
|
62
|
+
|
63
|
+
+rake proof+
|
64
|
+
|
65
|
+
The PDF will be created as +print/proof.pdf+. Since I rarely use the
|
66
|
+
inside covers for anything, +minicomic+ places the front and back covers
|
67
|
+
opposite the first and last interior pages respectively.
|
68
|
+
|
69
|
+
To generate a set of PDFs suitable for printing and assembly, use:
|
70
|
+
|
71
|
+
+rake print+
|
72
|
+
|
73
|
+
This will generate a set of three PDFs:
|
74
|
+
|
75
|
+
+print/duplex.pdf+:: suitable for duplex printing
|
76
|
+
+print/front.pdf+ and +print/back.pdf+:: front and back sides for single-sided printing
|
77
|
+
|
78
|
+
If you are using a duplex printer, if you're lucky it will deposit its
|
79
|
+
output pages face-up and they will be ready for assembly (this is the norm).
|
80
|
+
Otherwise if it deposits its pages face-down, you will have reverse them before
|
81
|
+
you can assemble the comic.
|
82
|
+
|
83
|
+
When using the single-sided PDFs, _you will need to experiment_ to find the
|
84
|
+
correct order to use them in, and the correct way to flip the paper. For my
|
85
|
+
printer, I print +back.pdf+ first, then flip the stack the long way before
|
86
|
+
printing +front.pdf+ on it. Other printers will differ depending on how the
|
87
|
+
paper is loaded in the tray, and how it is stacked on output.
|
88
|
+
|
89
|
+
== web output
|
90
|
+
|
91
|
+
You can generate files for web upload via:
|
92
|
+
|
93
|
+
+rake web+
|
94
|
+
|
95
|
+
When generating output for the web, +minicomic+ will generate a set of 4-bit
|
96
|
+
greyscale PNGs, and a corresponding set of JPEG thumbnails:
|
97
|
+
|
98
|
+
+web/page-NN.png+:: page NN
|
99
|
+
+web/thumbnail-NN.jpeg:: thumbnail of page NN
|
100
|
+
|
101
|
+
== cleanup
|
102
|
+
|
103
|
+
You can easily get rid of the temporary and output files with:
|
104
|
+
|
105
|
+
+rake clean+
|
106
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
|
6
|
+
Rake::TestTask.new do |task|
|
7
|
+
task.libs << 'lib'
|
8
|
+
task.libs << 'test'
|
9
|
+
task.test_files = [ "test/test_all.rb" ]
|
10
|
+
task.verbose = true
|
11
|
+
end
|
12
|
+
|
13
|
+
Rake::RDocTask.new do |task|
|
14
|
+
task.rdoc_files.include "README"
|
15
|
+
task.main = "README"
|
16
|
+
end
|
17
|
+
|
18
|
+
gemspec = Gem::Specification.new do |gemspec|
|
19
|
+
gemspec.platform = Gem::Platform::RUBY
|
20
|
+
gemspec.name = "minicomic"
|
21
|
+
gemspec.version = "0.0.1"
|
22
|
+
gemspec.author = "MenTaLguY <mental@rydia.net>"
|
23
|
+
gemspec.summary = "Rake rules for minicomic impressions"
|
24
|
+
gemspec.test_file = 'test/test_all.rb'
|
25
|
+
gemspec.files = FileList[ 'Rakefile', 'test/*.rb', 'lib/**/*.rb' ]
|
26
|
+
gemspec.require_paths = [ 'lib' ]
|
27
|
+
gemspec.has_rdoc = true
|
28
|
+
gemspec.extra_rdoc_files = %w(README)
|
29
|
+
gemspec.rdoc_options = %w(--main README)
|
30
|
+
end
|
31
|
+
|
32
|
+
task :package => [ :test ]
|
33
|
+
Rake::GemPackageTask.new( gemspec ) do |task|
|
34
|
+
task.gem_spec = gemspec
|
35
|
+
task.need_tar = true
|
36
|
+
end
|
37
|
+
|
38
|
+
task :default => [ :package ]
|
39
|
+
|
data/lib/minicomic.rb
ADDED
@@ -0,0 +1,447 @@
|
|
1
|
+
#
|
2
|
+
# minicomic.rb: Rake tasks for minicomics using Inkscape and other tools
|
3
|
+
#
|
4
|
+
# Copyright 2007 MenTaLguY <mental@rydia.net>
|
5
|
+
#
|
6
|
+
# This library is made available under the same terms as Ruby.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'set'
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
module Minicomic
|
13
|
+
extend self
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
# in PostScript points
|
18
|
+
FORMAT_WIDTH = ( 5.5 * 72 ).to_i
|
19
|
+
FORMAT_HEIGHT = ( 8.5 * 72 ).to_i
|
20
|
+
PAGE_SCALE = 0.932
|
21
|
+
|
22
|
+
# other constants
|
23
|
+
LEFT = 0
|
24
|
+
RIGHT = 1
|
25
|
+
PHI = ( 1 + Math.sqrt( 5 ) ) / 2
|
26
|
+
|
27
|
+
def eps_from_svg( eps_file, svg_file )
|
28
|
+
file eps_file => [ svg_file ] do
|
29
|
+
sh 'inkscape', '-T', '-B', '-E', eps_file, svg_file
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def back_eps( out_file, in_file )
|
34
|
+
file out_file => [ in_file ] do
|
35
|
+
sh 'psselect', '-e', in_file, out_file
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def front_eps( out_file, in_file )
|
40
|
+
file out_file => [ in_file ] do
|
41
|
+
sh 'psselect', '-o', in_file, out_file
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def make2up( in_file, out_file )
|
46
|
+
sh 'psnup', "-W#{ FORMAT_WIDTH }", "-H#{ FORMAT_HEIGHT }", "-h#{ FORMAT_WIDTH * 2 }", "-w#{ FORMAT_HEIGHT }", '-2', in_file, out_file
|
47
|
+
end
|
48
|
+
|
49
|
+
def duplex_eps( out_file, in_file )
|
50
|
+
temp_file = "#{ out_file }.temp"
|
51
|
+
file out_file => [ in_file ] do
|
52
|
+
sh 'psbook', in_file, temp_file
|
53
|
+
begin
|
54
|
+
make2up temp_file, out_file
|
55
|
+
ensure
|
56
|
+
rm temp_file
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def proof_eps( out_file, in_file )
|
62
|
+
temp_file = "#{ out_file }.temp"
|
63
|
+
file out_file => [ in_file ] do
|
64
|
+
sh 'psselect', '-p1,3-_3,_1', in_file, temp_file
|
65
|
+
begin
|
66
|
+
make2up temp_file, out_file
|
67
|
+
ensure
|
68
|
+
rm temp_file
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def pdf_from_eps( pdf_file, eps_file )
|
74
|
+
file pdf_file => [ eps_file ] do
|
75
|
+
sh 'ps2pdf', '-sPAPERSIZE=letter', eps_file, pdf_file
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def png_from_svg( png_file, svg_file )
|
80
|
+
temp_png_file = "#{ png_file }.temp"
|
81
|
+
file png_file => [ svg_file ] do
|
82
|
+
sh 'inkscape', '-d', '80', '-C', '-y', '1.0', '-e', temp_png_file, svg_file
|
83
|
+
begin
|
84
|
+
sh 'pngcrush', '-force', '-bit_depth', '4', '-c', '0', '-q', temp_png_file, png_file
|
85
|
+
ensure
|
86
|
+
rm temp_png_file
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def thumbnail_jpeg_from_image( jpeg_file, image_file )
|
92
|
+
file jpeg_file => [ image_file ] do
|
93
|
+
sh 'convert', '-filter', 'sinc', '-resize', "x96", image_file, jpeg_file
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class BookletLayout
|
98
|
+
def initialize( stream, *pages )
|
99
|
+
@bboxes = {}
|
100
|
+
@stream = stream
|
101
|
+
|
102
|
+
pages.push nil if pages.size % 2 != 0 # pad to even number of pages
|
103
|
+
|
104
|
+
# move the back cover to the beginning, to be paired with the front cover
|
105
|
+
pages.unshift pages.pop
|
106
|
+
|
107
|
+
# pair up adjacent pages into spreads
|
108
|
+
spreads = (0...(pages.size/2)).map { |i| [ pages[i*2], pages[i*2+1] ] }
|
109
|
+
|
110
|
+
# format each spread, breaking spreads back into invdividual pages after
|
111
|
+
pages = spreads.inject( [] ) do |acc, spread|
|
112
|
+
is_cover = acc.empty?
|
113
|
+
acc.push *format_pages( is_cover, *spread )
|
114
|
+
end
|
115
|
+
|
116
|
+
# return the back cover to the end
|
117
|
+
pages.push pages.shift
|
118
|
+
|
119
|
+
emit_document pages
|
120
|
+
end
|
121
|
+
|
122
|
+
def format_pages( is_cover, *pages )
|
123
|
+
spread = pages.map do |page|
|
124
|
+
if page
|
125
|
+
[ bbox(*page), page[2] ]
|
126
|
+
else
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
end.map do |page|
|
130
|
+
if page
|
131
|
+
bbox, document = page
|
132
|
+
dims = (0..1).map { |d| ( bbox[d].end - bbox[d].begin ) * PAGE_SCALE }
|
133
|
+
[ bbox, dims, document ]
|
134
|
+
else
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
if spread.all? # i.e. both?
|
140
|
+
spread_dims = spread.map { |page| page[1] }
|
141
|
+
left_document = spread[LEFT][2]
|
142
|
+
right_document = spread[RIGHT][2]
|
143
|
+
if left_document == right_document
|
144
|
+
tx = translate_spread( *spread_dims )
|
145
|
+
elsif is_cover
|
146
|
+
tx = spread_dims.map { |dims| translate_single( dims ) }
|
147
|
+
else
|
148
|
+
tx = translate_facing( *spread_dims )
|
149
|
+
end
|
150
|
+
[ [ spread[LEFT][0], tx[LEFT], left_document ],
|
151
|
+
[ spread[RIGHT][0], tx[RIGHT], right_document ] ]
|
152
|
+
else
|
153
|
+
spread.map do |page|
|
154
|
+
if page
|
155
|
+
[ page[0], translate_single( page[1] ), page[2] ]
|
156
|
+
else
|
157
|
+
nil
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def bbox( i, n, document )
|
164
|
+
rx, ry = @bboxes[document] ||= (
|
165
|
+
rx, ry = 0.0..(FORMAT_WIDTH.to_f * n), 0.0..(FORMAT_HEIGHT.to_f)
|
166
|
+
File.open( document, "r" ) do |stream|
|
167
|
+
stream.each_line do |line|
|
168
|
+
case line
|
169
|
+
when /^%%BoundingBox: (\d+) (\d+) (\d+) (\d+)/
|
170
|
+
rx, ry = ($1.to_f)..($3.to_f), ($2.to_f)..($4.to_f)
|
171
|
+
break
|
172
|
+
when /^%%EndComments/
|
173
|
+
break
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
[ rx, ry ]
|
178
|
+
)
|
179
|
+
width = rx.end - rx.begin
|
180
|
+
[ ( rx.begin + width * i / n )..( rx.begin + width * ( i + 1 ) / n ), ry ]
|
181
|
+
end
|
182
|
+
|
183
|
+
def bottom_margin( height )
|
184
|
+
( FORMAT_HEIGHT.to_f - height ) / PHI
|
185
|
+
end
|
186
|
+
|
187
|
+
def horizontal_margin( width )
|
188
|
+
( FORMAT_WIDTH.to_f - width ) / 2
|
189
|
+
end
|
190
|
+
|
191
|
+
def translate_single( dims )
|
192
|
+
[ horizontal_margin( dims[0] ), bottom_margin( dims[1] ) ]
|
193
|
+
end
|
194
|
+
|
195
|
+
def translate_facing( left, right )
|
196
|
+
left_margin = horizontal_margin( left[0] )
|
197
|
+
right_margin = horizontal_margin( right[0] )
|
198
|
+
gutter = [ [ left_margin, right_margin ].min, 0 ].max
|
199
|
+
[ [ left_margin + ( gutter / 3 ), bottom_margin( left[1] ) ],
|
200
|
+
[ right_margin - ( gutter / 3 ), bottom_margin( right[1] ) ] ]
|
201
|
+
end
|
202
|
+
|
203
|
+
def translate_spread( left, right )
|
204
|
+
[ [ FORMAT_WIDTH.to_f - left[0], bottom_margin( left[1] ) ],
|
205
|
+
[ 0, bottom_margin( right[1] ) ] ]
|
206
|
+
end
|
207
|
+
|
208
|
+
def emit_dsc( name, value=nil )
|
209
|
+
if value
|
210
|
+
@stream.puts "%%#{ name }: #{ value }"
|
211
|
+
else
|
212
|
+
@stream.puts "%%#{ name }"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def emit_document( pages )
|
217
|
+
@stream.puts "%!PS-Adobe-3.0"
|
218
|
+
emit_dsc 'Creator', 'minicomic'
|
219
|
+
emit_dsc 'Pages', pages.size
|
220
|
+
#emit_dsc 'Orientation', 'Portrait'
|
221
|
+
#bbox = "0 0 #{ FORMAT_WIDTH } #{ FORMAT_HEIGHT }"
|
222
|
+
#emit_dsc 'BoundingBox', bbox
|
223
|
+
#emit_dsc 'HiResBoundingBox', bbox
|
224
|
+
emit_dsc 'EndComments'
|
225
|
+
pages.each_with_index do |page, n|
|
226
|
+
if page
|
227
|
+
emit_page( n, *page )
|
228
|
+
else
|
229
|
+
emit_empty_page( n )
|
230
|
+
end
|
231
|
+
end
|
232
|
+
emit_dsc 'EOF'
|
233
|
+
end
|
234
|
+
|
235
|
+
def emit_clip_rect( x0, y0, x1, y1 )
|
236
|
+
@stream.puts "newpath"
|
237
|
+
@stream.puts "#{ x0 } #{ y0 } moveto"
|
238
|
+
@stream.puts "#{ x0 } #{ y1 } lineto"
|
239
|
+
@stream.puts "#{ x1 } #{ y1 } lineto"
|
240
|
+
@stream.puts "#{ x1 } #{ y0 } lineto"
|
241
|
+
@stream.puts "closepath eoclip newpath"
|
242
|
+
end
|
243
|
+
|
244
|
+
def emit_page( n, bbox, translate, document )
|
245
|
+
emit_dsc 'Page', "#{ n } #{ n }"
|
246
|
+
|
247
|
+
@stream.puts "save"
|
248
|
+
|
249
|
+
emit_clip_rect( 0, 0, FORMAT_WIDTH, FORMAT_HEIGHT )
|
250
|
+
|
251
|
+
@stream.puts <<EOS
|
252
|
+
#{ bbox.map { |r| -r.begin }.join( ' ' ) } translate
|
253
|
+
#{ PAGE_SCALE } #{ PAGE_SCALE } scale
|
254
|
+
#{ translate.join( ' ' ) } translate
|
255
|
+
EOS
|
256
|
+
|
257
|
+
emit_clip_rect( bbox[0].begin, bbox[1].begin, bbox[0].end, bbox[1].end )
|
258
|
+
|
259
|
+
emit_dsc 'BeginDocument', File.basename( document )
|
260
|
+
File.open( document, 'r' ) do |input|
|
261
|
+
input.each_line do |line|
|
262
|
+
@stream.puts line
|
263
|
+
end
|
264
|
+
end
|
265
|
+
emit_dsc 'EndDocument'
|
266
|
+
emit_dsc 'PageTrailer'
|
267
|
+
@stream.puts "restore"
|
268
|
+
end
|
269
|
+
|
270
|
+
def emit_empty_page( n )
|
271
|
+
emit_dsc 'Page', "#{ n } #{ n }"
|
272
|
+
@stream.puts "showpage"
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def layout_booklet( layout_ps, *pages )
|
277
|
+
file layout_ps => pages.compact.map { |i, n, file| file } do
|
278
|
+
begin
|
279
|
+
File.open( layout_ps, 'w' ) do |stream|
|
280
|
+
BookletLayout.new( stream, *pages )
|
281
|
+
end
|
282
|
+
rescue
|
283
|
+
rm layout_ps
|
284
|
+
raise
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
def special_name_re( name )
|
290
|
+
Regexp.new( Regexp.quote( name ).gsub( /-/, "\\W*" ), "i" )
|
291
|
+
end
|
292
|
+
|
293
|
+
def normalize_special_name( name )
|
294
|
+
name = name.gsub( /[a-z](?=[A-Z])/, '\&-' )
|
295
|
+
name.gsub!( /\W+/, '-' )
|
296
|
+
name.downcase!
|
297
|
+
name
|
298
|
+
end
|
299
|
+
|
300
|
+
SPECIAL_NAMES = %w(front-cover back-cover cover inside-front inside-back)
|
301
|
+
SPECIAL_NAME_RES = SPECIAL_NAMES.map { |n| special_name_re( n ) }
|
302
|
+
|
303
|
+
public
|
304
|
+
|
305
|
+
def minicomic( dir )
|
306
|
+
pages_dir = File.join( dir, 'pages' )
|
307
|
+
|
308
|
+
scratch_dir = File.join( dir, 'scratch' )
|
309
|
+
directory scratch_dir
|
310
|
+
|
311
|
+
web_dir = File.join( dir, 'web' )
|
312
|
+
directory web_dir
|
313
|
+
|
314
|
+
print_dir = File.join( dir, 'print' )
|
315
|
+
directory print_dir
|
316
|
+
|
317
|
+
layout_ps = File.join( scratch_dir, 'layout.ps' )
|
318
|
+
|
319
|
+
specials = Set.new
|
320
|
+
pages = []
|
321
|
+
|
322
|
+
FileList[File.join( pages_dir, '*.svg' )].each do |page_svg|
|
323
|
+
name = File.basename( page_svg )
|
324
|
+
name.sub!( /\.svg$/, '' )
|
325
|
+
|
326
|
+
min = max = nil
|
327
|
+
print_name = name
|
328
|
+
case name
|
329
|
+
when *SPECIAL_NAME_RES
|
330
|
+
name = normalize_special_name( name )
|
331
|
+
next unless SPECIAL_NAMES.include? name # warning?
|
332
|
+
next if specials.include? name # warning?
|
333
|
+
specials.add name
|
334
|
+
if name == 'front-cover'
|
335
|
+
web_name = "page-00"
|
336
|
+
else
|
337
|
+
web_name = nil
|
338
|
+
end
|
339
|
+
when /^page\W*(\d+)$/i
|
340
|
+
min = max = $1.to_i
|
341
|
+
suffix = "%02d" % [ min ]
|
342
|
+
print_name = "page-#{ suffix }"
|
343
|
+
web_name = print_name
|
344
|
+
when /^pages?\W*(\d+)\D+(\d+)$/i
|
345
|
+
min, max = $1.to_i, $2.to_i
|
346
|
+
min, max = max, min if max < min
|
347
|
+
suffix = "%02d-%02d" % [ min, max ]
|
348
|
+
print_name = "pages-#{ suffix }"
|
349
|
+
web_name = print_name
|
350
|
+
else
|
351
|
+
# warning?
|
352
|
+
next
|
353
|
+
end
|
354
|
+
|
355
|
+
page_eps = File.join( scratch_dir, "#{ print_name }.eps" )
|
356
|
+
|
357
|
+
if min and min > 0
|
358
|
+
size = max - min + 1
|
359
|
+
(0...size).each do |n|
|
360
|
+
pages[n+min-1] = [ n, size, page_eps ]
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
eps_from_svg( page_eps, page_svg )
|
365
|
+
task page_eps => [ scratch_dir ]
|
366
|
+
|
367
|
+
if web_name
|
368
|
+
page_png = File.join( web_dir, "#{ web_name }.png" )
|
369
|
+
png_from_svg( page_png, page_svg )
|
370
|
+
task page_png => [ web_dir ]
|
371
|
+
|
372
|
+
thumbnail_name = web_name.sub( /^page/, 'thumbnail' )
|
373
|
+
thumbnail_jpeg = File.join( web_dir, "#{ thumbnail_name }.jpeg" )
|
374
|
+
thumbnail_jpeg_from_image( thumbnail_jpeg, page_png )
|
375
|
+
task thumbnail_jpeg => [ web_dir ]
|
376
|
+
|
377
|
+
task :web => [ page_png, thumbnail_jpeg ]
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
pages = [ nil, nil ] + pages + [ nil ] * ( pages.size % 4 ) + [ nil, nil ]
|
382
|
+
|
383
|
+
specials.each do |name|
|
384
|
+
filename = File.join( scratch_dir, "#{ name }.eps" )
|
385
|
+
case name
|
386
|
+
when 'front-cover'
|
387
|
+
pages[0] ||= [ 0, 1, filename ] # 'cover' takes precedence
|
388
|
+
when 'back-cover'
|
389
|
+
pages[-1] ||= [ 0, 1, filename ] # 'cover' takes precedence
|
390
|
+
when 'cover'
|
391
|
+
pages[-1] = [ 0, 2, filename ]
|
392
|
+
pages[0] = [ 1, 2, filename ]
|
393
|
+
when 'inside-front'
|
394
|
+
pages[1] = [ 0, 1, filename ]
|
395
|
+
when 'inside-back'
|
396
|
+
pages[-2] = [ 0, 1, filename ]
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
layout_booklet( layout_ps, *pages )
|
401
|
+
|
402
|
+
duplex_eps = File.join( scratch_dir, "duplex.eps" )
|
403
|
+
|
404
|
+
%w(proof back front duplex).each do |kind|
|
405
|
+
case kind
|
406
|
+
when 'duplex', 'proof'
|
407
|
+
source = layout_ps
|
408
|
+
else
|
409
|
+
source = duplex_eps
|
410
|
+
end
|
411
|
+
kind_eps = File.join( scratch_dir, "#{ kind }.eps" )
|
412
|
+
send( "#{ kind }_eps", kind_eps, source )
|
413
|
+
task kind_eps => [ scratch_dir ]
|
414
|
+
kind_pdf = File.join( print_dir, "#{ kind }.pdf" )
|
415
|
+
pdf_from_eps( kind_pdf, kind_eps )
|
416
|
+
task kind_pdf => [ print_dir ]
|
417
|
+
task kind => [ kind_pdf ]
|
418
|
+
end
|
419
|
+
|
420
|
+
desc "Generate PDF files for printing"
|
421
|
+
task :print => [ :duplex, :front, :back ]
|
422
|
+
|
423
|
+
desc "Generate a proof PDF for review"
|
424
|
+
task :proof
|
425
|
+
|
426
|
+
desc "Remove all output and intermediate files"
|
427
|
+
task :clean do
|
428
|
+
rm_rf print_dir
|
429
|
+
rm_rf web_dir
|
430
|
+
rm_rf scratch_dir
|
431
|
+
end
|
432
|
+
|
433
|
+
desc "Generate graphics for the web"
|
434
|
+
task :web
|
435
|
+
|
436
|
+
desc "Generate web and print output"
|
437
|
+
task :both => [ :print, :web ]
|
438
|
+
|
439
|
+
task :default => [ :both ]
|
440
|
+
end
|
441
|
+
|
442
|
+
end
|
443
|
+
|
444
|
+
def minicomic( dir )
|
445
|
+
Minicomic.minicomic( dir )
|
446
|
+
end
|
447
|
+
|
data/test/test_all.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: minicomic
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.0.1
|
7
|
+
date: 2007-03-29 00:00:00 -04:00
|
8
|
+
summary: Rake rules for minicomic impressions
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email:
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
authors:
|
29
|
+
- MenTaLguY <mental@rydia.net>
|
30
|
+
files:
|
31
|
+
- Rakefile
|
32
|
+
- test/test_all.rb
|
33
|
+
- lib/minicomic.rb
|
34
|
+
- README
|
35
|
+
test_files:
|
36
|
+
- test/test_all.rb
|
37
|
+
rdoc_options:
|
38
|
+
- --main
|
39
|
+
- README
|
40
|
+
extra_rdoc_files:
|
41
|
+
- README
|
42
|
+
executables: []
|
43
|
+
|
44
|
+
extensions: []
|
45
|
+
|
46
|
+
requirements: []
|
47
|
+
|
48
|
+
dependencies: []
|
49
|
+
|