--- /dev/null
+--
+$Id: AUTHORS 1 2005-03-26 01:32:38Z tilman $
+++
+
+Tilman Sauerbeck (tilman at code-monkey de)
--- /dev/null
+--
+$Id: COPYING 1 2005-03-26 01:32:38Z tilman $
+++
+
+Copyright (c) 2005 Tilman Sauerbeck (tilman at code-monkey de)
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+--
+$Id: ChangeLog 1 2005-03-26 01:32:38Z tilman $
+++
+
+2005-03-22 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/app.rb: The default extension for Edje files is
+ 'edj' now
+2005-03-20 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/redact.rb, test/{red_rect,crossfade}.rb:
+ Use symbols for part/program types. Also, you need to provide
+ the part/program type now, there's no default anymore. This
+ fixes/works around the problem where you accidentally defined
+ a part when you just wanted to get a reference to an existing
+ part
+
+2005-03-19 Tilman Sauerbeck (tilman at code-monkey de)
+ * test/crossfade.rb: Updated to work with
+ TextDescription#set_fit change
+
+2005-03-17 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/app.rb: Store the source of files that are read
+ with File.read, too
+ * lib/redact/{source,app}.rb: Write a fontmap, so edje_decc can
+ dump the fonts that are used in the Edje
+ * lib/redact/part.rb: Added TextDescription#set_fit
+
+2005-03-16 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/{source,app}.rb: Write theme source to EET file,
+ too
+ * bin/redact, lib/redact/app.rb, test/test_basic.rb: Improved
+ commandline option handling
+ * lib/redact/redact.rb: Set the 'compiler' value in the
+ Edje_File EDD
+ * lib/redact/app.rb: Add support for the 'image_dir' and 'font_dir'
+ options. They aren't evaluated yet, though.
+
+2005-03-14 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/redact.rb: Fixed stupid exceptions
+
+2005-03-06 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/program.rb: Fixed a typo that resulted in an invalid
+ reader method
+ * lib/redact/{redact,program}.rb: Added support for basic
+ programs (signal, source, after parameters only)
+ * Rakefile: use FileUtils to for the install task
+
+2005-03-02 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/part.rb: Set the default offset for rel2 to -1,-1
+ * lib/redact/part.rb: Enable smoothing by default for non-image
+ parts, too.
+ * lib/redact/part.rb: Use sane defaults for the other fill
+ parameters
+ * lib/redact/part.rb: Fixed default values for outline and
+ shadow color
+
+2005-02-26 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/app.rb: Don't indent empty lines of Embryo code
+ * lib/redact/{app, redact, part}.rb: Added support for embedded
+ fonts
+ * lib/redact/redact.rb: When doing part/program-lookups in
+ Embryo code, use non-greedy matching of quotes
+ * lib/redact/program.rb: signal and source are set to empty
+ strings by default now, instead of nil
+ * lib/redact/part.rb: Rename color2 and color3 to outline_color
+ and shadow_color, respectively.
+ * lib/redact/part.rb: Make outline_color and shadow_color
+ writeable
+ * lib/redact/part.rb: Renamed clip_to to clip and made it
+ readable
+ * lib/redact/part.rb: Made TextDescription::text_min writeable
+ * lib/redact/part.rb: Made TextDescription::text_align writeable
+ * lib/redact/part.rb: Added support for tween images
+ * lib/redact/{redact, part}.rb: Split Part into various classes
+ * lib/redact/{redact, part, program}.rb: Code cleanup
+ * lib/redact/{redact, part}.rb: Don't make Part::type readable
+
+2005-02-23 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/app.rb: Use edje-config to figure out the
+ Embryo include directory
+
+2005-02-22 Tilman Sauerbeck (tilman at code-monkey de)
+ * lib/redact/app.rb: Enable zlib compression for the edje_file
+ and collections EET entries
+ * lib/redact/app.rb, lib/redact/redact.rb: Reworked the way
+ Embryo scripts are saved/processed
+ * lib/redact/app.rb: Delete the temporary redact.sma file when
+ we're done with it
--- /dev/null
+# $Id: Rakefile 1 2005-03-26 01:32:38Z tilman $
+
+require "rake/clean"
+require "rake/testtask"
+
+CLOBBER.include(FileList["test/*.eet"])
+
+sitelibdir = Config::CONFIG["sitelibdir"]
+destdir = "#{ENV["DESTDIR"]}"
+prefix = ENV["PREFIX"] || "/usr/local"
+
+task :install do |t|
+ ddir = destdir + prefix + "/bin"
+ FileUtils::Verbose.install("bin/redact", ddir, :mode => 0755)
+
+ ddir = destdir + sitelibdir + "/redact"
+
+ FileUtils::Verbose.mkdir(ddir) unless File.directory?(ddir)
+
+ ["app", "part", "program", "redact"].each do |file|
+ FileUtils::Verbose.install("lib/redact/#{file}.rb", ddir,
+ :mode => 0644)
+ end
+end
+
+task :test
+
+Rake::TestTask.new do |t|
+ t.libs << "lib"
+ t.test_files = FileList["test/test*.rb"]
+ t.verbose = true
+end
--- /dev/null
+--
+$Id: TODO 1 2005-03-26 01:32:38Z tilman $
+++
+
+* Add support for the various 'fill' properties in ImageDescription
+* Respect --image_dir and --font_dir command line switches
--- /dev/null
+#!/usr/bin/ruby -w
+
+require "redact/app"
+
+Redact::App.new(ARGV).run
--- /dev/null
+#--
+# $Id: app.rb 1 2005-03-26 01:32:38Z tilman $
+#
+# Copyright (c) 2005 Tilman Sauerbeck (tilman at code-monkey de)
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require "redact/redact.rb"
+require "redact/source.rb"
+require "ftools"
+require "pathname"
+require "ostruct"
+require "optparse"
+
+SCRIPT_LINES__ = {}
+
+module Redact
+ class App
+ def initialize(args)
+ @filename = nil
+ @options = OpenStruct.new
+ @option_parser = parse_args(args)
+
+ @options.input = args.first
+ if @options.input.nil?
+ puts @option_parser.help
+ exit
+ end
+
+ @options.output ||= @options.input.sub(/.[^.]+$/, ".edj")
+ end
+
+ def run
+ EDJE.clear
+ SCRIPT_LINES__.clear
+
+ begin
+ load @options.input
+ rescue LoadError
+ raise("Cannot load '#{@options.input}'")
+ end
+
+ @filename = Pathname.new(@options.input).cleanpath.to_s
+
+ if EDJE.collections.empty?
+ raise("No collections found")
+ end
+
+ amx = compile_embryo
+
+ Eet::File.open(@options.output, "w") do |ef|
+ dump_amx(amx, ef)
+
+ dump_header(ef)
+ dump_collections(ef)
+ dump_fonts(ef)
+ dump_images(ef)
+ dump_source(ef)
+ dump_fontmap(ef)
+ end
+ end
+
+ private
+ def parse_args(args)
+ OptionParser.new do |o|
+ o.banner = "Usage: redact [options] INPUT_FILE"
+
+ o.separator ""
+ o.separator "Specific options:"
+
+ o.on("-o", "--output OUTPUT_FILE",
+ "Write Edje to OUTPUT_FILE") do |file|
+ @options.output = file
+ end
+
+ o.on("--image_dir IMAGE_DIR",
+ "Add IMAGE_DIR to the image lookup path") do |dir|
+ @options.image_dir = dir
+ end
+
+ o.on("--font_dir FONT_DIR",
+ "Add FONT_DIR to the font lookup path") do |dir|
+ @options.font_dir = dir
+ end
+
+ o.separator ""
+ o.separator "Common options:"
+
+ o.on_tail("-h", "--help", "Show this message") do
+ puts o
+ exit
+ end
+
+ o.on_tail("--version", "Show version") do
+ puts <<EOT
+redact #{Redact::VERSION}
+
+Copyright (c) 2005 Tilman Sauerbeck (tilman at code-monkey de)
+EOT
+ exit
+ end
+
+ o.parse!(args)
+ end
+ end
+
+ def compile_embryo
+ ret = {}
+
+ EDJE.collections.each_value do |col|
+ next unless col.has_embryo?
+
+ File.open("/tmp/redact.sma", "w") do |tf|
+ tf.puts "#include <edje>"
+ dump_sma(tf, col)
+ tf.flush
+
+ out = "/tmp/redact.amx"
+ File.rm_f(out)
+
+ incl = `edje-config --datadir`.strip
+ c = "embryo_cc " +
+ "-i #{incl}/include " +
+ "-o #{out} #{tf.path}"
+ system(c)
+
+ ret[col.id] = IO.read(out)
+ File.rm_f(out)
+ File.unlink(tf.path)
+ end
+ end
+
+ ret
+ end
+
+ def dump_sma(tf, col)
+ if col.has_embryo?(false)
+ tf.puts col.script.to_embryo(col)
+ end
+
+ col.programs.each_value do |p|
+ next unless p.is_a?(ExecScriptProgram)
+
+ s = p.script.to_embryo(col).gsub(/^(.+)$/, "\t\\1")
+
+ tf.puts <<EOT
+public _p#{p.id}(sig[], src[])
+{
+#{s}
+}
+EOT
+ end
+ end
+
+ def dump_amx(amx, ef)
+ amx.each do |id, code|
+ ef.write("scripts/#{id}", code)
+ end
+ end
+
+ def dump_header(ef)
+ ef.write("edje_file", EDJE.to_eet)
+ end
+
+ def dump_collections(ef)
+ EDJE.collections.each_value do |col|
+ ef.write("collections/#{col.id}", col.to_eet)
+ end
+ end
+
+ def dump_fonts(ef)
+ EDJE.font_dir.each do |entry|
+ ef.write("fonts/#{entry.filename}",
+ File.read(entry.filename))
+ end
+ end
+
+ def dump_images(ef)
+ EDJE.image_dir.each do |entry|
+ ef.write_image("images/#{entry.id}",
+ entry.image.data_for_reading_only,
+ entry.image.width, entry.image.height,
+ entry.image.has_alpha?)
+ end
+ end
+
+ def dump_source(ef)
+ s = SourceFiles.new
+
+ SCRIPT_LINES__.each do |file, value|
+ sane = Pathname.new(file).cleanpath.to_s
+ method = (sane == @filename) ? :unshift : :push
+ s.send(method, SourceFile.new(sane, value.join))
+
+ # include files that are with File.read, too
+ value.join.grep(/File\.read\(\"(.+)\"\)/) do
+ sane = Pathname.new($1).cleanpath.to_s
+ s << SourceFile.new(sane, File.read(sane))
+ end
+ end
+
+ ef.write("edje_sources", s.to_eet)
+ end
+
+ def dump_fontmap(ef)
+ fm = EDJE.font_dir.inject(FontMap.new) do |a, entry|
+ a << FontMapEntry.new(entry)
+ end
+
+ ef.write("edje_source_fontmap", fm.to_eet)
+ end
+ end
+end
--- /dev/null
+#--
+# $Id: part.rb 1 2005-03-26 01:32:38Z tilman $
+#
+# Copyright (c) 2005 Tilman Sauerbeck (tilman at code-monkey de)
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module Redact
+ class Part
+ TYPE_RECTANGLE = 1
+ TYPE_TEXT = 2
+ TYPE_IMAGE = 3
+ TYPE_SWALLOW = 4
+
+ include Comparable
+
+ attr_reader :collection, :id, :name, :dragable, :clip
+ attr_accessor :mouse_events, :repeat_events
+
+ def initialize(collection, id, name)
+ @collection = collection
+ @id = id
+
+ @name = name.to_str.dup.freeze
+ @type = TYPE_RECTANGLE
+ @mouse_events = true
+ @repeat_events = false
+ @clip = nil
+ @dragable = Dragable.new(self)
+
+ @descriptions = Hash.new do |h, k|
+ desc, value = k.split("\0")
+ value = value.to_f
+
+ h[k] = description_class.new(desc, value)
+ end
+ end
+
+ def <=>(b)
+ @id <=> b.id
+ end
+
+ def clip=(part)
+ if self == part
+ raise(ArgumentError, "cannot clip part to itself")
+ elsif part.nil?
+ @clip = nil
+ elsif part.collection != @collection
+ raise(ArgumentError, "parts' collections not identical")
+ else
+ @clip = part
+ end
+ end
+
+ def description(name = "default", value = 0.0)
+ d = @descriptions[desc_key(name, value)]
+
+ block_given? ? (yield d) : d
+ end
+
+ protected
+ def description_class
+ Description
+ end
+
+ def to_eet_name
+ "Edje_Part"
+ end
+
+ def to_eet_properties
+ other_desc = @descriptions.dup
+ other_desc.delete(desc_key("default", 0.0))
+
+ confine_id = @dragable.confine.nil? ?
+ -1 : @dragable.confine.id
+
+ {"name" => [@name],
+ "id" => [@id],
+ "type" => [@type, :char],
+ "effect" => [0, :char],
+ "mouse_events" => [@mouse_events],
+ "repeat_events" => [@repeat_events],
+ "clip_to_id" => [@clip.nil? ? -1 : @clip.id],
+ "default_desc" => [description("default", 0.0)],
+ "other_desc" => [other_desc],
+ "dragable.x" => [@dragable.enabled[0], :char],
+ "dragable.step_x" => [@dragable.step[0]],
+ "dragable.count_x" => [@dragable.count[0]],
+ "dragable.y" => [@dragable.enabled[1], :char],
+ "dragable.step_y" => [@dragable.step[1]],
+ "dragable.count_y" => [@dragable.count[1]],
+ "dragable.counfine_id" => [confine_id]} # not a typo!
+ end
+
+ private
+ def desc_key(name, value)
+ name + "\0" + value.to_s
+ end
+ end
+
+ class SwallowPart < Part
+ def initialize(collection, id, name)
+ super
+
+ @type = TYPE_SWALLOW
+ end
+ end
+
+ class TextPart < Part
+ EFFECT_NONE = 0
+ EFFECT_PLAIN = 1
+ EFFECT_OUTLINE = 2
+ EFFECT_SOFT_OUTLINE = 3
+ EFFECT_SHADOW = 4
+ EFFECT_SOFT_SHADOW = 5
+ EFFECT_OUTLINE_SHADOW = 6
+ EFFECT_OUTLINE_SOFT_SHADOW = 7
+
+ attr_accessor :effect
+
+ def initialize(collection, id, name)
+ super
+
+ @type = TYPE_TEXT
+ @effect = EFFECT_NONE
+ end
+
+ protected
+ def description_class
+ TextDescription
+ end
+
+ def to_eet_properties
+ super.merge!({"effect" => [@effect, :char]})
+ end
+ end
+
+ class ImagePart < Part
+ def initialize(collection, id, name)
+ super
+
+ @type = TYPE_IMAGE
+ end
+
+ protected
+ def description_class
+ ImageDescription
+ end
+ end
+
+ class Dragable
+ attr_reader :enabled, :step, :count, :confine
+
+ def initialize(part)
+ @part= part
+
+ @enabled = [false, false]
+ @step = [0, 0]
+ @count = [0, 0]
+ @confine = nil
+ end
+
+ def confine=(part)
+ if part == self
+ raise(ArgumentError, "cannot confine part to itself")
+ elsif !part.nil? && part.collection != @part.collection
+ raise(ArgumentError, "parts' collections not identical")
+ else
+ @confine = part
+ end
+ end
+ end
+
+ class Relation
+ attr_reader :rel, :to_id, :offset
+
+ def initialize(rel, offset)
+ @rel = [rel, rel]
+ @to_id = [-1, -1]
+ @offset = [offset, offset]
+ end
+
+ def set_rel(x, y)
+ @rel = [x, y]
+ end
+
+ def set_offset(x, y)
+ @offset = [x, y]
+ end
+
+ def to=(part)
+ @to_id = [].fill(part.nil? ? -1 : part.id, 0..1)
+ end
+ end
+
+ class Description
+ attr_reader :rel
+ attr_accessor :visible
+
+ def initialize(name = "default", value = 0.0)
+ @name = name.to_str.dup.freeze
+ @value = value.freeze
+ @visible = true
+ @align = [0.5, 0.5]
+ @min = [0, 0]
+ @max = [-1, -1]
+ @step_x = 0
+ @step_y = 0
+ @rel = [Relation.new(0.0, 0), Relation.new(1.0, -1)]
+ @color = [].fill(255, 0..3)
+ @color_class = ""
+ end
+
+ def set_align(x = 0.5, y = 0.5)
+ @align = [x, y]
+ end
+
+ def set_size(w, h)
+ set_min(w, h)
+ set_max(w, h)
+ end
+
+ def set_min(w, h)
+ @min = [w, h]
+ end
+
+ def set_max(w, h)
+ @max = [w, h]
+ end
+
+ def color=(c)
+ @color = parse_hex_color(c)
+ end
+
+ protected
+ def parse_hex_color(c)
+ md = c.match(/^#?(([[:xdigit:]]{2}){1,4})$/)
+ if md.nil?
+ raise(ArgumentError, "Argument is not a hex string")
+ end
+
+ pairs = md.captures.shift.split(/(..)/).delete_if do |item|
+ item == ""
+ end
+
+ pairs.push("00") while pairs.length < 3
+ pairs.push("ff") if pairs.length == 3
+
+ pairs.map { |p| p.hex }
+ end
+
+ def to_eet_name
+ "Edje_Part_Description"
+ end
+
+ def to_eet_properties
+ {"state.name" => [@name],
+ "state.value" => [@value, :double],
+ "visible" => [@visible],
+ "align.x" => [@align[0], :double],
+ "align.y" => [@align[1], :double],
+ "min.w" => [@min[0]],
+ "min.h" => [@min[1]],
+ "max.w" => [@max[0]],
+ "max.h" => [@max[1]],
+ "step.x" => [@step_x],
+ "step.y" => [@step_y],
+ "aspect.min" => [0.0, :double],
+ "aspect.max" => [0.0, :double],
+ "aspect.prefer" => [0, :char],
+ "rel1.relative_x" => [@rel[0].rel[0], :double],
+ "rel1.relative_y" => [@rel[0].rel[1], :double],
+ "rel1.offset_x" => [@rel[0].offset[0]],
+ "rel1.offset_y" => [@rel[0].offset[1]],
+ "rel1.id_x" => [@rel[0].to_id[0]],
+ "rel1.id_y" => [@rel[0].to_id[1]],
+ "rel2.relative_x" => [@rel[1].rel[0], :double],
+ "rel2.relative_y" => [@rel[1].rel[1], :double],
+ "rel2.offset_x" => [@rel[1].offset[0]],
+ "rel2.offset_y" => [@rel[1].offset[1]],
+ "rel2.id_x" => [@rel[1].to_id[0]],
+ "rel2.id_y" => [@rel[1].to_id[1]],
+ "color_class" => [@color_class],
+ "color.r" => [@color[0], :char],
+ "color.g" => [@color[1], :char],
+ "color.b" => [@color[2], :char],
+ "color.a" => [@color[3], :char],
+
+ # image properties
+ "image.id" => [-1],
+ "image.tween_list" => [nil],
+ "border.l" => [0],
+ "border.r" => [0],
+ "border.t" => [0],
+ "border.b" => [0],
+ "fill.smooth" => [true],
+ "fill.pos_rel_x" => [0.0, :double],
+ "fill.pos_abs_x" => [0],
+ "fill.rel_x" => [1.0, :double],
+ "fill.abs_x" => [0],
+ "fill.pos_rel_y" => [0.0, :double],
+ "fill.pos_abs_y" => [0],
+ "fill.rel_y" => [1.0, :double],
+ "fill.abs_y" => [0],
+
+ # text properties
+ "color2.r" => [0, :char],
+ "color2.g" => [0, :char],
+ "color2.b" => [0, :char],
+ "color2.a" => [255, :char],
+ "color3.r" => [0, :char],
+ "color3.g" => [0, :char],
+ "color3.b" => [0, :char],
+ "color3.a" => [128, :char],
+ "text.text" => [""],
+ "text.text_class" => [""],
+ "text.font" => [""],
+ "text.size" => [0],
+ "text.fit_x" => [false],
+ "text.fit_y" => [false],
+ "text.min_x" => [0],
+ "text.min_y" => [0],
+ "text.align.x" => [0.0, :double],
+ "text.align.y" => [0.0, :double],
+ "text.id_source" => [-1],
+ "text.id_text_source" => [-1]}
+ end
+ end
+
+ class Tween
+ def initialize(image)
+ @id = image.id
+ end
+
+ def to_eet_name
+ "Edje_Part_Image_Id"
+ end
+ end
+
+ class Tweens < Array
+ def <<(im)
+ image = EDJE.image_dir.find { |e| e.filename == im }
+ if image.nil?
+ image = ImageDirectoryEntry.new(im)
+ EDJE.image_dir << image
+ end
+
+ super(Tween.new(image))
+ end
+ end
+
+ class ImageDescription < Description
+ attr_reader :image, :auto_rel, :tweens
+
+ def initialize(name = "default", value = 0.0)
+ super
+
+ @image = nil
+ @tweens = Tweens.new
+ @border = [0, 0, 0, 0]
+ @fill_smooth = true
+ @auto_rel = false
+ end
+
+ def image=(im)
+ return if !@image.nil? && im == @image.filename
+
+ @image = EDJE.image_dir.find { |e| e.filename == im }
+ if @image.nil?
+ @image = ImageDirectoryEntry.new(im)
+ EDJE.image_dir << @image
+ end
+
+ self.auto_rel = @auto_rel
+ end
+
+ def auto_rel=(b)
+ @auto_rel = b
+
+ if @auto_rel && !@image.nil?
+ off = @rel[0].offset
+
+ @rel[1].set_rel(0.0, 0.0)
+ @rel[1].set_offset(off[0] + @image.image.width - 1,
+ off[1] + @image.image.height - 1)
+ end
+ end
+
+ def set_border(l = 0, r = 0, t = 0, b = 0)
+ @border = [r, r, t, b]
+ end
+
+ def to_eet_properties
+ super.merge!(
+ {"image.id" => [@image.nil? ? -1 : @image.id],
+ "image.tween_list" => [@tweens],
+ "border.l" => [@border[0]],
+ "border.r" => [@border[1]],
+ "border.t" => [@border[2]],
+ "border.b" => [@border[3]],
+ "fill.smooth" => [@fill_smooth],
+ "fill.pos_rel_x" => [0.0, :double],
+ "fill.pos_abs_x" => [0],
+ "fill.rel_x" => [1.0, :double],
+ "fill.abs_x" => [0],
+ "fill.pos_rel_y" => [0.0, :double],
+ "fill.pos_abs_y" => [0],
+ "fill.rel_y" => [1.0, :double],
+ "fill.abs_y" => [0]})
+ end
+ end
+
+ class TextDescription < Description
+ attr_reader :font
+ attr_accessor :text, :font_size
+
+ def initialize(name = "default", value = 0.0)
+ super
+
+ @outline_color = [0, 0, 0, 255]
+ @shadow_color = [0, 0, 0, 128]
+ @text = ""
+ @text_class = ""
+ @font = ""
+ @font_size = 0
+ @fit = [false, false]
+ @text_min = [false, false]
+ @text_align = [0.5, 0.5]
+ @text_id_source = -1
+ @text_id_text_source = -1
+ end
+
+ def set_fit(x = false, y = false)
+ @fit = [x, y]
+ end
+
+ def set_text_min(x = false, y = false)
+ @text_min = [x, y]
+ end
+
+ def set_text_align(x = 0.5, y = 0.5)
+ @text_align = [x, y]
+ end
+
+ def font=(f)
+ md = f.to_str.match(/.*\.ttf/)
+ unless md.nil?
+ found = EDJE.font_dir.find { |font| font.filename == f }
+ if found.nil?
+ EDJE.font_dir << FontDirectoryEntry.new(f)
+ end
+ end
+
+ @font = f.dup
+ end
+
+ def outline_color=(c)
+ @outline_color = parse_hex_color(c)
+ end
+
+ def shadow_color=(c)
+ @shadow_color = parse_hex_color(c)
+ end
+
+ def to_eet_properties
+ super.merge!(
+ {"color2.r" => [@outline_color[0], :char],
+ "color2.g" => [@outline_color[1], :char],
+ "color2.b" => [@outline_color[2], :char],
+ "color2.a" => [@outline_color[3], :char],
+ "color3.r" => [@shadow_color[0], :char],
+ "color3.g" => [@shadow_color[1], :char],
+ "color3.b" => [@shadow_color[2], :char],
+ "color3.a" => [@shadow_color[3], :char],
+ "text.text" => [@text],
+ "text.text_class" => [@text_class],
+ "text.font" => [@font],
+ "text.size" => [@font_size],
+ "text.fit_x" => [@fit[0]],
+ "text.fit_y" => [@fit[1]],
+ "text.min_x" => [@text_min[0]],
+ "text.min_y" => [@text_min[1]],
+ "text.align.x" => [@text_align[0], :double],
+ "text.align.y" => [@text_align[1], :double],
+ "text.id_source" => [@text_id_source],
+ "text.id_text_source" => [@text_id_text_source]})
+ end
+ end
+end
--- /dev/null
+#--
+# $Id: program.rb 1 2005-03-26 01:32:38Z tilman $
+#
+# Copyright (c) 2005 Tilman Sauerbeck (tilman at code-monkey de)
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module Redact
+ class Program
+ TYPE_BASE = 0
+ TYPE_SET_STATE = 1
+ TYPE_STOP_PROGRAM = 2
+ TYPE_EMIT_SIGNAL = 3
+ #TYPE_SET_DRAG_VAL = 4
+ #TYPE_STEP_DRAG_VAL = 5
+ #TYPE_PAGE_DRAG_VAL = 6
+ TYPE_EXEC_SCRIPT = 7
+
+ include Comparable
+
+ attr_reader :collection, :id, :name, :after
+ attr_accessor :signal, :source, :in_from, :in_range
+
+ def initialize(collection, id, name)
+ @collection = collection
+ @id = id
+
+ @name = name.to_str.dup.freeze
+ @type = TYPE_BASE
+
+ @after = ProgramArgs.new(collection)
+ @in_from = 0.0
+ @in_range = 0.0
+ @signal = ""
+ @source = ""
+ end
+
+ def <=>(b)
+ @id <=> b.id
+ end
+
+ def to_eet_name
+ "Edje_Program"
+ end
+
+ def to_eet_properties
+ {"id" => [@id],
+ "name" => [@name],
+ "action" => [@type],
+ "signal" => [@signal],
+ "source" => [@source],
+ "in.from" => [@in_from, :double],
+ "in.range" => [@in_range, :double],
+ "after" => [@after]}
+ end
+ end
+
+ class SetStateProgram < Program
+ MODE_LINEAR = 1
+ MODE_SINUSOIDAL = 2
+ MODE_ACCELERATE = 3
+ MODE_DECELERATE = 4
+
+ attr_reader :targets
+ attr_accessor :state, :value, :mode, :time
+
+ def initialize(collection, id, name)
+ super
+
+ @type = TYPE_SET_STATE
+ @state = "default"
+ @value = 0.0
+ @mode = MODE_LINEAR
+ @time = 0.0
+ @targets = ProgramArgs.new(collection)
+ end
+
+ def to_eet_properties
+ super.merge!(
+ {"state" => [@state],
+ "value" => [@value, :double],
+ "tween.mode" => [@mode],
+ "tween.time" => [@time, :double],
+ "targets" => [@targets]})
+ end
+ end
+
+ class StopProgramProgram < Program
+ def initialize(collection, id, name)
+ super
+
+ @type = TYPE_STOP_PROGRAM
+ @targets = ProgramArgs.new(collection)
+ end
+
+ def to_eet_properties
+ super.merge!({"targets" => [@targets]})
+ end
+ end
+
+ class EmitSignalProgram < Program
+ attr_accessor :emission_signal, :emission_source
+
+ def initialize(collection, id, name)
+ super
+
+ @type = TYPE_EMIT_SIGNAL
+ @emission_signal = nil
+ @emission_source = nil
+ end
+
+ def to_eet_properties
+ super.merge!(
+ {"state" => [@emission_signal],
+ "state2" => [@emission_source]})
+ end
+ end
+
+ class ExecScriptProgram < Program
+ attr_accessor :script
+
+ def initialize(collection, id, name)
+ super
+
+ @type = TYPE_EXEC_SCRIPT
+ @script = nil
+ end
+ end
+
+ class ProgramArgs < Array
+ attr_reader :collection
+
+ def initialize(collection)
+ @collection = collection
+ end
+
+ def <<(v)
+ if v.collection != @collection
+ raise(ArgumentError, "items not in the same collection")
+ end
+
+ super
+ end
+ end
+
+ class ProgramArg
+ attr_reader :collection
+
+ def initialize(v)
+ @collection = v.collection
+ @id = v.id
+ end
+
+ def to_eet_properties
+ {"id" => [@id]}
+ end
+ end
+
+ class ProgramAfter < ProgramArg
+ def to_eet_name
+ "Edje_Program_After"
+ end
+ end
+
+ class ProgramTarget < ProgramArg
+ def to_eet_name
+ "Edje_Program_Target"
+ end
+ end
+end
--- /dev/null
+#--
+# $Id: redact.rb 1 2005-03-26 01:32:38Z tilman $
+#
+# Copyright (c) 2005 Tilman Sauerbeck (tilman at code-monkey de)
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+require "eet"
+require "imlib2"
+require "redact/part"
+require "redact/program"
+
+class Object
+ undef :id
+end
+
+class String
+ def to_embryo(collection)
+ unless strip.length > 0
+ raise(Redact::RedactError, "invalid embryo code")
+ end
+
+ s = strip.dup
+
+ {"part" => collection.parts,
+ "program" => collection.programs}.each do |entity, ary|
+ s.gsub!(/#{entity.upcase}:\"(.*?)\"/) do |m|
+ found = ary.find { |(k, p)| p.name == $1 }
+ if found.nil?
+ raise(Redact::RedactError,
+ "#{entity} not found - #{$1}")
+ else
+ found.last.id
+ end
+ end
+ end
+
+ s
+ end
+end
+
+module Redact
+ VERSION = "0.0.1"
+
+ class RedactError < StandardError; end
+
+ class Edje
+ attr_reader :collections, :data, :collection_dir, :image_dir,
+ :font_dir
+
+ def initialize
+ clear
+ end
+
+ def clear
+ @font_dir = FontDirectory.new
+ @image_dir = ImageDirectory.new
+ @collection_dir = CollectionDirectory.new
+
+ @collections = Hash.new do |h, k|
+ c = Collection.new(k, h.size)
+
+ @collection_dir << CollectionDirectoryEntry.new(c)
+ h[k] = c
+ end
+
+ @data = DataHash.new
+ end
+
+ def collection(name)
+ c = @collections[name]
+
+ block_given? ? (yield c) : c
+ end
+
+ def to_eet_name
+ "Edje_File"
+ end
+
+ def to_eet_properties
+ {"compiler" => ["redact"],
+ "version" => [2],
+ "feature_ver" => [1],
+ "font_dir" => [@font_dir, :sub],
+ "image_dir" => [@image_dir, :sub],
+ "collection_dir" => [@collection_dir, :sub],
+ "data" => [@data]}
+ end
+ end
+
+ class DataHash < Hash
+ def [](key)
+ super.value
+ end
+
+ def []=(key, value)
+ super(key, HashEntry.new(key, value))
+ end
+ end
+
+ class HashEntry
+ attr_reader :key, :value
+
+ def initialize(key, value)
+ @key = key.to_str.dup.freeze
+ @value = value.to_str.dup.freeze
+ end
+
+ def to_eet_name
+ "Edje_Data"
+ end
+ end
+
+ class FontDirectory < Array
+ def to_eet_name
+ "Edje_Font_Directory"
+ end
+
+ def to_eet_properties
+ {"entries" => [self]}
+ end
+ end
+
+ class FontDirectoryEntry
+ attr_reader :filename
+
+ def initialize(filename)
+ @filename = filename.to_str.dup.freeze
+ end
+
+ def to_eet_name
+ "Edje_Font_Directory_Entry"
+ end
+
+ def to_eet_properties
+ {"entry" => [@filename]}
+ end
+ end
+
+ class ImageDirectory < Array
+ def <<(entry)
+ super
+
+ entry.id = size - 1
+ end
+
+ def to_eet_name
+ "Edje_Image_Directory"
+ end
+
+ def to_eet_properties
+ {"entries" => [self]}
+ end
+ end
+
+ class ImageDirectoryEntry
+ attr_reader :filename, :image, :id
+
+ def initialize(filename)
+ @filename = filename.to_str.dup.freeze
+ @image = Imlib2::Image.load(@filename)
+ @id = -1
+ @source_type = 1 # COMP
+ @source_param = 1 # COMP
+ end
+
+ def id=(id)
+ if id < 0
+ raise(ArgumentError, "invalid ID - #{id}")
+ elsif @id != -1
+ raise(RedactError, "ID already set")
+ else
+ @id = id
+ end
+ end
+
+ def to_eet_name
+ "Edje_Image_Directory_Entry"
+ end
+
+ def to_eet_properties
+ {"entry" => [@filename],
+ "source_type" => [@source_type],
+ "source_param" => [@source_param],
+ "id" => [@id]}
+ end
+ end
+
+ class CollectionDirectory < Array
+ def to_eet_name
+ "Edje_Part_Collection_Directory"
+ end
+
+ def to_eet_properties
+ {"entries" => [self]}
+ end
+ end
+
+ class CollectionDirectoryEntry
+ def initialize(col)
+ @name = col.name.to_str.dup.freeze
+ @id = col.id
+ end
+
+ def to_eet_name
+ "Edje_Part_Collection_Directory_Entry"
+ end
+
+ def to_eet_properties
+ {"entry" => [@name],
+ "id" => [@id]}
+ end
+ end
+
+ class Collection
+ attr_reader :name, :id, :data, :min, :max, :parts, :programs
+ attr_accessor :script
+
+ def initialize(name, id)
+ @name = name.to_str.dup.freeze
+ @id = id
+
+ @min = [0, 0]
+ @max = [0, 0]
+ @data = DataHash.new
+
+ @parts = {}
+ @programs = {}
+
+ @script = nil
+ end
+
+ def part(name, type = :invalid)
+ p = @parts[name]
+ if p.nil?
+ klass = case type
+ when :rect
+ Part
+ when :swallow
+ SwallowPart
+ when :text
+ TextPart
+ when :image
+ ImagePart
+ else
+ raise(ArgumentError,
+ "invalid program type - #{type.to_s}")
+ end
+
+ p = klass.new(self, @parts.size, name)
+ @parts[name] = p
+ end
+
+ block_given? ? (yield p) : p
+ end
+
+ def program(name, type = :invalid)
+ p = @programs[name]
+ if p.nil?
+ klass = case type
+ when :base
+ Program
+ when :set_state
+ SetStateProgram
+ when :stop_program
+ StopProgramProgram
+ when :emit_signal
+ EmitSignalProgram
+ when :exec_script
+ ExecScriptProgram
+ else
+ raise(ArgumentError,
+ "invalid program type - #{type.to_s}")
+ end
+
+ p = klass.new(self, @programs.size, name)
+ @programs[name] = p
+ end
+
+ block_given? ? (yield p) : p
+ end
+
+ def set_size(w, h)
+ set_min(w, h)
+ set_max(w, h)
+ end
+
+ def set_min(w, h)
+ @min = [w, h]
+ end
+
+ def set_max(w, h)
+ @max = [w, h]
+ end
+
+ def has_embryo?(search_programs = true)
+ if !@script.nil? && @script.to_str.strip.length > 0
+ true
+ elsif search_programs
+ p = @programs.find do |(k, p)|
+ p.is_a?(ExecScriptProgram)
+ end
+
+ !p.nil?
+ end
+ end
+
+ def to_eet_name
+ "Edje_Part_Collection"
+ end
+
+ def to_eet_properties
+ # sort parts and programs by id, since edje doesn't sort
+ # them on load
+ parts = @parts.to_a.map { |(key, value)| value }.sort
+ programs = @programs.to_a.map { |(key, value)| value }.sort
+
+ {"id" => [@id],
+ "parts" => [parts],
+ "programs" => [programs],
+ "data" => [@data],
+ "prop.min.w" => [@min[0]],
+ "prop.min.h" => [@min[1]],
+ "prop.max.w" => [@max[0]],
+ "prop.max.h" => [@max[1]]}
+ end
+ end
+
+ EDJE = Redact::Edje.new
+end
--- /dev/null
+#--
+# $Id: source.rb 1 2005-03-26 01:32:38Z tilman $
+#
+# Copyright (c) 2005 Tilman Sauerbeck (tilman at code-monkey de)
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+module Redact
+ class SourceFile
+ attr_reader :filename, :contents
+
+ def initialize(filename, contents)
+ @filename = filename.to_str.dup.freeze
+ @contents = contents.to_str.dup.freeze
+ end
+
+ def to_eet_name
+ "srcfile"
+ end
+
+ def to_eet_properties
+ {"name" => [@filename],
+ "file" => [@contents]}
+ end
+ end
+
+ class SourceFiles < Array
+ def to_eet_name
+ "srcfile_list"
+ end
+
+ def to_eet_properties
+ {"list" => [self]}
+ end
+ end
+
+ class FontMapEntry
+ def initialize(font)
+ @font = font
+ end
+
+ def to_eet_name
+ "font"
+ end
+
+ def to_eet_properties
+ {"file" => [@font.filename],
+ "name" => [@font.filename]}
+ end
+ end
+
+ class FontMap < Array
+ def to_eet_name
+ "font_list"
+ end
+
+ def to_eet_properties
+ {"list" => [self]}
+ end
+ end
+end
--- /dev/null
+# $Id: crossfade.rb 1 2005-03-26 01:32:38Z tilman $
+
+include Redact
+
+EDJE.collection("crossfade") do |c|
+ c.part("background", :rect).description do |d|
+ d.color = "#ffffff"
+ end
+
+ c.part("rect_red", :rect) do |p|
+ p.description do |d|
+ d.color = "#00ff0000"
+ d.rel[1].set_rel(1.0, 0.0)
+ end
+
+ p.description("default", 1.0) do |d|
+ d.color = "#ff"
+ d.rel[1].set_rel(1.0, 0.4)
+ end
+ end
+
+ c.part("rect_green", :rect) do |p|
+ p.description do |d|
+ d.color = "#ff000080"
+ d.rel[0].set_rel(0.0, 1.0)
+ end
+
+ p.description("default", 1.0) do |d|
+ d.color = "#00ff"
+ d.rel[0].set_rel(0.0, 0.6)
+ end
+ end
+
+ c.part("text", :text) do |p|
+ p.description do |d|
+ d.color = "#00"
+
+ d.text = "cuddletech"
+ d.font = "Vera"
+ d.font_size = 12
+ d.set_fit(true, false)
+ end
+ end
+
+ c.program("animate", :set_state) do |p|
+ p.signal = "mouse,clicked,1"
+ p.source = "background"
+ p.value = 1.0
+ p.mode = SetStateProgram::MODE_ACCELERATE
+ p.time = 1.0
+ p.targets << ProgramTarget.new(c.part("rect_red"))
+ p.targets << ProgramTarget.new(c.part("rect_green"))
+ end
+end
--- /dev/null
+# $Id: red_rect.rb 1 2005-03-26 01:32:38Z tilman $
+
+include Redact
+
+EDJE.collection("red_rect") do |c|
+ c.part("rect", :rect) do |p|
+ p.description.color = "#ff"
+ end
+end
--- /dev/null
+# $Id: test_basic.rb 1 2005-03-26 01:32:38Z tilman $
+
+require "redact/app"
+require "test/unit"
+require "ftools"
+
+class TestRedact < Test::Unit::TestCase
+ def test_red_rect
+ title = "red_rect"
+ base = File.join(File.dirname(__FILE__), title)
+ file = base + ".rb"
+ args = [file, "-o", file + ".eet"]
+
+ assert_nothing_raised do
+ Redact::App.new(args).run
+ end
+ end
+
+ def test_crossfade
+ title = "crossfade"
+ base = File.join(File.dirname(__FILE__), title)
+ file = base + ".rb"
+ args = [file, "-o", file + ".eet"]
+
+ assert_nothing_raised do
+ Redact::App.new(args).run
+ end
+ end
+end