Tuesday, 26 August 2008

Echo, Nodoka, One Canvas, Ruby and New Fedora Certs

It's been some time since my last post, so several things pilled up since then I'd like to talk about. So first about Echo, One Canvas and Ruby.

We ought to keep up with latest technology and make the process of creating new Echo icons as easy/effective as possible. As already mentioned in the fedora-art-list there is a new workflow of creating the icons - One Canvas Workflow. As the name suggests, it means that you create all the icon sizes from 16x16 to 256x256 in one file. It has the obvious advantage of possibility of all the icons sharing the same gradients, direct comparison, ... The question is, how to make all the required PNGs from the one canvas SVG. Jimmac has an answer.

Basically the workflow means that you use some inkscape features like layer functionality (you can display/hide layer editor via ctrl+shift+L) or object labeling. First you need to have two layers - one supporting for the script that will generate the PNGs later, and one with the actual artwork. The supportive one needs to be named 'plate', the artwork one 'artwork' (required by the script). On the plate you draw squares with the desired icon sizes (from 16x16 to 256x256) and distribute them in the canvas so that 22x22 and 24x24 are used for the same image and the others are separate. In the artwork layer you just draw the icons over the prepared squares in the plate layer. It's good thing to lock the plate layer to avoid accidental drawing to it.

Finaly group the separate icons into separate groups (one group for one icon) and because we need to know where the icon gets installed to, add Description = (substitute with e.g. devices for printer icon) to Document Metadata.

Now that would be enough to generate all the PNGs, as is done in Jimmac's ruby script. But in Echo Icon Theme we also distribute Scalable images (SVGs). So I needed to extend the script to generate the desired SVG as well. First it needs to somehow identify what will be erased from the source SVGs and where the rest will be moved to. I decided that best way is to use inkscape's labeling functions. So select the icon artwork intended for the SVG (usually the 48x48 one), it needs to be one group, select obejct properties [ctrl+shift+o] and set Label to scalable. Do the same for the rectangle bellow in the plate layer (that's needed to reposition the icon).

Now, to the script. First I decided we need only the one icon variant, so I dropped the code iterating through all icons. Next I needed to somehow edit the SVG to remove all unnecessary objects change the canvas size and correctly place the scalable icon on it. Since I had never done anything in ruby up until yesterday it proved a rather long job, but finally, after about 4 hours of experimenting, reading REXML docs and googling, I've managed to put together working script. I am not sure though if it's written correctly, since I don't know how memory is allocated/freed in ruby, know practicaly nothing about ruby syntax, ... Anyway here's the code:

#!/usr/bin/env ruby

require "rexml/document"
require "ftools"
include REXML
INKSCAPE = '/usr/bin/inkscape'
SRC = "./svg"

def renderit(file)
svg = Document.new(File.new("#{SRC}/#{file}", 'r'))
context = svg.root.elements['//dc:description'].text
svg.root.each_element("//g[@inkscape:label='plate']/rect") do |icon|
dir = "#{icon.attributes['width']}x#{icon.attributes['height']}/#{context}"
cmd = "#{INKSCAPE} -i #{icon.attributes['id']} -e #{dir}/#{file.gsub(/\.svg$/,'.png')} #{SRC}/#{file} > /dev/null 2>&1"
File.makedirs(dir) unless File.exists?(dir)
print "."
#puts cmd

def expungeit(file)
svg = Document.new(File.new("#{SRC}/#{file}"), 'r')
context = svg.root.elements['//dc:description'].text
plate = svg.root.elements["//g[@inkscape:label='plate']/rect[@inkscape:label='scalable']"]
x = plate.attributes['x']
y = plate.attributes['y']
artwork = svg.root.elements["//g[@inkscape:label='artwork']/g[@inkscape:label='scalable']"]
translate = "translate(-#{x},-#{y})"
artwork.add_attribute(Attribute.new('transform', translate))
canvas = svg.root.elements["/svg"]
canvas.add_attribute(Attribute.new('width', '48'))
canvas.add_attribute(Attribute.new('height', '48'))
plate = svg.root.elements["//g[@inkscape:label='plate']"]
svg.root.each_element("//g[@inkscape:label='artwork']/*") do |icon|
label = icon.attributes['inkscape:label']
if (label != 'scalable')
dir = "Scalable/#{context}"
File.makedirs(dir) unless File.exists?(dir)
f = File.open("Scalable/#{context}/#{file}","w")
svg.write(f, -1, false)
cmd = "#{INKSCAPE} --vacuum-defs -l Scalable/#{context}/#{file} -f Scalable/#{context}/#{file}"

file = "#{ARGV[0]}.svg"
if (File.exists?("#{SRC}/#{file}"))
puts "\nRendered PNGs from #{SRC}/#{file}"
puts "\nCreated scalable SVG icon from #{SRC}/#{file}"
puts "[E] No such file (#{file})"

And here's the image (google accepts only PNG, but SVG is available on my fedorapeople page):

Next thing I have in mind are Nodoka improvements. I've done some further coding and improved the button rendering and added styled entry rendering. Even those two are still not complete, let alone the rest, but the progress is here. See in the following images.

And finally some words about new fedora cerificates. I had some problems with it like not being able to log into koji web interface or not being able to upload new sources for RPMs. It turned out that my user certificate was generated too early, still in the time when the problems with infrastructure were ongoing (kudos to infra guys for fixing it). So after the reason was discovered I am finally able to do all my work I do in Fedora.

That also means I updated subttitleeditor. Please test and report if it works for you. The update for F8 is here

and for F9 here


Anonymous said...

Wow, the second screenshot of the new nodoka style is just awesome.
The third one looks too much like Murrine.

Kevin Kofler said...

"ctrl+shit+L"? I wonder how many people will try hitting Ctrl+Window$ key+L and wonder why it doesn't work. ;-)

Martin said...

kevin, nice catch... what an interesting typo :-D Thanks for noticing me, I fixed it.