slidefield 0.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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +674 -0
  5. data/README.md +254 -0
  6. data/Rakefile +7 -0
  7. data/bin/slidefield +89 -0
  8. data/examples/complete/assets/K2.jpg +0 -0
  9. data/examples/complete/assets/gobi.jpg +0 -0
  10. data/examples/complete/assets/mount_everest.jpg +0 -0
  11. data/examples/complete/assets/sahara.jpg +0 -0
  12. data/examples/complete/main.sfp +7 -0
  13. data/examples/complete/slides/deserts.sfi +19 -0
  14. data/examples/complete/slides/mountains.sfi +25 -0
  15. data/examples/complete/templates.sfi +95 -0
  16. data/examples/complete/variables.sfi +6 -0
  17. data/examples/minimal/main.sfp +43 -0
  18. data/examples/minimal/ruby-logo.png +0 -0
  19. data/lib/slidefield/animator.rb +104 -0
  20. data/lib/slidefield/errors.rb +6 -0
  21. data/lib/slidefield/interpreter.rb +414 -0
  22. data/lib/slidefield/object_data.rb +78 -0
  23. data/lib/slidefield/object_manager.rb +29 -0
  24. data/lib/slidefield/object_rules.rb +79 -0
  25. data/lib/slidefield/objects/_base.rb +29 -0
  26. data/lib/slidefield/objects/_root.rb +10 -0
  27. data/lib/slidefield/objects/animation.rb +10 -0
  28. data/lib/slidefield/objects/debug.rb +18 -0
  29. data/lib/slidefield/objects/image.rb +47 -0
  30. data/lib/slidefield/objects/include.rb +9 -0
  31. data/lib/slidefield/objects/layout.rb +10 -0
  32. data/lib/slidefield/objects/rect.rb +44 -0
  33. data/lib/slidefield/objects/slide.rb +43 -0
  34. data/lib/slidefield/objects/song.rb +31 -0
  35. data/lib/slidefield/objects/text.rb +57 -0
  36. data/lib/slidefield/parser.rb +99 -0
  37. data/lib/slidefield/version.rb +3 -0
  38. data/lib/slidefield/viewer.rb +89 -0
  39. data/lib/slidefield.rb +27 -0
  40. data/slidefield.gemspec +27 -0
  41. data/test/helper.rb +11 -0
  42. data/test/resources/include_sub.sfp +1 -0
  43. data/test/resources/parse_error.sfp +1 -0
  44. data/test/resources/recursive_include.sfp +1 -0
  45. data/test/resources/sub/include_parent.sfp +1 -0
  46. data/test/resources/unclosed_object.sfp +2 -0
  47. data/test/resources/unknown_object.sfp +1 -0
  48. data/test/resources/wrong_template.sfp +4 -0
  49. data/test/test_animator.rb +244 -0
  50. data/test/test_examples.rb +29 -0
  51. data/test/test_interpreter.rb +1766 -0
  52. data/test/test_object_data.rb +108 -0
  53. data/test/test_object_manager.rb +48 -0
  54. data/test/test_object_rules.rb +87 -0
  55. data/test/test_parser.rb +408 -0
  56. metadata +199 -0
