Text: outline a string with a color or gradient

Fill color is still the same with 'color' (i.e. can be overridden by markup still), but now there's a stroke_width and a stroke_color option that, when stroke_width > 0, will draw an outline below the text. Since this isn't a Pango feature, we can't do markup for outlines. (Maybe make that a feature request to Pango if you want it.)

Implements #51
This commit is contained in:
Andy Meneely
2015-04-28 22:27:26 -04:00
parent 70b2e52d57
commit 7c69cad506
21 changed files with 247 additions and 148 deletions
+6 -2
View File
@@ -37,13 +37,16 @@ module Squib
# @option opts valign [:top, :middle, :bottom] (:top) When width and height are set, align text vertically according to the ink extents of the text.
# @option opts ellipsize [:none, :start, :middle, :end, true, false] (:end) When width and height are set, determines the behavior of overflowing text. Also: `true` maps to `:end` and `false` maps to `:none`. Default `:end`
# @option opts angle [FixNum] (0) Rotation of the text in radians. Note that this rotates around the upper-left corner of the text box, making the placement of x-y coordinates slightly tricky.
# @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 hint [String] (:nil) draw a rectangle around the text with the given color. Overrides global hints (see {Deck#hint}).
# @return [Array] Returns an Array of hashes keyed by :width and :height that mark the ink extents of the text rendered.
# @api public
def text(opts = {})
opts = { stroke_width: 0 }.merge(opts)
opts = needs(opts, [:range, :str, :font, :font_size, :x, :y, :width, :height, :color, :wrap,
:align, :justify, :spacing, :valign, :markup, :ellipsize, :hint, :layout,
:angle, :quotes])
:angle, :quotes, :stroke_color, :stroke_width])
embed = TextEmbed.new
yield(embed) if block_given? #store the opts for later use
extents = Array.new(@cards.size)
@@ -53,7 +56,8 @@ module Squib
opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i],
opts[:markup][i], opts[:justify][i], opts[:wrap][i],
opts[:ellipsize][i], opts[:spacing][i], opts[:align][i],
opts[:valign][i], opts[:hint][i], opts[:angle][i])
opts[:valign][i], opts[:hint][i], opts[:angle][i],
opts[:stroke_color][i], opts[:stroke_width][i] )
end
return extents
end
+1 -1
View File
@@ -22,7 +22,7 @@ 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
:antialias=, :curve_to, :matrix, :matrix=, :identity_matrix, :pango_layout_path
# :nodoc:
# @api private
+13 -2
View File
@@ -143,17 +143,26 @@ module Squib
return draw_calls
end
def stroke_outline!(cc, layout, stroke_width, stroke_color)
if stroke_width > 0
cc.set_source_squibcolor(stroke_color)
cc.set_line_width(stroke_width)
cc.pango_layout_path(layout)
cc.stroke
end
end
# :nodoc:
# @api private
def text(embed,str, font, font_size, color,
x, y, width, height,
markup, justify, wrap, ellipsize,
spacing, align, valign, hint, angle)
spacing, align, valign, hint, angle,
stroke_color, stroke_width)
Squib.logger.debug {"Placing '#{str}'' with font '#{font}' @ #{x}, #{y}, color: #{color}, angle: #{angle} etc."}
extents = nil
str = str.to_s
use_cairo do |cc|
cc.set_source_squibcolor(color)
cc.translate(x,y)
cc.rotate(angle)
cc.move_to(0, 0)
@@ -184,6 +193,8 @@ module Squib
cc.move_to(0, vertical_start)
cc.update_pango_layout(layout)
stroke_outline!(cc, layout, stroke_width, stroke_color)
cc.set_source_squibcolor(color)
cc.show_pango_layout(layout)
begin
embed_draws.each { |ed| ed[:draw].call(self, ed[:x], ed[:y] + vertical_start) }