fn_document 0.9.2

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 (48) hide show
  1. data/.document +5 -0
  2. data/Gemfile +13 -0
  3. data/Gemfile.lock +20 -0
  4. data/LICENSE.txt +20 -0
  5. data/README.rdoc +19 -0
  6. data/Rakefile +53 -0
  7. data/VERSION +1 -0
  8. data/fn_document.gemspec +95 -0
  9. data/lib/fn/block.rb +27 -0
  10. data/lib/fn/document.rb +204 -0
  11. data/lib/fn/migrate.xslt +224 -0
  12. data/lib/fn/node/base.rb +69 -0
  13. data/lib/fn/node/context.rb +70 -0
  14. data/lib/fn/node/root.rb +14 -0
  15. data/lib/fn/pdf/node/begin_document.rb +22 -0
  16. data/lib/fn/pdf/node/begin_page_ext.rb +24 -0
  17. data/lib/fn/pdf/node/create_textflow.rb +137 -0
  18. data/lib/fn/pdf/node/end_page_ext.rb +22 -0
  19. data/lib/fn/pdf/node/fit_image.rb +28 -0
  20. data/lib/fn/pdf/node/fit_pdi_page.rb +26 -0
  21. data/lib/fn/pdf/node/fit_textflow.rb +27 -0
  22. data/lib/fn/pdf/node/invert.rb +36 -0
  23. data/lib/fn/pdf/node/load_image.rb +21 -0
  24. data/lib/fn/pdf/node/open_pdi.rb +22 -0
  25. data/lib/fn/pdf/node/open_pdi_page.rb +31 -0
  26. data/lib/fn/pdf/node/resume_page.rb +21 -0
  27. data/lib/fn/pdf/node/set_parameter.rb +22 -0
  28. data/lib/fn/pdf/node/watermark.rb +24 -0
  29. data/lib/fn/pdf/struct.rb +40 -0
  30. data/lib/fn/pdf/writer.rb +205 -0
  31. data/lib/fn/resource.rb +53 -0
  32. data/lib/fn/swf/node/break.rb +19 -0
  33. data/lib/fn/swf/node/flash.rb +24 -0
  34. data/lib/fn/swf/node/font.rb +24 -0
  35. data/lib/fn/swf/node/frame.rb +19 -0
  36. data/lib/fn/swf/node/hot_spot.rb +43 -0
  37. data/lib/fn/swf/node/image.rb +19 -0
  38. data/lib/fn/swf/node/page.rb +30 -0
  39. data/lib/fn/swf/node/photo_block.rb +53 -0
  40. data/lib/fn/swf/node/text.rb +51 -0
  41. data/lib/fn/swf/struct.rb +43 -0
  42. data/lib/fn/swf/writer.rb +89 -0
  43. data/lib/fn/util.rb +27 -0
  44. data/lib/fn/validation.rng +172 -0
  45. data/lib/fn_document.rb +3 -0
  46. data/test/helper.rb +18 -0
  47. data/test/test_fn_document.rb +7 -0
  48. metadata +150 -0
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__) + "/util"
2
+
3
+ class String
4
+ def starts_with?(other)
5
+ head = self[0, other.length]
6
+ head == other
7
+ end
8
+ end
9
+
10
+ module FN
11
+ class Resource
12
+ include Util
13
+ attr_reader :node
14
+
15
+ def initialize(node)
16
+ raise_unless_xml_node node
17
+ @node = node
18
+ end
19
+
20
+ def complete?
21
+ !@node.children.empty?
22
+ end
23
+
24
+ def manual?
25
+ !!@node["manual"]
26
+ end
27
+
28
+ def path=(p)
29
+ @node.children.each{|c| c.remove! }
30
+ @node << p.to_s
31
+ end
32
+
33
+ def path
34
+ @node.first? && @node.first.to_s
35
+ end
36
+
37
+ def path_from(root)
38
+ File.expand_path("#{root}#{path}")
39
+ end
40
+
41
+ def key
42
+ @node["id"]
43
+ end
44
+
45
+ def type
46
+ @node["type"]
47
+ end
48
+
49
+ def delete
50
+ @node.remove!
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + "/../../node/base"
2
+ module FN
3
+ module SWF
4
+ module Node
5
+ def Break
6
+ FN::Node::Base("break").extend(Break)
7
+ end
8
+
9
+ module Break
10
+ include FN::Node::Base
11
+
12
+ def visit(struct)
13
+ has_no_children
14
+ struct.break
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + "/../../node/base"
2
+ module FN
3
+ module SWF
4
+ module Node
5
+ def Flash(width, height)
6
+ FN::Node::Base("flash", :width => width, :height => height).extend(Flash)
7
+ end
8
+
9
+ module Flash
10
+ include FN::Node::Base
11
+
12
+ def visit(struct)
13
+ w = self[:width]
14
+ h = self[:height]
15
+ size = "#{w}x#{h}"
16
+ struct.<< %[.flash bbox="#{size}" compress version=6] do
17
+ struct.<< %[.box bkg width=#{w} height=#{h} color=white fill]
18
+ visit_children struct
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + "/../../node/base"
2
+ module FN
3
+ module SWF
4
+ module Node
5
+
6
+ def Font(name, file)
7
+ FN::Node::Base("font", :name => name, :file => file).extend(Font)
8
+ end
9
+
10
+ module Font
11
+ include FN::Node::Base
12
+
13
+ def self.load_all_variants(key, path)
14
+ # no-op, since at present, we aren't using custom fonts?!
15
+ end
16
+
17
+ def visit(struct)
18
+ has_no_children
19
+ struct << %[.font #{self[:name]} "#{self[:file]}"]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + "/../../node/base"
2
+ module FN
3
+ module SWF
4
+ module Node
5
+ def Frame(name, file)
6
+ FN::Node::Base("frame", :name => name, :file => file).extend(Frame)
7
+ end
8
+
9
+ module Frame
10
+ include FN::Node::Base
11
+
12
+ def visit(struct)
13
+ has_no_children
14
+ struct << %[.font #{self[:name]} "#{self[:file]}"]
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + "/../../node/base"
2
+ module FN
3
+ module SWF
4
+ module Node
5
+ def HotSpot(page)
6
+ x, y, x2, y2 = page[:hotspot].gsub(/\s/, '').split(",").map{|s| s.to_i}
7
+ w = x2 - x
8
+ h = y2 - y
9
+ FN::Node::Base("hot_spot", :x => x, :y => y, :w => w, :h => h, :n => page[:number]).extend(HotSpot)
10
+ end
11
+
12
+ module HotSpot
13
+ include FN::Node::Base
14
+
15
+ def visit(struct)
16
+ has_no_children
17
+
18
+ x = self[:x]
19
+ y = self[:y]
20
+ w = self[:w]
21
+ h = self[:h]
22
+ n = self[:n]
23
+
24
+ struct << ".box btni#{n} width=#{w} height=#{h} color=red fill=white"
25
+
26
+ struct.<< ".button btn#{n}" do
27
+ struct.<< ".show btni#{n} as=area", :no_end_tag do
28
+ struct.<< ".on_release:" do
29
+ struct << "gotoAndStop(#{n});"
30
+ end
31
+ end
32
+ end
33
+
34
+ struct.<< ".action:" do
35
+ struct << "_root.attachMovie('btn#{n}', 'btni#{n}', #{$depth+=1}, {_x:#{x}, _y:#{y}});"
36
+ struct << "_root['btni#{n}']._x = #{x};"
37
+ struct << "_root['btni#{n}']._y = #{y};"
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + "/../../node/base"
2
+ module FN
3
+ module SWF
4
+ module Node
5
+ def Image(name, file)
6
+ FN::Node::Base("image", :name => name, :file => file).extend(Image)
7
+ end
8
+
9
+ module Image
10
+ include FN::Node::Base
11
+
12
+ def visit(struct)
13
+ has_no_children
14
+ struct << %[.jpeg #{self[:name]} "#{self[:file]}"]
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + "/../../node/base"
2
+ module FN
3
+ module SWF
4
+ module Node
5
+
6
+ def Page(number, bkg)
7
+ FN::Node::Base("page", :number => number, :bkg => bkg).extend(Page)
8
+ end
9
+
10
+ module Page
11
+ include FN::Node::Base
12
+
13
+ def visit(struct)
14
+ n = self[:number]
15
+ bkg = self[:bkg]
16
+ struct << ".frame #{n}"
17
+ struct.<< ".sprite page#{n}" do
18
+ struct << ".put bkg 0 0"
19
+ struct << ".put #{bkg} x=0 y=0"
20
+ visit_children(struct)
21
+ end
22
+ struct << ".put page#{n} 0 00"
23
+ struct.<< ".action:" do
24
+ struct << "stop();"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__) + "/../../node/base"
2
+ module FN
3
+ module SWF
4
+ module Node
5
+
6
+ def PhotoBlock(node, image_dims = {})
7
+ dims = image_dims[node[:src]]
8
+ FN::Node::Base("photo_block", node.attributes.to_h.update(
9
+ :orig_width => dims[0],
10
+ :orig_height => dims[1]
11
+ )).extend(PhotoBlock)
12
+ end
13
+
14
+ module PhotoBlock
15
+ include FN::Node::Base
16
+
17
+ # <block type="photo" src="logo" width="162" boxX="30" boxY="40"
18
+ # boxWidth="185" boxHeight="99" align="middlecenter"/>
19
+ def visit(struct)
20
+ has_no_children
21
+
22
+ src = self[:src]
23
+ bx = self[:boxX].to_i
24
+ by = self[:boxY].to_i
25
+ bw = self[:boxWidth].to_i
26
+ bh = self[:boxHeight].to_i
27
+ w = self[:width].to_i
28
+ ow = self[:orig_width].to_i
29
+ oh = self[:orig_height].to_i
30
+ align = self[:align]
31
+
32
+ scale = w.to_f / ow
33
+ percent = "#{scale * 100}%"
34
+ h = ow * scale
35
+
36
+ x = case align
37
+ when /center/: bx + (bw - w) / 2.0;
38
+ when /right/: bx + (bw - w)
39
+ else; bx
40
+ end
41
+
42
+ y = case align
43
+ when /middle/: by + (bh - h) / 2.0;
44
+ when /bottom/: by + (bh - h)
45
+ else; by
46
+ end
47
+
48
+ struct << ".put #{src} x=#{x} y=#{y} scalex=#{percent} scaley=#{percent}"
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,51 @@
1
+ require File.dirname(__FILE__) + "/../../node/base"
2
+ module FN
3
+ module SWF
4
+ module Node
5
+ def Text(node, alt_text)
6
+ out = FN::Node::Base("text", node.attributes.to_h)
7
+ out.extend(Text)
8
+ out.text = node.children.to_s
9
+ out.text = alt_text if out.text.empty?
10
+ out
11
+ end
12
+
13
+ module Text
14
+ include FN::Node::Base
15
+ SPACE = /\s+/
16
+
17
+ def text
18
+ (child && child.content).to_s
19
+ end
20
+
21
+ def text=(s)
22
+ self.children.map{|c| c.remove! }
23
+ self << XML::Node.new_cdata(s)
24
+ end
25
+
26
+ def escaped_text
27
+ text.gsub("\\", "\\\\").gsub("\"", "\\\"").gsub(SPACE, " ")
28
+ end
29
+
30
+ def visit(struct)
31
+ has_no_children
32
+ name = "#{self[:text]}_#{self[:index]}"
33
+ x = self[:x]
34
+ y = self[:y]
35
+ w = self[:width]
36
+ h = self[:height].to_i + 20 # Fudge
37
+
38
+ struct.<< ".action:" do
39
+ struct << "this.createTextField('#{name}', #{$depth+=1}, #{x}, #{y}, #{w}, #{h});"
40
+ struct << "id = this['#{name}'];"
41
+ struct << "id.html=true;"
42
+ struct << "id.multiline=true;"
43
+ struct << "id.wordWrap=true;"
44
+ struct << "id.htmlText = \"#{escaped_text}\";"
45
+ struct << "id.selectable = false;"
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,43 @@
1
+ module FN
2
+ module SWF
3
+ class Struct < Hash
4
+ TAB = " "
5
+
6
+ attr_reader :buffer
7
+
8
+ def initialize
9
+ @buffer = ""
10
+ @indent_level = 0
11
+ end
12
+
13
+ def break
14
+ self << ""
15
+ end
16
+
17
+ def <<(s, omit_end_tag = false, &b)
18
+ @buffer << "#{tabs}#{s}\n"
19
+ if block_given?
20
+ indent(&b)
21
+ @buffer << "#{tabs}.end\n" unless omit_end_tag
22
+ end
23
+ end
24
+
25
+ def tabs
26
+ TAB * @indent_level
27
+ end
28
+
29
+ def indent
30
+ @indent_level += 1
31
+ if block_given?
32
+ yield
33
+ @indent_level -= 1
34
+ end
35
+ end
36
+
37
+ def undent
38
+ @indent_level -= 1
39
+ raise "can't indent < 0" if @indent_level < 0
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,89 @@
1
+ Dir[File.dirname(__FILE__) + "/**/*.rb"].each do |f|
2
+ require_dependency f.sub(/\.rb$/, '')
3
+ end
4
+
5
+ module FN
6
+ module SWF
7
+ class Writer
8
+ include FN::SWF::Node
9
+
10
+ def initialize
11
+ end
12
+
13
+ def image_dimensions(image)
14
+ img = `identify "#{image}"`.scan(/ JPEG (\d+)x(\d+)/).flatten.map{|a|a.to_i}
15
+ end
16
+
17
+ def write(doc, options = {})
18
+ write_xml translate(doc, options), options[:save_as]
19
+ end
20
+
21
+ def write_xml(xml, file)
22
+ xml.root.extend(FN::Node::Root)
23
+ File.open("#{file}.txt", "w") {|f| f.puts xml.root.visit(FN::SWF::Struct.new).buffer }
24
+ cmd = %[swfc -o #{file} #{file}.txt]
25
+ system(cmd) ? file : raise("couldn't write swf")
26
+ end
27
+
28
+ def translate(doc, options = {})
29
+ raise "Not an FN Document" unless doc.is_a?(FN::Document)
30
+
31
+ file = options[:save_as] or raise "must provide :save_as"
32
+ root = options[:resource_root]
33
+
34
+ context = FN::Node::Context.new
35
+ $depth = 500
36
+
37
+ page = doc.pages.first
38
+ context << Flash(page[:width], page[:height])
39
+
40
+ # sorta no-op-ish
41
+ # doc.fonts.each do |font|
42
+ # context.add Font.load_all_variants(font.key, font.path_from(root))
43
+ # end
44
+
45
+ global_texts = doc.textflows.inject({}) do |memo, node|
46
+ memo[node["id"]] = node.children.to_s
47
+ memo
48
+ end
49
+
50
+ context.add Break()
51
+
52
+ image_dims = {}
53
+
54
+ doc.images.each do |img|
55
+ if img.complete?
56
+ path = img.path_from(root)
57
+ context.add Image(img.key, path)
58
+ image_dims[img.key] = image_dimensions(path)
59
+ end
60
+ end
61
+
62
+ context.add Break()
63
+
64
+ doc.pages.each do |page|
65
+ context.retain_after do
66
+ context.pre HotSpot(page)
67
+ context << Page(page[:number], page[:background])
68
+
69
+ doc.text_blocks_by(page["number"]).each do |block|
70
+ context.add Text(block, global_texts[block["text"]])
71
+ end
72
+
73
+ context.add Break()
74
+
75
+ i = 0
76
+ doc.photo_blocks_by(page["number"]).each do |block|
77
+ i += 1
78
+ context.add PhotoBlock(block, image_dims)
79
+ end
80
+
81
+ context.add Break()
82
+ end
83
+ end
84
+
85
+ return context.doc
86
+ end
87
+ end
88
+ end
89
+ end