From 42ae2144e015dc840d2f1210aee1d430e4f15830 Mon Sep 17 00:00:00 2001 From: Andy Meneely Date: Tue, 24 Mar 2015 14:58:42 -0400 Subject: [PATCH] Fix index location issue, working on vertical placement Contributes to #30 Also added little adjusters for the icons in case your icon is a little off. [skip ci] --- lib/squib/api/text_embed.rb | 8 ++++-- lib/squib/constants.rb | 8 ++++++ lib/squib/graphics/text.rb | 54 +++++++++++++++++++++++-------------- samples/embed_text.rb | 40 +++++++++++++++++++++++---- 4 files changed, 83 insertions(+), 27 deletions(-) diff --git a/lib/squib/api/text_embed.rb b/lib/squib/api/text_embed.rb index afed104..033d6b9 100644 --- a/lib/squib/api/text_embed.rb +++ b/lib/squib/api/text_embed.rb @@ -17,8 +17,10 @@ module Squib # @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 layout [String, Symbol] (nil) entry in the layout to use as defaults for this command. See {file:README.md#Custom_Layouts Custom Layouts}. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion} - # @option opts width [Integer, :native] (:native) the width of the image rendered - # @option opts height [Integer, :native] the height the height of the image rendered + # @option opts width [Integer, :native] (:native) the width of the image rendered. + # @option opts height [Integer, :native] the height the height of the image rendered. + # @option opts dx [Integer] (0) "delta x", or adjust the icon horizontally by x pixels + # @option opts dy [Integer] (0) "delta y", or adjust the icon vertically by y pixels # @option opts alpha [Decimal] (1.0) the alpha-transparency percentage used to blend this image. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion} # @option opts blend [:none, :multiply, :screen, :overlay, :darken, :lighten, :color_dodge, :color_burn, :hard_light, :soft_light, :difference, :exclusion, :hsl_hue, :hsl_saturation, :hsl_color, :hsl_luminosity] (:none) the composite blend operator used when applying this image. See Blend Modes at http://cairographics.org/operators. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion} # @option opts angle [FixNum] (0) Rotation of the in radians. Note that this rotates around the upper-left corner, making the placement of x-y coordinates slightly tricky. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion} @@ -41,6 +43,8 @@ module Squib # @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}. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion} # @option opts width [Integer, :native] (:native) the width of the image rendered # @option opts height [Integer, :native] the height the height of the image rendered + # @option opts dx [Integer] (0) "delta x", or adjust the icon horizontally by x pixels + # @option opts dy [Integer] (0) "delta y", or adjust the icon vertically by y pixels # @option opts alpha [Decimal] (1.0) the alpha-transparency percentage used to blend this image. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion} # @option opts blend [:none, :multiply, :screen, :overlay, :darken, :lighten, :color_dodge, :color_burn, :hard_light, :soft_light, :difference, :exclusion, :hsl_hue, :hsl_saturation, :hsl_color, :hsl_luminosity] (:none) the composite blend operator used when applying this image. See Blend Modes at http://cairographics.org/operators. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion} # @option opts angle [FixNum] (0) Rotation of the in radians. Note that this rotates around the upper-left corner, making the placement of x-y coordinates slightly tricky. Supports Arrays, see {file:README.md#Arrays_and_Singleton_Expansion Arrays and Singleon Expansion} diff --git a/lib/squib/constants.rb b/lib/squib/constants.rb index b1e503a..cc55b5d 100644 --- a/lib/squib/constants.rb +++ b/lib/squib/constants.rb @@ -12,6 +12,8 @@ module Squib :count_format => '%02d', :default_font => 'Arial 36', :dir => '_output', + :dx => 0, # delta + :dy => 0, # delta :dx1 => 0, :dx2 => 0, :dy1 => 0, @@ -147,6 +149,12 @@ module Squib # value: the user-facing API key (e.g. radius: '1in') UNIT_CONVERSION_PARAMS = { :circle_radius => :radius, + :dx => 0, # delta + :dy => 0, # delta + :dx1 => 0, + :dx2 => 0, + :dy1 => 0, + :dy2 => 0, :gap => :gap, :height => :height, :margin => :margin, diff --git a/lib/squib/graphics/text.rb b/lib/squib/graphics/text.rb index c312052..9f8ccaf 100644 --- a/lib/squib/graphics/text.rb +++ b/lib/squib/graphics/text.rb @@ -62,24 +62,24 @@ module Squib # :nodoc: # @api private - def valign!(cc, layout, valign) - if layout.height > 0 - ink_extents = layout.extents[1] - case valign.to_s.downcase - when 'middle' - cc.move_to(0, (layout.height - ink_extents.height) / (2 * Pango::SCALE)) - when 'bottom' - cc.move_to(0, (layout.height - ink_extents.height) / Pango::SCALE) - end + def compute_valign(layout, valign) + return 0 unless layout.height > 0 + ink_extents = layout.extents[1] + case valign.to_s.downcase + when 'middle' + Pango.pixels( (layout.height - ink_extents.height) / 2) + when 'bottom' + Pango.pixels(layout.height - ink_extents.height) + else + 0 end end # :nodoc: # @api private def set_wh!(layout, width, height) - layout.width = width * Pango::SCALE unless width.nil? || width == :native + layout.width = width * Pango::SCALE unless width.nil? || width == :native layout.height = height * Pango::SCALE unless height.nil? || height == :native - layout end # :nodoc: @@ -100,15 +100,17 @@ module Squib # :nodoc: # @api private - def process_embeds(embed, str, layout, cc) + def process_embeds(embed, str, layout, vertical_start) return unless embed.rules.any? - while (key = next_embed(embed.rules.keys, str)) != nil + layout.markup = str + clean_str = layout.text + while (key = next_embed(embed.rules.keys, clean_str)) != nil rule = embed.rules[key] spacing = rule[:width] * Pango::SCALE - index = str.gsub(/ <\/span>/,' ').index(key) - str = str.sub(key, " ") + index = clean_str.index(key) + str.sub!(key, " ") layout.markup = str - cc.update_pango_layout(layout) + clean_str = layout.text rect = layout.index_to_pos(index) iter = layout.iter while iter.next_char! && iter.index < index; end @@ -118,8 +120,17 @@ module Squib Pango::Layout::Alignment::RIGHT Squib.logger.warn "Center- or right-aligned text do not always embed properly. This is a known issue with a workaround. See https://github.com/andymeneely/squib/issues/46" end - x = Pango.pixels(rect.x + (letter_width / 2)) - y = Pango.pixels(rect.y) + x = Pango.pixels(rect.x + (letter_width / 2)) + rule[:dx] + y = Pango.pixels(rect.y) + rule[:dy] + vertical_start + puts <<-EOS + Embed: #{key} + Index: #{index} + Spacing: #{spacing} or #{Pango.pixels(spacing)}px + Markup string: #{str} + index_to_pos: #{rect.x},#{rect.y} or #{Pango.pixels(rect.x)},#{Pango.pixels(rect.y)} + Computed x,y: #{x},#{y} + ================= + EOS rule[:draw].call(self, x, y) end end @@ -155,10 +166,13 @@ module Squib layout.spacing = spacing * Pango::SCALE unless spacing.nil? cc.update_pango_layout(layout) - valign!(cc, layout, valign) + vertical_start = compute_valign(layout, valign) + + process_embeds(embed, str, layout, vertical_start) + + cc.move_to(0, vertical_start) cc.update_pango_layout(layout) - process_embeds(embed, str, layout, cc) cc.show_pango_layout(layout) draw_text_hint(cc,x,y,layout,hint,angle) extents = { width: layout.extents[1].width / Pango::SCALE, diff --git a/samples/embed_text.rb b/samples/embed_text.rb index da66f61..ad7c410 100644 --- a/samples/embed_text.rb +++ b/samples/embed_text.rb @@ -2,17 +2,47 @@ require 'squib' Squib::Deck.new do background color: :white - rect x: 0, y: 0, width: 825, height: 1125 - rect x: 0, y: 0, width: 180, height: 180, stroke_color: :red + rect x: 0, y: 0, width: 825, height: 1125, stroke_width: 2.0 - embed_text = 'Take 1 :tool:and gain 2 :health:. Take 2 :tool: and gain 3 :purse: if level 2.' - text(str: embed_text, font: 'Sans 18', - x: 0, y: 0, width: 180, + embed_text = 'Take 11 :tool: and gain 2 :health:. Take 2 :tool: and gain 3 :purse: if level 2.' + text(str: embed_text, font: 'Sans 21', + x: 0, y: 0, width: 180, hint: :red, align: :left, ellipsize: false, justify: false) do |embed| + embed.svg key: ':tool:', width: 28, height: 28, dx: 0, dy: 3, file: 'spanner.svg' + embed.svg key: ':health:', width: 28, height: 28, dx: 2, dy: 3, file: 'glass-heart.svg' + embed.png key: ':purse:', width: 28, height: 28, dx: 0, dy: 3, file: 'shiny-purse.png' + end + + embed_text = 'Middle align: Take 1 :tool: and gain 2 :health:. Take 2 :tool: and gain 3 :purse:' + text(str: embed_text, font: 'Sans 21', + x: 200, y: 0, width: 180, height: 300, valign: :middle, + align: :left, ellipsize: false, justify: false, hint: :cyan) do |embed| + embed.svg key: ':tool:', width: 28, height: 28, file: '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 + + embed_text = 'This :tool: will not align on the bottom properly. :purse:' + text(str: embed_text, font: 'Sans 21', + x: 400, y: 0, width: 180, height: 300, valign: :bottom, + align: :left, ellipsize: false, justify: false, hint: :cyan) do |embed| embed.svg key: ':tool:', width: 28, height: 28, file: '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 + embed_text = 'This :tool: will not align on the bottom properly. :purse:' + text(str: embed_text, font: 'Sans 21', + x: 400, y: 350, width: 180, height: 300, valign: :bottom, + align: :left, ellipsize: false, justify: false, hint: :cyan) do |embed| + # embed.svg key: ':tool:', width: 28, height: 28, file: '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 + + text str: 'But this does align properly', font: 'Sans 21', + x: 600, y: 0, width: 180, height: 300, valign: :bottom, + align: :left, ellipsize: false, justify: false, hint: :cyan + save_png prefix: 'embed_' end \ No newline at end of file