Created
August 28, 2012 09:50
-
-
Save okonet/3496682 to your computer and use it in GitHub Desktop.
SVG post-processing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
fs = require 'fs' | |
path = require 'path' | |
ensureDir = require 'ensureDir' | |
jsdom = require 'jsdom' | |
phantom = require 'phantom' | |
{exec} = require 'child_process' | |
# ANSI Terminal Colors. | |
# bold = '\033[0;1m' | |
# red = '\033[0;31m' | |
# green = '\033[0;32m' | |
# reset = '\033[0m' | |
task 'process', 'Pre-process SVG files to work with JavaScript configurator', (options) -> | |
unless process.env.APP? | |
return console.error "Make sure to set APP before running 'cake process'." | |
else | |
app_name = process.env.APP | |
src_path = "#{__dirname}/src/avatars/#{app_name}/" | |
target_path = "#{__dirname}/public/avatars/#{app_name}/" | |
# Get all SVG sources | |
fs.readdir src_path, (err, files) -> | |
throw err if err | |
files.forEach (file) -> | |
return unless file.match(/\.svg$/i) | |
# Read and process each file | |
fs.readFile src_path + file, (err, data) -> | |
throw err if err | |
content = data.toString() | |
plugins = [ | |
'http://code.jquery.com/jquery-1.5.min.js' | |
] | |
jsdom.env content, plugins, (errors, window) -> | |
throw errors if errors | |
# Scope | |
$ = window.$ | |
# Each avatar section becomes an appropriate class name for better DOM traversing | |
for section in ['front', 'back', 'body', 'head','torso', 'arms', 'headshapes', 'hair', 'brows', 'eyes', 'noses', 'mouths', 'shirt', 'trousers', 'extras', 'fill', 'outline'] | |
$('*[id^="' + section + '"]').addClass section | |
# console.log "Processed #{section}" | |
# For every element with "selection[1...n]" and "dependentSelection[1...n]" add an appropriate class name | |
for section in ['selection', 'dependentSelection'] | |
$('*[id^="' + section + '"]').each (idx, el) -> | |
class_name = $(el).attr("id").split("_")[0] | |
$(el).addClass("#{section} #{class_name}").attr("style", "visibility:hidden") | |
# Produce speedy selectors. | |
# Speedy selectors are used to speedup coloring parts of avatar. | |
# So each group of sections gets unique class name which is used to apply color from picker. | |
# This improved $ performance dramatically (x200 times) | |
speedySelectors = body: ['torso', 'arms', 'headshapes'], hair: ['hair'], brows: ['brows'], shirt: ['shirt'], trousers: ['trousers'], eyes: ['eyes'], extras: ['extras'] | |
for type in ["fill", "outline"] | |
for group, sections of speedySelectors | |
selectors = for section in sections | |
".#{section} .#{type}, .#{section} .#{type} path" | |
selectors.join(",") | |
for selector in selectors | |
$(selector).addClass(group + "_" + type) | |
# console.log "Processed #{selector} in #{group}_#{type}" | |
# Cleaning SVG up by removing unused attributes to reduce file size. | |
for attr in ['fill-rule', 'clip-rule', 'stroke-linecap', 'stroke-miterlimit'] | |
$("[#{attr}]").removeAttr(attr) | |
$("[id]:not([id^=SVGID])").removeAttr('id') | |
data = $('body').html() | |
# For some reason the pre-processor converts camelcased svg tags to lowercase which is wrong. Work around it. | |
data = data.replace("viewbox", "viewBox") | |
data = data.replace(/lineargradient/g, "linearGradient") | |
data = data.replace(/radialgradient/g, "radialGradient") | |
data = data.replace(/gradientunits/g, "gradientUnits") | |
data = data.replace(/gradienttransform/g, "gradientTransform") | |
enhgsureDir target_path, 0o0755, (err) -> | |
throw err if err | |
fs.writeFile "#{target_path}#{file}", data, (err) -> | |
throw err if err | |
console.log "Processed: #{file}"; | |
# Generate thumbnails | |
phantom.create (ph) -> | |
ph.createPage (page) -> | |
width = 240 | |
height = 360 | |
page.set "clipRect", { top: 10, left: 10, width: width, height: height } | |
html = data.replace("250px", "#{width}px").replace("550px", "#{height}px") | |
page.set('content', html) | |
page.includeJs plugins[0], () -> | |
page.evaluate -> | |
$(".selection, .dependentSelection").attr("style", "visibility:hidden") | |
$(".selection1, .dependentSelection1").attr("style", "") | |
$(".extras .selection, .extras .dependentSelection").attr("style", "visibility:hidden") # Hide all extras | |
page.render "#{target_path}#{file}.png", () -> | |
console.log "Generated screenshot for #{target_path}#{file}.png" | |
ph.exit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment