Browse Source

Smart quotes!

Closes #50
dev
Andy Meneely 11 years ago
parent
commit
674397c005
  1. 4
      CHANGELOG.md
  2. 10
      lib/squib/api/text.rb
  3. 29
      lib/squib/args/smart_quotes.rb
  4. 2
      lib/squib/constants.rb
  5. 2
      samples/embed_text.rb
  6. 6
      samples/text_options.rb
  7. 46
      spec/args/smart_quotes_spec.rb
  8. 6
      spec/data/samples/text_options.rb.txt

4
CHANGELOG.md

@ -1,11 +1,11 @@
# Squib CHANGELOG # Squib CHANGELOG
# v0.5.0 # v0.5.0
* Embedding of SVGs and PNGs into text! See README, `text_options.rb`, and `embed_text.rb`, and API documentation. This was a finnicky feature, so feedback and bug reports are welcome. (#30) * Embedding of SVGs and PNGs into text! See README, `text_options.rb`, and `embed_text.rb`, and API documentation. This was a finnicky feature, so feedback and bug reports are welcome.
* Curves! We can now do Bezier curves. Documented, and added to the sample `draw_shapes.rb` (#37). * Curves! We can now do Bezier curves. Documented, and added to the sample `draw_shapes.rb` (#37).
* Smart Quotes! The `text` rule now has a `quotes: 'smart'` option where straight quotes get converted to curly quotes. Assumes UTF-8, or you can specify your own quote characters if you're not in UTF-8.
Known issues Known issues
* Embedding icons for right-aligned and center-aligned is wrong for the first icon (#46). This is likely a Pango bug - I'm working on getting that fixed. There is a workaround.
* OSX Yosemite will show this warning: `<Error>: The function ‘CGFontGetGlyphPath’ is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.` This warning will go away when the Ruby Cairo bindings upgrades from 1.14.1 to 1.14.2. * OSX Yosemite will show this warning: `<Error>: The function ‘CGFontGetGlyphPath’ is obsolete and will be removed in an upcoming update. Unfortunately, this application, or a library it uses, is using this obsolete function, and is thereby contributing to an overall degradation of system performance.` This warning will go away when the Ruby Cairo bindings upgrades from 1.14.1 to 1.14.2.
# v0.4.0 # v0.4.0

10
lib/squib/api/text.rb

@ -1,4 +1,5 @@
require 'squib/api/text_embed' require 'squib/api/text_embed'
require 'squib/args/smart_quotes'
module Squib module Squib
class Deck class Deck
@ -38,17 +39,20 @@ module Squib
# @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 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 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 hint [String] (:nil) draw a rectangle around the text with the given color. Overrides global hints (see {Deck#hint}). # @option opts hint [String] (:nil) draw a rectangle around the text with the given color. Overrides global hints (see {Deck#hint}).
# @options ops quotes [:smart, :dumb, or Array]. Convert straight ("dumb") quotes to curly ("smart") quotes. The 'smart' option assumes UTF-8 characters. If you supply a two-element array of characters, those will be used (first is left, second is right). Smart quoting looks for a quote next to a letter, word, number, or underscore character. Default is to show straight quotes.
# @return [Array] Returns an Array of hashes keyed by :width and :height that mark the ink extents of the text rendered. # @return [Array] Returns an Array of hashes keyed by :width and :height that mark the ink extents of the text rendered.
# @api public # @api public
def text(opts = {}) def text(opts = {})
opts = needs(opts, [:range, :str, :font, :font_size, :x, :y, :width, :height, :color, :wrap, opts = needs(opts, [:range, :str, :font, :font_size, :x, :y, :width, :height, :color, :wrap,
:align, :justify, :spacing, :valign, :markup, :ellipsize, :hint, :layout, :angle]) :align, :justify, :spacing, :valign, :markup, :ellipsize, :hint, :layout,
:angle, :quotes])
embed = TextEmbed.new embed = TextEmbed.new
yield(embed) if block_given? #store the opts for later use yield(embed) if block_given? #store the opts for later use
extents = Array.new(@cards.size) extents = Array.new(@cards.size)
opts[:range].each do |i| opts[:range].each do |i|
extents[i] = @cards[i].text(embed, str = Args::SmartQuotes.new.process(opts[:str][i], opts[:quotes][i])
opts[:str][i], opts[:font][i], opts[:font_size][i], opts[:color][i], extents[i] = @cards[i].text(embed, str,
opts[:font][i], opts[:font_size][i], opts[:color][i],
opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i], opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i],
opts[:markup][i], opts[:justify][i], opts[:wrap][i], opts[:markup][i], opts[:justify][i], opts[:wrap][i],
opts[:ellipsize][i], opts[:spacing][i], opts[:align][i], opts[:ellipsize][i], opts[:spacing][i], opts[:align][i],

29
lib/squib/args/smart_quotes.rb

@ -0,0 +1,29 @@
module Squib
module Args
class SmartQuotes
def process(str, opt)
clean_opt = opt.to_s.downcase.strip
return str if clean_opt.eql? 'dumb'
if clean_opt.eql? 'smart'
quotify(str) # default to UTF-8
else
quotify(str, opt) # supplied quotes
end
end
# Convert regular quotes to smart quotes by looking for
# a boundary between a word character (letters, numbers, underscore)
# and a quote. Replaces with the UTF-8 equivalent.
# :nodoc:
# @api private
def quotify(str, quote_chars = ["\u201C", "\u201D"])
left_regex = /(\")(\w)/
right_regex = /(\w)(\")/
str.gsub(left_regex, quote_chars[0] + '\2')
.gsub(right_regex, '\1' + quote_chars[1])
end
end
end
end

2
lib/squib/constants.rb

@ -37,6 +37,7 @@ module Squib
:offset => 1.1, :offset => 1.1,
:prefix => 'card_', :prefix => 'card_',
:progress_bar => false, :progress_bar => false,
:quotes => :dumb,
:reflect_offset => 15, :reflect_offset => 15,
:reflect_percent => 0.25, :reflect_percent => 0.25,
:reflect_strength => 0.2, :reflect_strength => 0.2,
@ -121,6 +122,7 @@ module Squib
:layout => :layout, :layout => :layout,
:markup => :markup, :markup => :markup,
:mask => :mask, :mask => :mask,
:quotes => :quotes,
:rect_radius => :radius, :rect_radius => :radius,
:spacing => :spacing, :spacing => :spacing,
:str => :str, :str => :str,

2
samples/embed_text.rb

@ -72,7 +72,7 @@ end
Squib::Deck.new(cards: 3) do Squib::Deck.new(cards: 3) do
embed_text = 'Take 1 :tool: and gain 2 :health:.' embed_text = 'Take 1 :tool: and gain 2 :health:.'
text(str: embed_text, font: 'Sans', font_size: [18, 25, 32], text(str: embed_text, font: 'Sans', font_size: [18, 32, 45],
x: 0, y: 0, width: 180, height: 300, valign: :bottom, x: 0, y: 0, width: 180, height: 300, valign: :bottom,
align: :left, ellipsize: false, justify: false, hint: :cyan) do |embed| align: :left, ellipsize: false, justify: false, hint: :cyan) do |embed|
embed.svg key: ':tool:', width: 28, height: 28, file: 'spanner.svg' embed.svg key: ':tool:', width: 28, height: 28, file: 'spanner.svg'

6
samples/text_options.rb

@ -23,12 +23,12 @@ Squib::Deck.new(width: 825, height: 1125, cards: 3) do
text str: 'Font string sizes can be overridden per card.', x: 65, y: 350, text str: 'Font string sizes can be overridden per card.', x: 65, y: 350,
font: 'Impact 36', font_size: [16, 20, 24] font: 'Impact 36', font_size: [16, 20, 24]
text str: 'This text has fixed width, fixed height, center-aligned, middle-valigned, and has a red hint', text str: 'This text has fixed width, fixed height, center-aligned, middle-valigned, has a red hint, and "smart quotes"',
hint: :red, hint: :red,
x: 65, y: 400, x: 65, y: 400,
width: 300, height: 125, width: 300, height: 125,
align: :center, valign: 'MIDDLE', #case-insenstive strings allowed too. align: :center, valign: 'MIDDLE', # these can be specified with case-insenstive strings too
font: 'Arial 18' font: 'Serif 16', quotes: [:smart,:smart, :dumb]
extents = text str: 'Ink extent return value', extents = text str: 'Ink extent return value',
x: 65, y: 550, x: 65, y: 550,

46
spec/args/smart_quotes_spec.rb

@ -0,0 +1,46 @@
require 'spec_helper'
require 'squib/args/smart_quotes'
describe Squib::Args::SmartQuotes do
it 'does nothing on a non-quoted string' do
expect(subject.quotify('nothing')).to eq('nothing')
end
it 'left quotes at the beginning' do
expect(subject.quotify('"foo')).to eq("\u201Cfoo")
end
it 'left quotes in the middle of the string' do
expect(subject.quotify('hello "foo')).to eq("hello \u201Cfoo")
end
it 'right quotes at the end of a string' do
expect(subject.quotify('foo"')).to eq("foo\u201D")
end
it 'handles the entire string quoted' do
expect(subject.quotify('"foo"')).to eq("\u201Cfoo\u201D")
end
it "quotes in the middle of the string" do
expect(subject.quotify('hello "foo" world')).to eq("hello \u201Cfoo\u201D world")
end
it "allows custom quotes for different character sets" do
expect(subject.quotify('hello "foo" world', %w({ }))).to eq("hello {foo} world")
end
it "processes dumb quotes" do
expect(subject.process('hello "foo" world', :dumb)).to eq("hello \"foo\" world")
end
it "processes smart quotes" do
expect(subject.process('hello "foo" world', :smart)).to eq("hello \u201Cfoo\u201D world")
end
it "processes custom quotes" do
expect(subject.process('hello "foo" world', %w({ }))).to eq("hello {foo} world")
end
end

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

@ -331,7 +331,7 @@ cairo: translate([65, 400])
cairo: rotate([0]) cairo: rotate([0])
cairo: move_to([0, 0]) cairo: move_to([0, 0])
pango: font_description=([MockDouble]) pango: font_description=([MockDouble])
pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, and has a red hint"]) pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, has a red hint, and \u201Csmart quotes\u201D"])
pango: width=([307200]) pango: width=([307200])
pango: height=([128000]) pango: height=([128000])
pango: wrap=([#<Pango::Layout::WrapMode word-char>]) pango: wrap=([#<Pango::Layout::WrapMode word-char>])
@ -354,7 +354,7 @@ cairo: translate([65, 400])
cairo: rotate([0]) cairo: rotate([0])
cairo: move_to([0, 0]) cairo: move_to([0, 0])
pango: font_description=([MockDouble]) pango: font_description=([MockDouble])
pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, and has a red hint"]) pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, has a red hint, and \u201Csmart quotes\u201D"])
pango: width=([307200]) pango: width=([307200])
pango: height=([128000]) pango: height=([128000])
pango: wrap=([#<Pango::Layout::WrapMode word-char>]) pango: wrap=([#<Pango::Layout::WrapMode word-char>])
@ -377,7 +377,7 @@ cairo: translate([65, 400])
cairo: rotate([0]) cairo: rotate([0])
cairo: move_to([0, 0]) cairo: move_to([0, 0])
pango: font_description=([MockDouble]) pango: font_description=([MockDouble])
pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, and has a red hint"]) pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, has a red hint, and \"smart quotes\""])
pango: width=([307200]) pango: width=([307200])
pango: height=([128000]) pango: height=([128000])
pango: wrap=([#<Pango::Layout::WrapMode word-char>]) pango: wrap=([#<Pango::Layout::WrapMode word-char>])

Loading…
Cancel
Save