Add antialias config option

Closes #41
dev
Andy Meneely 2015-02-28 19:34:46 -05:00
parent b5016f90c0
commit f49bff2388
33 changed files with 109 additions and 8 deletions

View File

@ -2,11 +2,13 @@
# v0.4.0
* SVG backend support! You can now set the deck's back end to work with SVGs instead of images, making the resulting PDFs vectorized. (You can still save to PNGs too.) This was a big change for Squib, and it's got a few known issues here and there. See discussion on the README for more details.
* Bugfix: Stray stroke on circles (#35)
* Added config option for antialiasing method. My benchmarks showed that 'best' is only 10% slower than 'fast' on extremely alias-intensive tasks, so that's the Squib default now.
* Bugfix: Stray stroke on circles after text (#35)
* Bugfix: Progress bar increment error (#34)
Known issues
*
* Masking SVGs onto an SVG backend will rasterize as an intermediate step.
* Scale on vectorized PDFs is not perfect.
## v0.3.0
* Masks! The `png` and `svg` commands can be used as if they are a mask, so you can color the icon with any color you like. Can be handy for switching to black-and-white, or for reusing the same image but different colors across cards.

View File

@ -295,6 +295,7 @@ Squib supports various configuration properties that can be specified in an exte
* `dpi` (Integer, default: 300). Used in calculations when units are used (e.g. for PDF rendering and unit conversion).
* `hint` (ColorString, default: off). Text hints are used to show the boundaries of text boxes. Can be enabled/disabled for individual commands, or set globally with the `set` command. This setting is overriden by `set` and individual commands.
* `custom_colors` (Hash of Colors, default: {}). Defines globally-available colors available to the deck that can be specified in commands.
* `antialias` (`fast, good, best, none`, default: best). Set the algorithm that Cairo will use for antialiasing. Using our benchmarks on large decks, `best` is only X% slower anyway. For more info see the [Cairo docs](http://www.cairographics.org/manual/cairo-cairo-t.html#cairo-antialias-t).
The following sample demonstrates the config file.

View File

@ -0,0 +1,13 @@
require 'squib'
Squib::Deck.new(cards: 200, config: 'antialias_best.yml') do
background color: :white
# alphabet = 'a'.upto('z').to_a.join + ' ' + 'A'.upto('Z').to_a.join + ' '
# text str: alphabet * 36 , font: 'Sans Bold 18', width: 825, height: 1125, hint: :red
0.upto(500).each do |i|
circle radius: 50,
x: (i % 17) * 50,
y: (i / 17) * 50
end
save_png prefix: 'antialias_best_'
end

View File

@ -0,0 +1 @@
antialias: best

View File

@ -0,0 +1,13 @@
require 'squib'
Squib::Deck.new(cards: 200, config: 'antialias_fast.yml') do
background color: :white
# alphabet = 'a'.upto('z').to_a.join + ' ' + 'A'.upto('Z').to_a.join + ' '
# text str: alphabet * 36 , font: 'Sans Bold 18', width: 825, height: 1125, hint: :red
0.upto(500).each do |i|
circle radius: 50,
x: (i % 17) * 50,
y: (i / 17) * 50
end
save_png prefix: 'antialias_fast_'
end

View File

@ -0,0 +1 @@
antialias: fast

View File

@ -25,6 +25,7 @@ module Squib
@svgfile = "#{deck.dir}/#{deck.prefix}#{deck.count_format % index}.svg"
@cairo_surface = make_surface(@svgfile, backend)
@cairo_context = Squib::Graphics::CairoContextWrapper.new(Cairo::Context.new(@cairo_surface))
@cairo_context.antialias = @deck.antialias
end
def make_surface(svgfile, backend)

View File

@ -63,6 +63,7 @@ module Squib
#
# @api public
CONFIG_DEFAULTS = {
'antialias' => 'best',
'backend' => 'memory',
'count_format' => SYSTEM_DEFAULTS[:count_format],
'custom_colors' => {},

View File

@ -30,7 +30,7 @@ module Squib
# :nodoc:
# @api private
attr_reader :text_hint
attr_reader :text_hint, :antialias
# :nodoc:
# @api private
@ -58,6 +58,7 @@ module Squib
# @param block [Block] the main body of the script.
# @api public
def initialize(width: 825, height: 1125, cards: 1, dpi: 300, config: 'config.yml', layout: nil, &block)
@antialias = CONFIG_DEFAULTS['antialias']
@dpi = dpi
@font = SYSTEM_DEFAULTS[:default_font]
@cards = []
@ -109,6 +110,7 @@ module Squib
@dir = config['dir']
@prefix = config['prefix']
@count_format = config['count_format']
@antialias = config['antialias']
end
end

View File

@ -15,7 +15,8 @@ module Squib
:translate, :rotate, :move_to, :update_pango_layout, :width, :height,
:show_pango_layout, :rounded_rectangle, :set_line_width, :stroke, :fill,
:set_source, :scale, :render_rsvg_handle, :circle, :triangle, :line_to,
:operator=, :show_page, :clip, :transform, :mask, :create_pango_layout
:operator=, :show_page, :clip, :transform, :mask, :create_pango_layout,
:antialias=
def set_source_squibcolor(arg)
if match = arg.match(LINEAR_GRADIENT)

View File

@ -4,6 +4,9 @@
# Default: 300
#dpi: 72
#antialias: best #recommended. Only about 10% slower than fast
#antialias: default # set the anti-aliasing algorithm. default defers to the underlying graphics device. See http://www.cairographics.org/manual/cairo-cairo-t.html#cairo-antialias-t
# Text hints are used to show the boundaries of text boxes.
# Can be enabled/disabled at the command-level, or set globally with `set`
#text_hint: '#F00'
@ -21,5 +24,4 @@
# Use a SVG cairo back end, instead of an in-memory buffer
# backend: :memory # default
# backend: :svg # slower, but can create scalable pdfs
# tmp_dir: _tmp # for SVG backend, you MUST specify a tmp_dir
# backend: :svg # can create scalable pdfs, but rendering done at the printer level is not as good as Cairo.

View File

@ -1,3 +1,6 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:white])
cairo: paint([])

View File

@ -1,3 +1,6 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:white])
cairo: paint([])

View File

@ -1,3 +1,5 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:white])
cairo: paint([])

