Skip to content

Commit

Permalink
parsing of subtle.svg
Browse files Browse the repository at this point in the history
  • Loading branch information
J.J. Green committed Dec 28, 2015
1 parent 6e16742 commit 851a7d9
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 4 deletions.
1 change: 1 addition & 0 deletions gradient.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
spec.require_paths = ["lib"]

spec.add_dependency "color", "~> 1.8"
spec.add_dependency 'nokogiri', '~> 1.6'
spec.add_development_dependency "bundler", "~> 1.7"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec"
Expand Down
60 changes: 60 additions & 0 deletions lib/gradient/svg.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
require 'scanf'
require 'nokogiri'

module Gradient

class SVGError < StandardError ; end

class SVG

attr_reader :maps
Expand Down Expand Up @@ -29,8 +35,62 @@ def initialize
@maps = {}
end

SVGNS = 'http://www.w3.org/2000/svg'

def parse(buffer)
xml = Nokogiri::XML(buffer)
xml.xpath('//xmlns:linearGradient', 'xmlns' => SVGNS).each do |linear_gradient|
unless (id = linear_gradient['id']) then
raise SVGError, 'linearGradient has no id'
end
@maps[id] = parse_linear_gradient(linear_gradient)
end
end

private def parse_linear_gradient(linear_gradient)
map = Gradient::Map.new
linear_gradient.children.each do |stop|
next unless stop.name == 'stop'
map.points << parse_stop(stop)
end
map
end

private def parse_stop(stop)
unless (offset = stop['offset']) then
raise SVGError, 'stop has no offset'
end
location = parse_location(offset)
# FIXME, handle style
unless (stop_color = stop['stop-color']) then
raise SVGError, 'stop has no stop-color'
end
red, green, blue, opacity = parse_stop_color(stop_color)
if (stop_opacity = stop['stop-opacity']) then
opacity = parse_stop_opacity(stop_opacity)
end
color = Color::RGB.new(red, green, blue)
Gradient::Point.new(location, color, opacity)
end

private def parse_location(offset)
unless (location = offset.scanf('%f%%')).count == 1 then
raise SVGError, "failed parse of offset #{offset}"
end
location.first
end

private def parse_stop_color(stop_color)
# FIXME - handle # colours
if (parts = stop_color.scanf('rgb(%d,%d,%d)')).count == 3 then
[*parts, 1.0]
elsif (parts = stop_color.scanf('rgba(%d,%d,%d,%f)')).count == 4 then
parts
end
end

private def parse_stop_opacity(stop_opacity)
stop_opacity.scanf('%f')
end
end
end
39 changes: 35 additions & 4 deletions spec/gradient/svg_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,44 @@ def fixture_buffer(base)
end

it 'should have the correct keys' do
skip 'implementation'
expect(maps.keys).to match_array ['subtle']
end

it "should have #{described_class} values" do
maps.values.each do |map|
expect(map).to be_a described_class
describe 'the hash value' do

let(:map) { maps['subtle'] }

it 'should be a Gradient::Map' do
expect(map).to be_a Gradient::Map
end

describe 'the points' do

let(:points) { map.points }

it 'should be an array' do
expect(points).to be_an Array
end

it 'should have 11 elements' do
expect(points.count).to eq 11
end

it 'should consist of Gradient::Point objects' do
points.each do |point|
expect(point).to be_a Gradient::Point
end
end

describe 'the locations' do

let(:locations) { points.map(&:location) }

it 'should have the expected values' do
expect(locations)
.to match_array [0, 6, 19, 25, 32, 42, 53, 65, 75, 87, 100]
end
end
end
end
end
Expand Down

0 comments on commit 851a7d9

Please sign in to comment.