Browse Source

Add 'data' field to svg method for loading XML directly

Implements #65
dev
Andy Meneely 11 years ago
parent
commit
e974880e03
  1. 3
      CHANGELOG.md
  2. 8
      lib/squib/api/image.rb
  3. 2
      lib/squib/api/text_embed.rb
  4. 2
      lib/squib/constants.rb
  5. 8
      lib/squib/graphics/image.rb
  6. 2
      samples/embed_text.rb
  7. 14
      samples/load_images.rb
  8. 2
      spec/api/api_image_spec.rb
  9. 6
      spec/data/samples/load_images.rb.txt
  10. 10
      spec/graphics/graphics_images_spec.rb
  11. 1
      squib.gemspec
  12. 4
      squib.sublime-project

3
CHANGELOG.md

@ -4,8 +4,9 @@ Squib follows [semantic versioning](http://semver.org).
## v0.6.0 / Unreleased
Features:
* Upgraded roo (Excel parsing) to 2.0.0. Nothing major for Squib users, just keeping up with the times.
* Added `data` field to `svg` to allow for manipulating SVG XML data directly. Works nicely with my new `game_icons` [gem](https://github.com/andymeneely/game_icons) (#65)
* Added `stroke_width` and `stroke_color` to the `text` method to outlines text. (#51)
* Upgraded roo (Excel parsing) to 2.0.0. Nothing major for Squib users, just keeping up with the times.
Bugs:
* Fixed global text hinting (#63)

8
lib/squib/api/image.rb

@ -34,7 +34,7 @@ module Squib
end
end
# Renders an entire svg file at the given location. Uses the SVG-specified units and DPI to determine the pixel width and height.
# Renders an entire svg file at the given location. Uses the SVG-specified units and DPI to determine the pixel width and height. If neither data nor file are specified for a given card, this method does nothing.
#
# See {file:samples/load-images.rb samples/load-images.rb} and {file:samples/tgc-overlay.rb samples/tgc-overlay.rb} as examples.
# @example
@ -42,6 +42,7 @@ module Squib
#
# @option opts range [Enumerable, :all] (:all) the range of cards over which this will be rendered. See {file:README.md#Specifying_Ranges Specifying Ranges}
# @option opts file [String] ('') file(s) to read in. If it's a single file, then it's use for every card in range. If the parameter is an Array of files, then each file is looked up for each card. If any of them are nil or '', nothing is done. See {file:README.md#Specifying_Files Specifying Files}. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
# @option opts data [String] (nil) render from an SVG XML string. Overrides file if both are specified (a warning is shown) . If it's a single file, then it's use for every card in range. If the parameter is an Array of files, then each file is looked up for each card. If any of them are nil or '', nothing is done. See {file:README.md#Specifying_Files Specifying Files}. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}.
# @option opts id [String] (nil) if set, then only render the SVG element with the given id. Prefix '#' is optional. Note: the x-y coordinates are still relative to the SVG document's page. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
# @option opts force_id [Boolean] (false) if set, then this svg will not be rendered at all if the id is empty or nil. If not set, the entire SVG is rendered. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}
# @option opts x [Integer] (0) the x-coordinate to place. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion}. Supports Unit Conversion, see {file:README.md#Units Units}.
@ -56,12 +57,13 @@ module Squib
# @return [nil] Returns nil
# @api public
def svg(opts = {})
p = needs(opts,[:range, :files, :svgid, :force_svgid, :x, :y, :width, :height, :layout, :alpha, :blend, :angle, :mask])
p = needs(opts,[:range, :files, :svgdata, :svgid, :force_svgid, :x, :y, :width, :height,
:layout, :alpha, :blend, :angle, :mask])
Dir.chdir(img_dir) do
@progress_bar.start('Loading SVG(s)', p[:range].size) do |bar|
p[:range].each do |i|
unless p[:force_id][i] && p[:id][i].to_s.empty?
@cards[i].svg(p[:file][i], p[:id][i], p[:x][i], p[:y][i],
@cards[i].svg(p[:file][i], p[:data][i], p[:id][i], p[:x][i], p[:y][i],
p[:width][i], p[:height][i], p[:alpha][i], p[:blend][i], p[:angle][i],p[:mask][i])
end
bar.increment

2
lib/squib/api/text_embed.rb

@ -30,7 +30,7 @@ module Squib
# TODO: add input validation here. We need the key for example.
rule = {type: :svg}.merge(opts)
rule[:draw] = Proc.new do |card, x,y|
card.svg(rule[:file], rule[:id], x, y, rule[:width], rule[:height],
card.svg(rule[:file], rule[:data], rule[:id], x, y, rule[:width], rule[:height],
rule[:alpha], rule[:blend], rule[:angle], rule[:mask])
end
@rules[opts[:key]] = rule

2
lib/squib/constants.rb

@ -14,6 +14,7 @@ module Squib
:cx2 => 0,
:cy1 => 0,
:cy2 => 0,
:data => nil,
:default_font => 'Arial 36',
:dir => '_output',
:dx => 0, # delta
@ -107,6 +108,7 @@ module Squib
:str => :str,
:stroke_color => :stroke_color,
:stroke_width => :stroke_width,
:svgdata => :data,
:svgid => :id,
:valign => :valign,
:width => :width,

8
lib/squib/graphics/image.rb

@ -41,10 +41,12 @@ module Squib
# :nodoc:
# @api private
def svg(file, id, x, y, width, height, alpha, blend, angle, mask)
def svg(file, data, id, x, y, width, height, alpha, blend, angle, mask)
Squib.logger.debug {"Rendering: #{file}, id: #{id} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}, mask: #{mask}"}
return if file.nil? or file.eql? ''
svg = RSVG::Handle.new_from_file(file)
Squib.logger.warn 'Both an SVG file and SVG data were specified' unless file.to_s.empty? or data.to_s.empty?
return if (file.nil? or file.eql? '') and data.nil? # nothing specified
data = File.read(file) if data.to_s.empty?
svg = RSVG::Handle.new_from_data(data)
width = svg.width if width == :native
height = svg.height if height == :native
scale_width = width.to_f / svg.width.to_f

2
samples/embed_text.rb

@ -61,7 +61,7 @@ Squib::Deck.new do
text(str: embed_text, font: 'Sans 21',
x: 400, y: 320, width: 180, height: 300,
align: :center, ellipsize: false, justify: false, hint: :magenta) do |embed|
embed.svg key: ':tool:', width: 28, height: 28, file: 'spanner.svg'
embed.svg key: ':tool:', width: 28, height: 28, data: File.read('spanner.svg')
embed.svg key: ':health:', width: 28, height: 28, file: 'glass-heart.svg'
embed.png key: ':purse:', width: 28, height: 28, file: 'shiny-purse.png'
end

14
samples/load_images.rb

@ -17,6 +17,20 @@ Squib::Deck.new(width: 825, height: 1125, cards: 1) do
# Squib prepends a #-sign if one is not specified
svg file: 'spanner.svg', id: 'backdrop', x: 50, y: 450, width: 125, height: 125
# We can also load SVGs as a string of XML
svg data: File.read('spanner.svg'), x: 50, y: 600, width: 75, height: 75
# The svg data field works nicely with modifying the SVG XML on-the-fly.
# To run this one, do `gem install game_icons` and uncomment the following
#
# require 'game_icons'
# svg data: GameIcons.get('angler-fish').recolor(fg: '#ccc', bg: '#333').string,
# x: 150, y: 600, width: 75, height: 75
#
# More examples at https://github.com/andymeneely/game_icons
# (or `gem install game_icons`) to get & manipulate art from game-icons.net
# Nokogiri (already included in Squib) is also great for XML manipulation.
# WARNING! If you choose to use the SVG ID, the x-y coordinates are still
# relative to the SVG page. See this example in an SVG editor
svg file: 'offset.svg', id: 'thing', x: 0, y: 0, width: 600, height: 600

2
spec/api/api_image_spec.rb

@ -23,7 +23,7 @@ describe Squib::Deck, 'images' do
it 'calls Card#svg, Dir, and progress bar' do
card = instance_double(Squib::Card)
progress = double(Squib::Progress)
expect(card).to receive(:svg).with('foo', '#bar', 0, 1, 20, 30, 0.5, :overlay, 0.75, nil).once
expect(card).to receive(:svg).with('foo', nil, '#bar', 0, 1, 20, 30, 0.5, :overlay, 0.75, nil).once
expect(Dir).to receive(:chdir).with('.').and_yield.once
expect(progress).to receive(:start).and_yield(progress).once
expect(progress).to receive(:increment).once

6
spec/data/samples/load_images.rb.txt

@ -52,6 +52,12 @@ cairo: scale([0.9765625, 0.9765625])
cairo: render_rsvg_handle([RSVG::Handle, "#backdrop"])
cairo: restore([])
cairo: save([])
cairo: translate([50, 600])
cairo: rotate([0])
cairo: scale([0.5859375, 0.5859375])
cairo: render_rsvg_handle([RSVG::Handle, nil])
cairo: restore([])
cairo: save([])
cairo: translate([0, 0])
cairo: rotate([0])
cairo: scale([0.8021390374331551, 0.8032128514056225])

10
spec/graphics/graphics_images_spec.rb

@ -12,7 +12,7 @@ describe Squib::Card do
allow(Cairo::Context).to receive(:new).and_return(context)
allow(Cairo::ImageSurface).to receive(:from_png).and_return(png)
allow(Cairo::ImageSurface).to receive(:new).and_return(png)
allow(RSVG::Handle).to receive(:new_from_file).and_return(svg)
allow(RSVG::Handle).to receive(:new_from_data).and_return(svg)
allow(deck).to receive(:dir).and_return('_output')
allow(deck).to receive(:count_format).and_return('%02d')
allow(deck).to receive(:prefix).and_return('card_')
@ -58,8 +58,8 @@ describe Squib::Card do
expect(context).to receive(:restore).once
card = Squib::Card.new(deck, 100, 150)
# svg(file, id, x, y, width, height, alpha, blend, angle)
card.svg('foo.png', 'id', 37, 38, :native, :native, 0.9, :none, 0.0, nil)
# svg(file, data, id, x, y, width, height, alpha, blend, angle)
card.svg(nil, '<svg></svg>', 'id', 37, 38, :native, :native, 0.9, :none, 0.0, nil)
end
it 'sets blend when needed' do
@ -68,7 +68,7 @@ describe Squib::Card do
expect(context).to receive(:operator=).with(:overlay).once
card = Squib::Card.new(deck, 100, 150)
card.svg('foo.png', nil, 37, 38, :native, :native, 0.9, :overlay, 0.0, nil)
card.svg(nil, '<svg></svg>', nil, 37, 38, :native, :native, 0.9, :overlay, 0.0, nil)
end
it 'sets width & height when needed' do
@ -78,7 +78,7 @@ describe Squib::Card do
expect(context).to receive(:scale).with(2.0, 3.0).once
card = Squib::Card.new(deck, 100, 150)
card.svg('foo.png', nil, 37, 38, 200, 300, 0.9, :none, 0.0, nil)
card.svg(nil, '<svg></svg>', nil, 37, 38, 200, 300, 0.9, :none, 0.0, nil)
end
end

1
squib.gemspec

@ -43,5 +43,6 @@ Gem::Specification.new do |spec|
spec.add_development_dependency 'coveralls'
spec.add_development_dependency 'byebug'
spec.add_development_dependency 'launchy'
spec.add_development_dependency 'game_icons'
end

4
squib.sublime-project vendored

@ -40,6 +40,10 @@
"name": "rake run[custom_config]",
"shell_cmd": "rake run[custom_config]",
},
{
"name": "rake run[load_images]",
"shell_cmd": "rake run[load_images]",
},
{
"name": "rspec spec/samples/samples_regression_spec.rb",
"shell_cmd": "rspec spec/samples/samples_regression_spec.rb",

Loading…
Cancel
Save