data/README.md ADDED
@@ -0,0 +1,254 @@
1
+ # SlideField
2
+
3
+ **A presentation software that reads plain text files written in its own
4
+ interpreted language.**
5
+
6
+ ## Installation
7
+
8
+ Requirements: ruby, sdl, sdl_ttf, freeimage
9
+
10
+ $ gem install slidefield
11
+
12
+
13
+ ## Usage
14
+
15
+ $ slidefield [options] [file ...]
16
+
17
+ ### Comments
18
+
19
+ % single-line comment
20
+ %{ multi-line
21
+ comment %}
22
+
23
+ ### Variables
24
+
25
+ A variable can only be created once inside each object (with the `=` operator).
26
+ However they can be modified freely using any other available operator.
27
+ The type of the variable cannot be changed after the variable creation.
28
+
29
+ variable = value
30
+ variable += value
31
+ variable -= value
32
+ variable *= value
33
+ variable /= value
34
+
35
+
36
+ ### Value types
37
+
38
+ Integers:
39
+
40
+ variable = 42
41
+ variable += 2 % add
42
+ variable -= 10 % subtract
43
+ variable *= 6 % multiply
44
+ variable /= 10 % divide
45
+ % variable is 20
46
+
47
+ Character strings:
48
+
49
+ variable = "hello"
50
+ variable += " world!\n" % append
51
+ variable -= "!" % remove the bang
52
+ variable *= "3" % multiply by 3
53
+ % variable is "hello world\nhello world\nhello world\n"
54
+
55
+ Size or point coordinates:
56
+
57
+ variable = 2x4
58
+ variable += 100x80 % add
59
+ variable -= 10x0 % subtract
60
+ variable *= 3x4 % multiply
61
+ variable /= 2x2 % divide
62
+ % variable is 138x168
63
+
64
+ Colors (red, blue, green & alpha in hexadecimal notation):
65
+
66
+ variable = #C0FF33FF
67
+ variable += #03003300 % add
68
+ variable -= #0C240055 % subtract
69
+ % variable is #B7DB66AA
70
+
71
+ Booleans:
72
+
73
+ variable = :true
74
+ opposite = :false
75
+
76
+ Variables can also store custom objects. See the 'Templates' section below.
77
+
78
+ ### Objects
79
+
80
+ Variables are bound to the object in which they are created into.
81
+ Most SlideField object have reserved variables ("*properties*")
82
+ with a predefined type.
83
+ All properties are mandatory unless otherwise specified.
84
+
85
+ Nested objects inherit their parent's variables.
86
+ All slide objects (marked as such in the list below) can be infinitely nested.
87
+
88
+ % Syntax:
89
+ \object_name
90
+ \object_name { ... }
91
+ \object_name value
92
+ \object_name value { ... }
93
+
94
+ The shortcut syntax `\object value` assigns `value` to the first property
95
+ compatible with the value's type.
96
+
97
+ ### Object List
98
+
99
+ **(Anywhere)** Load another file at the current location:
100
+
101
+ \include "relative/path/to/file.sfp"
102
+ \include {
103
+ source = "relative/path/to/file.sfp"
104
+ }
105
+
106
+ **(Anywhere)** Print debug information about any value to standard output:
107
+
108
+ \debug any_value
109
+
110
+ **(Top-level, required, maximum 1)** Configure the output window:
111
+
112
+ \layout 1920x1080
113
+ \layout {
114
+ size = 1920x1080
115
+ fullscreen = :true % optional
116
+ }
117
+
118
+ **(Top-level, required)** Create a slide:
119
+
120
+ \slide { ... }
121
+
122
+ **(Slide)** Animation between slides:
123
+
124
+ \animation "fade" { ... }
125
+ \animation {
126
+ name = "fade"
127
+ %{
128
+ other possible values are:
129
+ name = "slide right"
130
+ name = "slide left"
131
+ name = "slide down"
132
+ name = "slide up"
133
+ name = "zoom"
134
+ %}
135
+ duration = 400 % in ms (optional)
136
+ }
137
+ *Note: The animation is applied only to nested objects.*
138
+
139
+ **(Slide)** Add an image:
140
+
141
+ \image "relative/path/to/image.png"
142
+ \image {
143
+ source = "relative/path/to/image.png"
144
+ size = 0x0 % automatic if 0 (optional)
145
+ color = #FFFFFFFF % color filter (optional)
146
+ position = 0x0 % optional
147
+ z_order = 0 % optional
148
+ }
149
+
150
+ **(Slide)** Add a rectangle:
151
+
152
+ \rect 100x100
153
+ \rect {
154
+ size = 100x100
155
+ fill = #FFFFFFFF % optional
156
+ position = 0x0 % optional
157
+ z_order = 0 % optional
158
+ }
159
+
160
+ **(Slide)** Play an audio file:
161
+
162
+ \song "relative/path/to/audio.ogg"
163
+ \song {
164
+ source = "relative/path/to/audio.ogg"
165
+ volume = 100 % optional
166
+ loop = :true % optional
167
+ }
168
+
169
+ **(Slide)** Add text:
170
+
171
+ \text "Hello World!"
172
+ \text {
173
+ content = "Hello World!"
174
+ color = #FFFFFFFF % optional
175
+ font = "sans" % font name or relative font path (optional)
176
+ % font = "./my_font.ttf"
177
+ height = 20 % font height in pixels (optional)
178
+ width = 0 % maximum width (automatic if 0, optional)
179
+ spacing = 0 % line spacing (optional)
180
+ align = "left" % optional
181
+ %{
182
+ other possible values are:
183
+ align = "right"
184
+ align = "center"
185
+ align = "justify"
186
+ %}
187
+ position = 0x0 % optional
188
+ z_order = 0 % optional
189
+ }
190
+
191
+ ### Filters
192
+ Filters are like methods in an object-oriented programming language.
193
+ They can be chained infinitely.
194
+
195
+ variable = (filter)value
196
+ variable = (second_filter)(first_filter)value
197
+
198
+ Point to integer:
199
+
200
+ point = 1920x1080
201
+ x = (x)point
202
+ % x is 1920
203
+
204
+ y = (y)point
205
+ % y is 1080
206
+
207
+ Integer to point:
208
+
209
+ point = (x)1920
210
+ % point is 1920x0
211
+
212
+ point += (y)1080
213
+ % point is 1920x1080
214
+
215
+ Line count:
216
+
217
+ lines = (lines)"Lorem\nIpsum"
218
+ % lines is 2
219
+
220
+ ### Templates
221
+ Custom objects can be created using templates.
222
+
223
+ template_name = \object_name { ... }
224
+ \&template_name
225
+
226
+ % creation
227
+ slide_template = \slide {
228
+ \image background { size = 1920x1080; }
229
+ \text title { height = 72; }
230
+ }
231
+
232
+ % usage
233
+ \&slide_template {
234
+ title = "Hello World!"
235
+ background = "relative/path/to/image.png"
236
+ }
237
+
238
+ Equivalent of the above example without using templates:
239
+
240
+ \slide {
241
+ title = "Hello World!"
242
+ background = "relative/path/to/image.png"
243
+ \image background { size = 1920x1080; }
244
+ \text title { height = 72; }
245
+ }
246
+
247
+ ## Contributing
248
+
249
+ 1. [Fork it](https://bitbucket.org/cfi30/slidefield/fork)
250
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
251
+ 3. Test your changes (`rake`)
252
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
253
+ 5. Push to the branch (`git push origin my-new-feature`)
254
+ 6. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ task :default => [:test]
5
+ Rake::TestTask.new do |t|
6
+ t.test_files = FileList['test/helper.rb', 'test/test_*.rb']
7
+ end
data/bin/slidefield ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env ruby
2
+ # This program is free software: you can redistribute it and/or modify
3
+ # it under the terms of the GNU General Public License as published by
4
+ # the Free Software Foundation, either version 3 of the License, or
5
+ # (at your option) any later version.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
14
+
15
+ require 'slidefield'
16
+ require 'optparse'
17
+
18
+ def parse_opts
19
+ options = []
20
+
21
+ OptionParser.new do |opts|
22
+ opts.program_name = "SlideField"
23
+ opts.version = SlideField::VERSION
24
+ opts.banner = "Usage: slidefield [options] [file ...]"
25
+
26
+ opts.on '-c', '--check', "Check input only" do
27
+ options << :check
28
+ end
29
+
30
+ opts.on_tail '-v', '--version', "Show version number and copyright" do
31
+ puts opts.ver
32
+ puts <<GPL
33
+ Copyright (C) 2014 by Christian Fillion
34
+
35
+ This program is free software; you can redistribute it and/or
36
+ modify it under the terms of the GNU General Public License as
37
+ published by the Free Software Foundation, either version 3 of
38
+ the License, or (at your option) any later version.
39
+
40
+ This program is distributed in the hope that it will be useful,
41
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
42
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43
+ General Public License for more details.
44
+ GPL
45
+ exit
46
+ end
47
+
48
+ opts.on_tail '-h', '--help', "Show this message" do
49
+ puts opts.help
50
+ exit
51
+ end
52
+ end.parse!
53
+
54
+ options
55
+ end
56
+
57
+ begin
58
+ begin
59
+ options = parse_opts
60
+ rescue OptionParser::InvalidOption => e
61
+ raise SlideField::Error, e
62
+ end
63
+
64
+ files = ARGV
65
+
66
+ # read from standard input by default
67
+ files << '-' if files.empty?
68
+
69
+ files.each {|file|
70
+ interpreter = SlideField::Interpreter.new
71
+ if '-' == file
72
+ interpreter.run_string STDIN.read
73
+ else
74
+ path = File.absolute_path file
75
+ interpreter.run_file path
76
+ end
77
+
78
+ next if options.include? :check
79
+
80
+ project_root = interpreter.root
81
+ viewer = SlideField::Viewer.new project_root
82
+ viewer.caption = project_root.context
83
+ viewer.show
84
+ }
85
+ rescue SlideField::Error => e
86
+ warn "#{e.class}: #{e}"
87
+ rescue Interrupt
88
+ puts
89
+ end
Binary file
Binary file
Binary file
@@ -0,0 +1,7 @@
1
+ \include "variables.sfi"
2
+ \include "templates.sfi"
3
+
4
+ \layout layout_size
5
+
6
+ \include "slides/mountains.sfi"
7
+ \include "slides/deserts.sfi"
@@ -0,0 +1,19 @@
1
+ \&slide_tpl {
2
+ title = "Sahara"
3
+
4
+ infos = "<b>Area:</b> 9,400,000 km²\n"
5
+ infos += "<b>Notes:</b> The world's hottest desert"
6
+
7
+ background_src = "../assets/sahara.jpg"
8
+ background_link = "https://en.wikipedia.org/wiki/File:Sahara_satellite_hires.jpg"
9
+ }
10
+
11
+ \&slide_tpl {
12
+ title = "Gobi"
13
+
14
+ infos = "<b>Area:</b> 1,295,000 km²\n"
15
+ infos += "<b>Notes:</b> The expansion of the Gobi is\nattributed mostly to human activities"
16
+
17
+ background_src = "../assets/gobi.jpg"
18
+ background_link = "https://en.wikipedia.org/wiki/File:Khongoryn_Els,_Gurvansaikhan_NP,_Gobi_desert,_Mongolia.jpg"
19
+ }
@@ -0,0 +1,25 @@
1
+ \&slide_tpl {
2
+ title = "Mount Everest"
3
+
4
+ infos = "<b>Country:</b> Nepal\n"
5
+ infos += "<b>Elevation:</b> 8,848 m\n"
6
+ infos += "<b>First ascent:</b> 29 May 1953\n"
7
+ infos += "<b>Easiest route:</b> South Col\n"
8
+ infos += "<b>Notes:</b> Earth's highest mountain"
9
+
10
+ background_src = "../assets/mount_everest.jpg"
11
+ background_link = "https://en.wikipedia.org/wiki/File:Mount_Everest_as_seen_from_Drukair2_PLW_edit.jpg"
12
+ }
13
+
14
+ \&slide_tpl {
15
+ title = "K2"
16
+
17
+ infos = "<b>Country:</b> Pakistan\n"
18
+ infos += "<b>Elevation:</b> 8,611 m\n"
19
+ infos += "<b>First ascent:</b> 31 July 1954\n"
20
+ infos += "<b>Easiest route:</b> Abruzzi Spur\n"
21
+ infos += "<b>Notes:</b> The mountain was first\nsurveyed by a European team in 1856"
22
+
23
+ background_src = "../assets/K2.jpg"
24
+ background_link = "https://en.wikipedia.org/wiki/File:K2_2006b.jpg"
25
+ }
@@ -0,0 +1,95 @@
1
+ background_tpl = \image {
2
+ size = layout_size
3
+ }
4
+
5
+ title_tpl = \text {
6
+ color = #FFFFFFFF
7
+ font = title_font
8
+ height = 100
9
+ position = 100x70
10
+ z_order = 1
11
+
12
+ % support alignment
13
+ x = (x)position
14
+ x *= 2
15
+ width = (x)layout_size
16
+ width -= x
17
+
18
+ % shadow
19
+ \text #00000099 {
20
+ position += 2x2
21
+ z_order -= 1
22
+ }
23
+ }
24
+
25
+ infobox_tpl = \rect {
26
+ padding = 10
27
+ text_height = 40
28
+ z_order = 1
29
+
30
+ box_height = (lines)content
31
+ box_height *= text_height
32
+ box_height += padding
33
+
34
+ size = 650x0
35
+ size += (y)box_height
36
+
37
+ position = layout_size
38
+ position -= size
39
+ position /= 2x1
40
+ position -= 0x100
41
+
42
+ fill = #FFFFFF69
43
+
44
+ \text {
45
+ position += (x)padding
46
+ position += (y)padding
47
+
48
+ height = text_height
49
+ color = #011010FF
50
+ font = info_font
51
+
52
+ % shadow
53
+ \text {
54
+ position += 1x1
55
+ color = #FFFFFF99
56
+ z_order -= 1
57
+ }
58
+ }
59
+ }
60
+
61
+ credit_tpl = \text {
62
+ position = 10x-30
63
+ position += (y)(y)layout_size
64
+
65
+ color = #FFFFFFFF
66
+ z_order = 1
67
+
68
+ \text {
69
+ position += 1x1
70
+ color = #000000FF
71
+ z_order -= 1
72
+ }
73
+ }
74
+
75
+ slide_tpl = \slide {
76
+ \animation "fade" {
77
+ \&background_tpl background_src
78
+ }
79
+
80
+ \&title_tpl {
81
+ content = "<b>"
82
+ content += title
83
+ }
84
+
85
+ \animation "slide left" {
86
+ \&infobox_tpl {
87
+ content = infos
88
+ }
89
+ }
90
+
91
+ \&credit_tpl {
92
+ content = "<b>Photo Credit:</b> "
93
+ content += background_link
94
+ }
95
+ }
@@ -0,0 +1,6 @@
1
+ % ---- LAYOUT ---- %
2
+ layout_size = 1920x1080
3
+
4
+ % ---- SLIDES ---- %
5
+ title_font = "URW Bookman L"
6
+ info_font = "monospace"
@@ -0,0 +1,43 @@
1
+ layout_size = 1366x768
2
+
3
+ \layout layout_size
4
+
5
+ \slide {
6
+ \text "Hello World!" { height = 50; }
7
+ \text "Press <b>Enter</b> to display the next slide" {
8
+ position = 0x50
9
+ }
10
+ }
11
+
12
+ \slide {
13
+ \text "Second Slide"
14
+ \text "Press <b>Backspace</b> to return to the previous slide" {
15
+ position = 0x30
16
+ width = 200
17
+ }
18
+
19
+ \text "This example contains 3 slides.\n(Press <b>Enter</b> again)" {
20
+ position = 0x70
21
+ width = (x)layout_size
22
+ align = "right"
23
+ }
24
+ }
25
+
26
+ \slide {
27
+ \rect {
28
+ fill = #FFFFFFFF % RRGGBBAA
29
+ size = layout_size
30
+ }
31
+
32
+ \image "ruby-logo.png" {
33
+ position = layout_size
34
+ position -= 62x62
35
+ position /= 2x2
36
+ }
37
+
38
+ \text {
39
+ content = "Last Slide\nPress <b>Escape</b> to quit"
40
+ color = #000000FF
41
+ font = "monospace"
42
+ }
43
+ }
Binary file
@@ -0,0 +1,104 @@
1
+ class SlideField::Animator
2
+ attr_accessor :current, :forward
3
+
4
+ def initialize(layout_size)
5
+ @layout_size = layout_size
6
+ reset
7
+ end
8
+
9
+ def need_redraw?
10
+ @animations.each {|k,v| return true if v.enabled }
11
+ @animations.empty?
12
+ end
13
+
14
+ def reset
15
+ @animations = {}
16
+ end
17
+
18
+ def frame(*args)
19
+ struct = Struct.new :time, :current?, :forward?
20
+ @frame = struct.new *args
21
+ yield
22
+ @frame = nil
23
+ end
24
+
25
+ def transform(obj)
26
+ raise "Can not animate outside a frame" unless @frame
27
+
28
+ tr_struct = Struct.new :skip_draw?, :x_offset, :y_offset, :scale, :opacity
29
+ tr = tr_struct.new false, 0, 0, 1.0, 1.0
30
+
31
+ anim = animation_for obj.ancestor(:animation)
32
+
33
+ # no animation
34
+ return tr if anim.nil?
35
+
36
+ elapsed = @frame.time - anim.start_time
37
+ position = elapsed / anim.duration
38
+ anim.enabled = false if position > 1.0
39
+
40
+ # animation finished
41
+ unless anim.enabled
42
+ tr[:skip_draw?] = !@frame.current? # don't draw the previous slide anymore
43
+ return tr
44
+ end
45
+
46
+ width, height = @layout_size
47
+
48
+ case anim.name
49
+ when "fade"
50
+ if @frame.current?
51
+ tr.opacity = position
52
+ else
53
+ tr.opacity = 1.0 - position
54
+ end
55
+ when "slide right"
56
+ tr.x_offset = slide_offset position, width, false
57
+ when "slide left"
58
+ tr.x_offset = slide_offset position, width, true
59
+ when "slide down"
60
+ tr.y_offset = slide_offset position, height, false
61
+ when "slide up"
62
+ tr.y_offset = slide_offset position, height, true
63
+ when "zoom"
64
+ if @frame.current?
65
+ tr.scale = position
66
+ else
67
+ tr.scale = 1.0 - position
68
+ end
69
+ else
70
+ # the validator has missed ?!
71
+ # TODO: validate at interpret time
72
+ raise SlideField::RuntimeError,
73
+ "Unsupported animation '#{anim.name}'"
74
+ end
75
+
76
+ tr
77
+ end
78
+
79
+ private
80
+ def animation_for(data)
81
+ return @animations[data] if @animations.has_key? data
82
+
83
+ anim_struct = Struct.new :enabled, :start_time, :name, :duration
84
+ anim = anim_struct.new false, 0.0, '', 0
85
+
86
+ if data
87
+ anim.enabled = true
88
+ anim.start_time = @frame.time.to_f
89
+ anim.name = data.get :name
90
+ anim.duration = data.get :duration
91
+ end
92
+
93
+ @animations[data] = anim
94
+ end
95
+
96
+ def slide_offset(position, size, inverse)
97
+ inverse = !inverse unless @frame.forward?
98
+
99
+ offset = size * position
100
+ offset -= size if @frame.current?
101
+ offset = 0 - offset if inverse
102
+ offset
103
+ end
104
+ end
@@ -0,0 +1,6 @@
1
+ module SlideField
2
+ class Error < RuntimeError; end
3
+ class ParseError < Error; end
4
+ class InterpreterError < Error; end
5
+ class RuntimeError < Error; end
6
+ end