inkmake 0.1.2 → 0.1.4

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.
Files changed (3) hide show
  1. checksums.yaml +5 -5
  2. data/lib/inkmake.rb +182 -51
  3. metadata +3 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9bfce00fca4b90da107ec5682f2e4b0ed2e1f178
4
- data.tar.gz: 3482fed6b2c0e92c244a50c43004eab801f407ff
2
+ SHA256:
3
+ metadata.gz: 020ed9f884ade66f1fc89a553d5187852aeaaa330236a58da5dc7f9f0f289a71
4
+ data.tar.gz: dc3019d1323bde40081b23c28b040fdb4c75d534be571985b9dc5255a8cdab3e
5
5
  SHA512:
6
- metadata.gz: d69a68ecca8fc2b0d5414e38a548499f1eec67025a01b9040c0a45d61138f287cc269a920fe6fa5c4b96be530b9f405984418d4f6d5358f5bc0d96f40949528c
7
- data.tar.gz: 51e689399a5fb976462d34f89d4000e7506c00074500c12c3872c5d482eb30afe78f6451ef7444bcf281595ce0115f31d3e38f76d7aca9be2f6c57996c54f128
6
+ metadata.gz: e2ffa9662e94fc3641392d20b4f661e42a8ab993d672d80174e23da95b11a4ef4f8218c7be69571d0d02712b621af04ac3f06a33eb2353853953843c9597988d
7
+ data.tar.gz: e8a8e294a01eab9d537130b0fa6d3d3e4ad36c3b006e93763b1a426e1f1ed10096bd362ae7dfd3d1fbcaeae0664c1d4a9dd2983292271adcda9fbcf0134276e4
data/lib/inkmake.rb CHANGED
@@ -113,9 +113,12 @@ class Inkmake
113
113
  end
114
114
 
115
115
  class InkscapeRemote
116
+ attr_reader :inkscape_version
117
+
116
118
  def initialize
117
- open
118
- probe_decimal_symbol
119
+ @inkscape_version = probe_inkscape_version
120
+ open_shell
121
+ probe_decimal_symbol if @inkscape_version == 0
119
122
  yield self
120
123
  ensure
121
124
  quit
@@ -125,14 +128,20 @@ class Inkmake
125
128
  @is_windows ||= (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) != nil
126
129
  end
127
130
 
128
- def open
131
+ def open(args)
129
132
  if is_windows
