diff --git a/CHANGELOG.md b/CHANGELOG.md index 792814e..431bb43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Features: * 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. +* Added an `ellipse` method to (you guessed it) draw ellipses. See the draw_shapes.rb sample (#66) Bugs: * Fixed global text hinting (#63) diff --git a/lib/squib/api/shapes.rb b/lib/squib/api/shapes.rb index 7f4051e..3b786f7 100644 --- a/lib/squib/api/shapes.rb +++ b/lib/squib/api/shapes.rb @@ -59,6 +59,34 @@ module Squib end end + # Draw an ellipse + # + # @example + # ellipse x: 0, y: 0, width: 825, height: 1125 + # + # Options support Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion} + # + # @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 x [Integer] (0) the x-coordinate to place. Supports Unit Conversion, see {file:README.md#Units Units}. + # @option opts y [Integer] (0) the y-coordinate to place. Supports Unit Conversion, see {file:README.md#Units Units}. + # @option opts width [Integer] the width of the rectangle. Supports Unit Conversion, see {file:README.md#Units Units}. + # @option opts height [Integer] the height of the rectangle. Supports Unit Conversion, see {file:README.md#Units Units}. + # @option opts fill_color [String] ('#0000') the color with which to fill the rectangle. See {file:README.md#Specifying_Colors___Gradients Specifying Colors & Gradients} + # @option opts stroke_color [String] (:black) the color with which to stroke the outside of the rectangle. {file:README.md#Specifying_Colors___Gradients Specifying Colors & Gradients} + # @option opts stroke_width [Decimal] (2.0) the width of the outside stroke. Supports Unit Conversion, see {file:README.md#Units Units}. + # @option opts layout [String, Symbol] (nil) entry in the layout to use as defaults for this command. See {file:README.md#Custom_Layouts Custom Layouts} + # @return [nil] intended to be void + # @api public + def ellipse(opts = {}) + opts = needs(opts, [:range, :x, :y, :width, :height, + :fill_color, :stroke_color, :stroke_width, :layout]) + opts[:range].each do |i| + @cards[i].ellipse(opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i], + opts[:fill_color][i], opts[:stroke_color][i], + opts[:stroke_width][i]) + end + end + # Draw a triangle using the given coordinates # # @example diff --git a/lib/squib/graphics/cairo_context_wrapper.rb b/lib/squib/graphics/cairo_context_wrapper.rb index 939a9d0..f5c26ba 100644 --- a/lib/squib/graphics/cairo_context_wrapper.rb +++ b/lib/squib/graphics/cairo_context_wrapper.rb @@ -22,7 +22,8 @@ module Squib :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, - :antialias=, :curve_to, :matrix, :matrix=, :identity_matrix, :pango_layout_path + :antialias=, :curve_to, :matrix, :matrix=, :identity_matrix, :pango_layout_path, + :stroke_preserve # :nodoc: # @api private diff --git a/lib/squib/graphics/shapes.rb b/lib/squib/graphics/shapes.rb index 115f7c5..1d6b68a 100644 --- a/lib/squib/graphics/shapes.rb +++ b/lib/squib/graphics/shapes.rb @@ -32,6 +32,34 @@ module Squib end end + # Ellipse drawing taken from looking at the control points in Inkscape + # Think of it like a rectangle. Curves go from mid-points of the sides + # of the rectangle. Control points are at 1/4 and 3/4 of the side. + # :nodoc: + # @api private + def ellipse(x, y, w, h, fill_color, stroke_color, stroke_width) + use_cairo do |cc| + cc.move_to(x, y + 0.5*h) # start west + cc.curve_to(x, y + 0.25*h, # west to north + x + 0.25*w, y, + x + 0.5*w, y) + cc.curve_to(x + 0.75*w, y, # north to east + x + w, y + 0.25*h, + x + w, y + 0.5*h) + cc.curve_to(x + w, y + 0.75*h, # east to south + x + 0.75*w, y + h, + x + 0.5*w, y + h) + cc.curve_to(x + 0.25*w, y + h, # south to west + x, y + 0.75*h, + x, y + 0.5*h) + cc.set_source_squibcolor(stroke_color) + cc.set_line_width(stroke_width) + cc.stroke_preserve + cc.set_source_squibcolor(fill_color) + cc.fill + end + end + # :nodoc: # @api private def triangle(x1, y1, x2, y2, x3, y3, fill_color, stroke_color, stroke_width) diff --git a/samples/draw_shapes.rb b/samples/draw_shapes.rb index 186d9b2..31fcb36 100644 --- a/samples/draw_shapes.rb +++ b/samples/draw_shapes.rb @@ -1,6 +1,7 @@ require 'squib' Squib::Deck.new do + background color: :white rect x: 300, y: 300, width: 400, height: 400, fill_color: :blue, stroke_color: :red, stroke_width: 50.0 @@ -20,5 +21,9 @@ Squib::Deck.new do stroke_width: 12.0, stroke_color: :cyan, fill_color: :burgundy + ellipse x: 50, y: 925, width: 200, height: 100, + stroke_width: 5.0, stroke_color: :cyan, + fill_color: :burgundy + save_png prefix: 'shape_' end diff --git a/spec/data/samples/draw_shapes.rb.txt b/spec/data/samples/draw_shapes.rb.txt index d845106..aed053b 100644 --- a/spec/data/samples/draw_shapes.rb.txt +++ b/spec/data/samples/draw_shapes.rb.txt @@ -1,5 +1,9 @@ cairo: antialias=(["subpixel"]) cairo: save([]) +cairo: set_source_color([:white]) +cairo: paint([]) +cairo: restore([]) +cairo: save([]) cairo: rounded_rectangle([300, 300, 400, 400, 0, 0]) cairo: set_source_color([:red]) cairo: set_line_width([50.0]) @@ -45,4 +49,16 @@ cairo: curve_to([150, 700, 150, 700, 625, 900]) cairo: set_source_color([:burgundy]) cairo: fill([]) cairo: restore([]) +cairo: save([]) +cairo: move_to([50, 975.0]) +cairo: curve_to([50, 950.0, 100.0, 925, 150.0, 925]) +cairo: curve_to([200.0, 925, 250, 950.0, 250, 975.0]) +cairo: curve_to([250, 1000.0, 200.0, 1025, 150.0, 1025]) +cairo: curve_to([100.0, 1025, 50, 1000.0, 50, 975.0]) +cairo: set_source_color([:cyan]) +cairo: set_line_width([5.0]) +cairo: stroke_preserve([]) +cairo: set_source_color([:burgundy]) +cairo: fill([]) +cairo: restore([]) surface: write_to_png(["_output/shape_00.png"]) diff --git a/spec/samples/expected/shape_00.png b/spec/samples/expected/shape_00.png index da0bf1b..fc317e4 100644 Binary files a/spec/samples/expected/shape_00.png and b/spec/samples/expected/shape_00.png differ diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d390ac1..2d98218 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -102,7 +102,7 @@ def mock_cairo(strio) 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 antialias= curve_to matrix= pango_layout_path).each do |m| + reset_clip antialias= curve_to matrix= pango_layout_path stroke_preserve).each do |m| allow(cxt).to receive(m) { |*args| strio << scrub_hex("cairo: #{m}(#{args})\n") } end