View File

@ -1,3 +1,5 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:white])
cairo: paint([])

View File

@ -1,3 +1,4 @@
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color(["#ccc"])
cairo: paint([])

View File

@ -1,3 +1,4 @@
cairo: antialias=(["best"])
cairo: save([])
cairo: rounded_rectangle([300, 300, 400, 400, 0, 0])
cairo: set_source_color([:red])

View File

@ -1,3 +1,6 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:white])
cairo: paint([])

View File

@ -1,3 +1,4 @@
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source([LinearPattern])
cairo: paint([])

View File

@ -1,3 +1,5 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:black])
cairo: translate([0, 0])

View File

@ -1,3 +1,4 @@
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color(["#0b7c8e"])
cairo: paint([])

View File

@ -1,3 +1,4 @@
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color(["#aaa"])
cairo: paint([])
@ -20,6 +21,7 @@ cairo: update_pango_layout([MockDouble])
cairo: show_pango_layout([MockDouble])
cairo: restore([])
surface: write_to_png(["_output/portrait_00.png"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color(["#aaa"])
cairo: paint([])

View File

@ -1,3 +1,6 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:white])
cairo: paint([])

View File

@ -1,3 +1,19 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:gray])
cairo: paint([])

View File

@ -1,3 +1,7 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color(["#CE534D"])
cairo: paint([])

View File

@ -1,3 +1,6 @@
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:white])
cairo: paint([])

View File

@ -1,3 +1,4 @@
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color([:white])
cairo: paint([])

View File

@ -1,3 +1,4 @@
cairo: antialias=(["best"])
cairo: save([])
cairo: set_source_color(["#ddd"])
cairo: paint([])

View File

@ -15,10 +15,13 @@ describe Squib::Card do
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_')
allow(@deck).to receive(:antialias).and_return('best')
end
context '#png' do
it 'makes all the expected calls on a smoke test' do
expect(@context).to receive(:antialias=).with('best')
expect(@context).to receive(:save).once
expect(@context).to receive(:translate).with(-37, -38).once
expect(@context).to receive(:rotate).with(0.0).once
@ -45,6 +48,7 @@ describe Squib::Card do
it 'makes all the expected calls on a smoke test' do
expect(@svg).to receive(:width).and_return(100).twice
expect(@svg).to receive(:height).and_return(100).twice
expect(@context).to receive(:antialias=).with('best').once
expect(@context).to receive(:save).once
expect(@context).to receive(:rotate).with(0.0).once
expect(@context).to receive(:translate).with(37, 38).once

View File

@ -20,13 +20,14 @@ describe Squib::Deck, '#save_pdf' do
before(:each) do
allow(Cairo::PDFSurface).to receive(:new).and_return(nil) #don't create the file
allow(Cairo::Context).to receive(:new).and_return(cxt)
allow(cxt).to receive(:antialias=)
end
it 'make all the expected calls on a smoke test' do
num_cards = 9
deck = Squib::Deck.new(cards: 9, width: 825, height: 1125)
expect(Squib.logger).to receive(:debug).at_least(:once)
expect(deck).to receive(:dirify) { |arg| arg } #don't create the dir
expect(Squib.logger).to receive(:debug).at_least(:once)
expect_card_place(75, 75)
expect_card_place(831, 75)

View File

@ -18,10 +18,12 @@ describe Squib::Card do
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_')
allow(@deck).to receive(:antialias).and_return('best')
end
context 'rect' do
it 'make all the expected calls on a smoke test' do
expect(@context).to receive(:antialias=).with('best')
expect(@context).to receive(:save).once
expect(@context).to receive(:rounded_rectangle).with(37, 38, 50, 100, 10, 15).twice
expect_stroke('#fff', '#f00', 2.0)
@ -36,6 +38,7 @@ describe Squib::Card do
context 'circle' do
it 'make all the expected calls on a smoke test' do
expect(@context).to receive(:antialias=).with('best')
expect(@context).to receive(:save).once
expect(@context).to receive(:move_to).with(137, 38)
expect(@context).to receive(:circle).with(37, 38, 100).twice
@ -51,6 +54,7 @@ describe Squib::Card do
context 'triangle' do
it 'make all the expected calls on a smoke test' do
expect(@context).to receive(:antialias=).with('best')
expect(@context).to receive(:save).once
expect(@context).to receive(:triangle).with(1, 2, 3, 4, 5, 6).twice
expect_stroke('#fff', '#f00', 2.0)
@ -63,6 +67,7 @@ describe Squib::Card do
context 'line' do
it 'make all the expected calls on a smoke test' do
expect(@context).to receive(:antialias=).with('best')
expect(@context).to receive(:save).once
expect(@context).to receive(:move_to).with(1, 2).once
expect(@context).to receive(:line_to).with(3, 4).once

View File

@ -14,11 +14,13 @@ describe Squib::Card, '#text' do
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_')
allow(deck).to receive(:antialias).and_return('best')
end
it 'make all the expected calls on a smoke test' do
extent = Pango::Rectangle.new(50,60,100,200)
expect(Squib.logger).to receive(:debug).once
expect(context).to receive(:antialias=).with('best').once
expect(context).to receive(:save).once
expect(context).to receive(:set_source_color).once
expect(context).to receive(:move_to).with(10, 15).once
@ -67,6 +69,7 @@ describe Squib::Card, '#text' do
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_')
allow(deck).to receive(:antialias).and_return('best')
end
it 'aligns right with strings' do

View File

@ -76,7 +76,8 @@ def mock_cairo(strio)
%w(save set_source_color paint restore translate rotate move_to
update_pango_layout width height show_pango_layout rounded_rectangle
set_line_width stroke fill set_source scale render_rsvg_handle circle
triangle line_to operator= show_page clip transform mask rectangle reset_clip).each do |m|
triangle line_to operator= show_page clip transform mask rectangle
reset_clip antialias=).each do |m|
allow(cxt).to receive(m) { |*args| strio << scrub_hex("cairo: #{m}(#{args})\n") }
end