130
- # Inkscape on Windows for some reason needs to run from its binary dir
131
- @in, @out, @err = Open3.popen3(*[File.basename(self.class.path), "--shell"],
133
+ # Inkscape on Windows for some reason needs to run from its binary dir.
134
+ # popen2e so get stdout and stderr in one pipe. inkscape 1 shell seems to
135
+ # use both as output and we need to read to not block it.
136
+ Open3.popen2e(*[File.basename(self.class.path)] + args,
132
137
  :chdir => File.dirname(self.class.path))
133
138
  else
134
- @in, @out, @err = Open3.popen3(*[self.class.path, "--shell"])
139
+ Open3.popen2e(*[self.class.path] + args)
135
140
  end
141
+ end
142
+
143
+ def open_shell
144
+ @in, @out = open(["--shell"])
136
145
  loop do
137
146
  case response
138
147
  when :prompt then break
@@ -140,7 +149,7 @@ class Inkmake
140
149
  end
141
150
  end
142
151
 
143
- def command(args)
152
+ def command0(args)
144
153
  c = args.collect do |key, value|
145
154
  if value
146
155
  "\"#{key}=#{self.class.escape value.to_s}\""
@@ -148,54 +157,94 @@ class Inkmake
148
157
  key
149
158
  end
150
159
  end.join(" ")
151
- puts "> #{c}" if Inkmake.verbose
160
+ puts "< #{c}" if Inkmake.verbose
161
+ @in.write "#{c}\n"
162
+ @in.flush
163
+ end
164
+
165
+ def command1(args)
166
+ c = args.collect do |key, value|
167
+ if value
168
+ "#{key}:#{value.to_s}"
169
+ else
170
+ "#{key}:"
171
+ end
172
+ end.join("\n")
173
+ puts "< #{c}" if Inkmake.verbose
152
174
  @in.write "#{c}\n"
153
175
  @in.flush
154
176
  end
155
177
 
156
178
  def response
157
- o = @out.read(1)
158
- if o == ">"
159
- puts "< #{o}" if Inkmake.verbose
160
- return :prompt;
179
+ if @inkscape_version == 0
180
+ o = @out.read(1)
181
+ if o == ">"
182
+ puts "1> #{o}" if Inkmake.verbose
183
+ return :prompt;
184
+ end
185
+ else
186
+ o = @out.read(2)
187
+ if o == "> "
188
+ puts "1> #{o}" if Inkmake.verbose
189
+ return :prompt;
190
+ end
161
191
  end
162
192
  o = o + @out.readline
163
- puts "< #{o}" if Inkmake.verbose
193
+ puts "2> #{o}" if Inkmake.verbose
164
194
  o
165
195
  end
166
196
 
197
+ def probe_inkscape_version
198
+ _in, out = open(["--version"])
199
+ version = 0
200
+ begin
201
+ loop do
202
+ case out.readline()
203
+ when /^\s*Inkscape 1\..*$/ then
204
+ version = 1
205
+ when /^\s*Inkscape 0\..*$/ then
206
+ version = 0
207
+ end
208
+ end
209
+ rescue EOFError
210
+ end
211
+ version
212
+ end
213
+
167
214
  # this is weird but is the least weird and most protable way i could come up with
168
215
  # to figuring out what decimal symbol to use.
169
216
  # forcing LC_NUMERIC=C seems hard to do in a portable way
170
217
  # trying to use env inkmake is running in is also not so portable (windows?)
171
218
  def probe_decimal_symbol
219
+ @decimal_symbol = "."
172
220
  svg =
173
221
  "<?xml version=\"1.0\"?>" +
174
222
  "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"1\" height=\"1\">" +
175
223
  "</svg>"
176
- f = Tempfile.new("inkmake")
224
+ f = Tempfile.new(["inkmake", ".svg"])
177
225
  f.write(svg)
178
226
  f.flush
179
227
  begin
180
- command({
181
- "--file" => f.path,
182
- "--export-png" => Tempfile.new("inkmake").path,
183
- "--export-area" => "0.0:0.0:1.0:1.0",
228
+ # this will try export with "." as symbol in area
229
+ export({
230
+ :svg_path => f.path,
231
+ :out_path => Tempfile.new(["inkmake", ".png"]).path,
232
+ :format => "png",
233
+ :area => [0.0, 0.0, 1.0, 1.0]
184
234
  })
185
235
  loop do
186
236
  case response
187
237
  when :prompt then break
188
238
  end
189
239
  end
190
- @decimal_symbol = "."
191
240
  rescue EOFError
192
241
  @decimal_symbol = ","
193
242
  # restart inkscape
194
- open
243
+ open_shell
195
244
  end
196
245
  end
197
246
 
198
- def export(opts)
247
+ def export0(opts)
199
248
  c = {
200
249
  "--file" => opts[:svg_path],
201
250
  "--export-#{opts[:format]}" => opts[:out_path]
@@ -215,13 +264,13 @@ class Inkmake
215
264
  elsif opts[:area].kind_of? String
216
265
  c["--export-id"] = opts[:area]
217
266
  end
218
- command(c)
267
+ command0(c)
219
268
  width, height = [0, 0]
220
- out = nil
269
+ #out = nil
221
270
  loop do
222
271
  case response
223
- when /^Bitmap saved as: (.*)$/ then
224
- out = $1
272
+ # when /^Bitmap saved as: (.*)$/ then
273
+ # out = $1
225
274
  when /^Area .* exported to (\d+) x (\d+) pixels.*$/ then
226
275
  width = $1
227
276
  height = $2
@@ -232,18 +281,89 @@ class Inkmake
232
281
  [width, height]
233
282
  end
234
283
 
284
+ def export1(opts)
285
+ c = [
286
+ ["file-open", opts[:svg_path]],
287
+ ["export-type", opts[:format]],
288
+ ["export-filename", opts[:out_path]]
289
+ ]
290
+ if opts[:res]
291
+ s = opts[:rotate_scale_hack] ? 2 : 1
292
+ c += [["export-width", opts[:res].width.to_pixels(opts[:dpi] || 90) * s]]
293
+ c += [["export-height", opts[:res].height.to_pixels(opts[:dpi] || 90) * s]]
294
+ else
295
+ c += [["export-width", ""]]
296
+ c += [["export-height", ""]]
297
+ end
298
+ if opts[:dpi]
299
+ c += [["export-dpi", opts[:dpi]]]
300
+ end
301
+
302
+ c += [["export-area", ""]]
303
+ c += [["export-area-drawing", "false"]]
304
+ c += [["export-id", ""]]
305
+ c += [["export-area-page", "false"]]
306
+
307
+ if opts[:area].kind_of? Array
308
+ c += [["export-area", ("%f:%f:%f:%f" % opts[:area]).gsub(".", @decimal_symbol)]]
309
+ elsif opts[:area] == :drawing
310
+ c += [["export-area-drawing", "true"]]
311
+ elsif opts[:area].kind_of? String
312
+ c += [["export-id", opts[:area]]]
313
+ else
314
+ c += [["export-area-page", "true"]]
315
+ end
316
+ c.each do |a|
317
+ command1([a])
318
+ response
319
+ end
320
+
321
+ command1([["export-do"]])
322
+ width, height = [0, 0]
323
+ loop do
324
+ case response
325
+ when /^Area .* exported to (\d+) x (\d+) pixels.*$/ then
326
+ width = $1
327
+ height = $2
328
+ when :prompt then break
329
+ end
330
+ end
331
+ command1([["file-close"]])
332
+ response
333
+
334
+ [width, height]
335
+ end
336
+
337
+ def export(opts)
338
+ if @inkscape_version == 0 then
339
+ export0(opts)
340
+ else
341
+ export1(opts)
342
+ end
343
+ end
344
+
235
345
  def query_all(file)
236
346
  ids = []
237
- command({
238
- "--file" => file,
239
- "--query-all" => nil,
240
- })
347
+ if @inkscape_version == 0 then
348
+ command0({
349
+ "--file" => file,
350
+ "--query-all" => nil,
351
+ })
352
+ else
353
+ command1([["file-open", file]])
354
+ response
355
+ command1([["query-all", file]])
356
+ end
241
357
  loop do
242
358
  case response
243
359
  when /^(.*),(.*),(.*),(.*),(.*)$/ then ids << [$1, $2.to_f, $3.to_f, $4.to_f, $5.to_f]
244
360
  when :prompt then break
245
361
  end
246
362
  end
363
+ if @inkscape_version == 1 then
364
+ command1([["file-close", file]])
365
+ response
366
+ end
247
367
  ids
248
368
  end
249
369
 
@@ -256,7 +376,11 @@ class Inkmake
256
376
  end
257
377
 
258
378
  def quit
259
- command({"quit" => nil})
379
+ if @inkscape_version == 0 then
380
+ command0({"quit" => nil})
381
+ else
382
+ @in.close
383
+ end
260
384
  @out.read
261
385
  nil
262
386
  end
@@ -269,8 +393,9 @@ class Inkmake
269
393
  return Inkmake.inkscape_path if Inkmake.inkscape_path
270
394
 
271
395
  # try to figure out inkscape path
272
- p = (
273
- (["/Applications/Inkscape.app/Contents/Resources/bin/inkscape",
396
+ p = (
397
+ (["/Applications/Inkscape.app/Contents/MacOS/inkscape",
398
+ "/Applications/Inkscape.app/Contents/Resources/bin/inkscape",
274
399
  'c:\Program Files\Inkscape\inkscape.exe',
275
400
  'c:\Program Files (x86)\Inkscape\inkscape.exe'] +
276
401
  (ENV['PATH'].split(':').map {|p| File.join(p, "inkscape")}))
@@ -283,7 +408,12 @@ class Inkmake
283
408
  else
284
409
  begin
285
410
  require "osx/cocoa"
286
- "#{OSX::NSWorkspace.sharedWorkspace.fullPathForApplication:"Inkscape"}/Contents/Resources/bin/inkscape"
411
+ app_path = OSX::NSWorkspace.sharedWorkspace.fullPathForApplication:"Inkscape"
412
+ ["#{app_path}/Contents/MacOS/inkscape",
413
+ "#{app_path}/Contents/Resources/bin/inkscape"]
414
+ .select do |path|
415
+ File.exists? path
416
+ end
287
417
  rescue NameError, LoadError
288
418
  nil
289
419
  end
@@ -303,29 +433,29 @@ class Inkmake
303
433
  }
304
434
  # 123x123, 12.3cm*12.3cm
305
435
  RES_RE = /^(\d+(?:\.\d+)?(?:px|pt|pc|mm|cm|dm|m|in|ft|uu)?)[x*](\d+(?:\.\d+)?(?:px|pt|pc|mm|cm|dm|m|in|ft|uu)?)$/
306
- # *123, *1.23
307
- SCALE_RE = /^\*(\d+(?:\.\d+)?)$/
308
- # 180dpi
309
- DPI_RE = /^(\d+(?:\.\d+)?)dpi$/i
436
+ # *123, *1.23
437
+ SCALE_RE = /^\*(\d+(?:\.\d+)?)$/
438
+ # 180dpi
439
+ DPI_RE = /^(\d+(?:\.\d+)?)dpi$/i
310
440
  # (prefix)[(...)](suffix)
311
441
  DEST_RE = /^([^\[]*)(?:\[(.*)\])?(.*)$/
312
- # test.svg, test.SVG
313
- SVG_RE = /\.svg$/i
442
+ # test.svg, test.SVG
443
+ SVG_RE = /\.svg$/i
314
444
  # ext to format, supported inkscape output formats
315
445
  EXT_RE = /\.(png|pdf|ps|eps)$/i
316
446
  # supported inkscape output formats
317
447
  FORMAT_RE = /^(png|pdf|ps|eps)$/i
318
448
  # @name
319
449
  AREA_NAME_RE = /^@(.*)$/
320
- # @x:y:w:h
321
- AREA_SPEC_RE = /^@(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):(\d+(?:\.\d+)?)$/
322
- # right, left, upsidedown
323
- ROTATE_RE = /^(right|left|upsidedown)$/
324
- # show/hide layer or id, "+Layer 1", +#id, -*
325
- SHOWHIDE_RE = /^([+-])(.+)$/
450
+ # @x:y:w:h
451
+ AREA_SPEC_RE = /^@(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):(\d+(?:\.\d+)?):(\d+(?:\.\d+)?)$/
452
+ # right, left, upsidedown
453
+ ROTATE_RE = /^(right|left|upsidedown)$/
454
+ # show/hide layer or id, "+Layer 1", +#id, -*
455
+ SHOWHIDE_RE = /^([+-])(.+)$/
326
456
 
327
- class SyntaxError < StandardError
328
- end
457
+ class SyntaxError < StandardError
458
+ end
329
459
 
330
460
  class ProcessError < StandardError
331
461
  end
@@ -363,7 +493,7 @@ class Inkmake
363
493
  if RUBY_VERSION.start_with? "1.8"
364
494
  CSV::parse_line(line, fs = " ")
365
495
  else
366
- CSV::parse_line(line, {:col_sep => " "})
496
+ CSV::parse_line(line, **{:col_sep => " "})
367
497
  end
368
498
  end
369
499
 
@@ -468,16 +598,17 @@ class Inkmake
468
598
  else
469
599
  out_width, out_height = width, height
470
600
  end
601
+ file_href = "file://#{path}"
471
602
  svg =
472
603
  "<?xml version=\"1.0\"?>" +
473
604
  "<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"#{out_width}\" height=\"#{out_height}\">" +
474
605
  "<g>" +
475
606
  "<image transform=\"translate(#{out_width/2} #{out_height/2}) rotate(#{degrees})\"" +
476
607
  " width=\"#{width}\" height=\"#{height}\" x=\"#{-width/2}\" y=\"#{-height/2}\"" +
477
- " xlink:href=\"file:///#{URI.escape(path)}\" />" +
608
+ " xlink:href=#{file_href.encode(:xml => :attr)} />" +
478
609
  "</g>" +
479
610
  "</svg>"
480
- f = Tempfile.new("inkmake")
611
+ f = Tempfile.new(["inkmake", ".svg"])
481
612
  f.write(svg)
482
613
  f.flush
483
614
  f.seek(0)
@@ -679,7 +810,7 @@ class Inkmake
679
810
  end
680
811
  end
681
812
 
682
- f = Tempfile.new("inkmake")
813
+ f = Tempfile.new(["inkmake", ".svg"])
683
814
  doc.write(:output => f)
684
815
  f.flush
685
816
  f
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inkmake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattias Wadman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-02 00:00:00.000000000 Z
11
+ date: 2020-05-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: mattias.wadman@gmail.com
@@ -38,8 +38,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
38
38
  - !ruby/object:Gem::Version
39
39
  version: '0'
40
40
  requirements: []
41
- rubyforge_project:
42
- rubygems_version: 2.2.2
41
+ rubygems_version: 3.0.3
43
42
  signing_key:
44
43
  specification_version: 4
45
44
  summary: Makefile inspired export from SVG files using Inkscape as backend with some