The Mighty text Method

The text method is a particularly powerful method with a ton of options. Be sure to check the option-by-option details in the DSL reference, but here are the highlights.

Fonts

To set the font, your text method call will look something like this:

text str: "Hello", font: 'MyFont Bold 32'

The 'MyFont Bold 32' is specified as a “Pango font string”, which can involve a lot of options including backup font families, size, all-caps, stretch, oblique, italic, and degree of boldness. (These options are only available if the underlying font supports them, however.) Here’s are some text calls with different Pango font strings:

text str: "Hello", font: 'Sans 18'
text str: "Hello", font: 'Arial,Verdana weight=900 style=oblique 36'
text str: "Hello", font: 'Times New Roman,Sans 25'

Finally, Squib’s text method has options such as font_size that allow you to override the font string. This means that you can set a blanket font for the whole deck, then adjust sizes from there. This is useful with layouts and extends too (see Layouts are Squib’s Best Feature).

Note

When the font has a space in the name (e.g. Times New Roman), you’ll need to put a backup to get Pango’s parsing to work. In some operating systems, you’ll want to simply end with a comma:

text str: "Hello", font: 'Times New Roman, 25'

Note

Most of the font rendering is done by a combination of your installed fonts, your OS, and your graphics card. Thus, different systems will render text slightly differently.

Width and Height

By default, Pango text boxes will scale the text box to whatever you need, hence the :native default. However, for most of the other customizations to work (e.g. center-aligned) you’ll need to specify the width. If both the width and the height are specified and the text overflows, then the ellipsize option is consulted to figure out what to do with the overflow. Also, the valign will only work if height is also set to something other than :native.

Autoscaling Font Size

See our sample below Sample: _autoscale_font.rb

Hints

Laying out text by typing in numbers can be confusing. What Squib calls “hints” is merely a rectangle around the text box. Hints can be turned on globally in the config file, using the hint method, or in an individual text method. These are there merely for prototyping and are not intended for production. Additionally, these are not to be conflated with “rendering hints” that Pango and Cairo mention in their documentation.

Extents

Sometimes you want size things based on the size of your rendered text. For example, drawing a rectangle around card’s title such that the rectangle perfectly fits. Squib returns the final rendered size of the text so you can work with it afterward. It’s an array of hashes that correspond to each card. The output looks like this:

Squib::Deck.new(cards: 2) do
  extents = text(str: ['Hello', 'World!'])
  puts extents
end

will output:

[{:width=>109, :height=>55}, {:width=>142, :height=>55}] # Hello was 109 pixels wide, World 142 pixels

Embedding Images

Squib can embed icons into the flow of text. To do this, you need to define text keys for Squib to look for, and then the corresponding files. The object given to the block is a TextEmbed, which supports PNG and SVG. Here’s a minimal example:

text(str: 'Gain 1 :health:') do |embed|
  embed.svg key: ':health:', file: 'heart.svg'
end

Markup

See Markup in text.

Samples

These samples are maintained in the repository here in case you need some of the assets referenced.

Sample: _text.rb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
require 'squib'
require 'squib/sample_helpers'

Squib::Deck.new(width: 1000, height: 1450) do
  draw_graph_paper width, height

  sample 'Font strings are quite expressive. Specify family, modifiers, then size. Font names with spaces in them should end with a comma to help with parsing.' do |x, y|
    text font: 'Arial bold italic 11', str: 'Bold and italic!', x: x, y: y - 50
    text font: 'Arial weight=300 11', str: 'Light bold!', x: x, y: y
    text font: 'Times New Roman, 11', str: 'Times New Roman', x: x, y: y + 50
    text font: 'NoSuchFont,Arial 11', str: 'Arial Backup', x: x, y: y + 100
  end

  sample 'Specify width and height to see a text box. Also: set "hint" to see the extents of your text box' do |x, y|
    text str: 'This has fixed width and height.', x: x, y: y,
         hint: :red, width: 300, height: 100, font: 'Serif bold 8'
  end

  sample 'If you specify the width only, the text will ellipsize.' do |x, y|
    text str: 'The meaning of life is 42', x: x - 50, y: y,
         hint: :red, width: 350, font: 'Serif bold 7'
  end

  sample 'If you specify ellipsize: :autosize, the font size will autoscale.' do |x, y|
    text str: 'This text doeas not fit with font size 7. It is autoscaled to the largest size that fits instead.', x: x - 50, y: y,
         hint: :red, width: 350, height: 100, ellipsize: :autoscale, font: 'Serif bold 7'
  end

  sample 'If you specify the width only, and turn off ellipsize, the height will auto-stretch.' do |x, y|
    text str: 'This has fixed width, but not fixed height.', x: x, y: y,
         hint: :red, width: 300, ellipsize: false, font: 'Serif bold 8'
  end

  sample 'The text method returns the ink extents of each card\'s rendered text. So you can custom-fit a shape around it.' do |x, y|
    ['Auto fit!', 'Auto fit!!!!' ].each.with_index do |str, i|
      text_y = y + i * 50
      extents = text str: str, x: x, y: text_y, font: 'Sans Bold 8'

      # Extents come back as an array of hashes, which can get split out like this
      text_width  = extents[0][:width]
      text_height = extents[0][:height]
      rect x: x, y: text_y, width: text_width, height: text_height, radius: 10,
           stroke_color: :purple, stroke_width: 3
    end
  end

  sample 'Text can be rotated about the upper-left corner of the text box. Unit is in radians.' do |x, y|
    text str: 'Rotated', hint: :red, x: x, y: y, angle: Math::PI / 6
  end

  save_png prefix: '_text_'
end

Sample: text_options.rb

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
# encoding: UTF-8
# require 'squib'
require_relative '../../lib/squib'

data = { 'name' => ['Thief', 'Grifter', 'Mastermind'],
        'level' => [1, 2, 3] }
longtext = "This is left-justified text, with newlines.\nWhat do you know about tweetle beetles? well... When tweetle beetles fight, it's called a tweetle beetle battle. And when they battle in a puddle, it's a tweetle beetle puddle battle. AND when tweetle beetles battle with paddles in a puddle, they call it a tweetle beetle puddle paddle battle. AND... When beetles battle beetles in a puddle paddle battle and the beetle battle puddle is a puddle in a bottle... ..they call this a tweetle beetle bottle puddle paddle battle muddle."

Squib::Deck.new(width: 825, height: 1125, cards: 3) do
  background color: :white
  rect x: 15, y: 15, width: 795, height: 1095, x_radius: 50, y_radius: 50
  rect x: 30, y: 30, width: 128, height: 128, x_radius: 25, y_radius: 25

  # Arrays are rendered over each card
  text str: data['name'], x: 250, y: 55, font: 'Arial weight=900 18'
  text str: data['level'], x: 65, y: 40, font: 'Arial 24', color: :burnt_orange

  text str: 'Font strings are expressive!', x:65, y: 200,
       font: 'Impact bold italic 12'

  text str: 'Font strings are expressive!', x:65, y: 300,
       font: 'Arial,Verdana weight=900 style=oblique 12'

  text str: 'Font string sizes can be overridden per card.', x: 65, y: 350,
       font: 'Impact 12', font_size: [5, 7, 8]

  text str: 'This text has fixed width, fixed height, center-aligned, middle-valigned, and has a red hint',
       hint: :red,
       x: 65, y: 400,
       width: 300, height: 125,
       align: :center, valign: 'MIDDLE', # these can be specified with case-insenstive strings too
       font: 'Serif 5'

  extents = text str: 'Ink extent return value',
       x: 65, y: 550,
       font: 'Sans Bold', font_size: [5, 7, 8]
  margin = 10
  # Extents come back as an array of hashes, which can get split out like this
  ws = extents.inject([]) { |arr, ext| arr << ext[:width] + 10; arr }
  hs = extents.inject([]) { |arr, ext| arr << ext[:height] + 10; arr }
  rect x: 65 - margin / 2, y: 550 - margin / 2,
       width: ws, height: hs,
       radius: 10, stroke_color: :black

  # If width & height are defined and the text will overflow the box, we can ellipsize.
  text str: "Ellipsization!\nThe ultimate question of life, the universe, and everything to life and everything is 42",
       hint: :green, font: 'Arial 7',
       x: 450, y: 400,
       width: 280, height: 180,
       ellipsize: true

  # Text hints are guides for showing you how your text boxes are laid out exactly
  hint text: :cyan
  set font: 'Serif 7' # Impacts all future text calls (unless they specify differently)
  text str: 'Text hints & fonts are globally togglable!', x: 65, y: 625
  set font: :default # back to Squib-wide default
  hint text: :off
  text str: 'See? No hint here.',
        x: 565, y: 625,
        font: 'Arial 7'

  # Text can be rotated, in radians, about the upper-left corner of the text box.
  text str: 'Rotated',
        x: 565, y: 675, angle: 0.2,
        font: 'Arial 6', hint: :red

  # Text can be justified, and have newlines
  text str: longtext, font: 'Arial 5',
       x: 65, y: 700,
       width: '1.5in', height: inches(1),
       justify: true, spacing: -6

  # Here's how you embed images into text.
  # Pass a block to the method call and use the given context
  embed_text = 'Embedded icons! Take 1 :tool: and gain 2:health:. If Level 2, take 2 :tool:'
  text(str: embed_text, font: 'Sans 6',
       x: '1.8in', y: '2.5in', width: '0.85in',
       align: :left, ellipsize: false) 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'
  end

  text str: 'Fill n <span fgcolor="#ff0000">stroke</span>',
       color: :green, stroke_width: 2.0, stroke_color: :blue,
       x: '1.8in', y: '2.9in', width: '0.85in', font: 'Sans Bold 9', markup: true

  text str: 'Stroke n <span fgcolor="#ff0000">fill</span>',
       color: :green, stroke_width: 2.0, stroke_color: :blue, stroke_strategy: :stroke_first,
       x: '1.8in', y: '3.0in', width: '0.85in', font: 'Sans Bold 9', markup: true

  text str: 'Dotted',
       color: :white, stroke_width: 2.0, dash: '4 2', stroke_color: :black,
       x: '1.8in', y: '3.1in', width: '0.85in', font: 'Sans Bold 9', markup: true
  #
  text str: "<b>Markup</b> is <i>quite</i> <s>'easy'</s> <span fgcolor=\"\#ff0000\">awesome</span>. Can't beat those \"smart\" 'quotes', now with 10--20% more en-dashes --- and em-dashes --- with explicit ellipses too...",
       markup: true,
       x: 50, y: 1000,
       width: 750, height: 100,
       valign: :bottom,
       font: 'Serif 6', hint: :cyan

  save prefix: 'text_options_', format: :png
end

Sample: embed_text.rb

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
require 'squib'

Squib::Deck.new do
  background color: :white
  rect x: 0, y: 0, width: 825, height: 1125, stroke_width: 2.0

  embed_text = 'Take 11 :tool: and gain 2 :health:. Take <b>2</b> :tool: <i>and gain 3 :purse: if level 2.</i>'
  text(str: embed_text, font: 'Sans 7',
       x: 0, y: 0, width: 180, hint: :red,
       align: :left, ellipsize: false, justify: false) 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 = 'Middle align: Take 1 :tool: and gain 2 :health:. Take 2 :tool: and gain 3 :purse:'
  text(str: embed_text, font: 'Sans 7',
       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: aligns on the bottom properly. :purse:'
  text(str: embed_text, font: 'Sans 7',
       x: 400, y: 0, width: 180, height: 300, valign: :bottom,
       align: :left, ellipsize: false, justify: false, hint: :green) 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 = 'Yes, this wraps strangely. We are trying to determine the cause. These are 1 :tool::tool::tool: and these are multiple :tool::tool: :tool::tool:'
  text(str: embed_text, font: 'Sans 6',
       x: 600, y: 0, width: 180, height: 300, wrap: :word_char,
       align: :left, ellipsize: false, justify: false, hint: :cyan) do |embed|
    embed.svg key: ':tool:', width: 28, height: 28, file: 'spanner.svg'
  end

  embed_text = ':tool:Justify will :tool: work too, and :purse: with more words just for fun'
  text(str: embed_text, font: 'Sans 7',
       x: 0, y: 320, width: 180, height: 300, valign: :bottom,
       align: :left, ellipsize: false, justify: true, hint: :magenta) 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 = 'Right-aligned works :tool: with :health: and :purse:'
  text(str: embed_text, font: 'Sans 7',
       x: 200, y: 320, width: 180, height: 300, valign: :bottom,
       align: :right, ellipsize: false, justify: false, hint: :magenta) 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 = ':tool:Center-aligned works :tool: with :health: and :purse:'
  text(str: embed_text, font: 'Sans 7',
       x: 400, y: 320, width: 180, height: 300,
       align: :center, ellipsize: false, justify: false, hint: :magenta) do |embed|
    embed.svg key: ':tool:',   width: 28, height: 28, data: File.read('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 = 'Markup --- and typography replacements --- with ":tool:" icons <i>won\'t</i> fail'
  text(str: embed_text, font: 'Serif 6', markup: true,
       x: 600, y: 320, width: 180, height: 300,
       align: :center, hint: :magenta) do |embed|
    embed.svg key: ':tool:',   width: 28, height: 28, file: 'spanner.svg'
  end

  embed_text = ':tool:' # JUST the icon
  text(str: embed_text, x: 0, y: 640, width: 180, height: 50, markup: true,
     font: 'Arial 7', align: :center, valign: :middle, hint: :red) do |embed|
    embed.svg key: ':tool:', width: 28, height: 28, file: 'spanner.svg'
  end

  embed_text = ':purse:' # JUST the icon
  text(str: embed_text, x: 200, y: 640, width: 180, height: 50, markup: true,
     font: 'Arial 7', align: :center, valign: :middle, hint: :red) do |embed|
    embed.png key: ':purse:', width: 28, height: 28, file: 'shiny-purse.png'
  end

  embed_text = ":tool: Death to Nemesis bug 103!! :purse:"
  text(str: embed_text, font: 'Sans Bold 8', stroke_width: 2,
       color: :red, stroke_color: :blue, dash: '3 3', align: :left,
       valign: :middle, x: 0, y: 700, width: 380, height: 150,
       hint: :magenta) do |embed|
    embed.svg key: ':tool:', file: 'spanner.svg', width: 32, height: 32
    embed.png key: ':purse:', file: 'shiny-purse.png', width: 32, height: 32
  end

  embed_text = 'You can adjust the icon with dx and dy. Normal: :tool: Adjusted: :heart:'
  text(str: embed_text, font: 'Sans 6', x: 400, y: 640, width: 180,
       height: 300, hint: :magenta) do |embed|
    embed.svg key: ':tool:', width: 28, height: 28, file: 'spanner.svg'
    embed.svg key: ':heart:', width: 28, height: 28, dx: 10, dy: 10,
              file: 'glass-heart.svg'
  end

  embed_text = "Native sizes work too\n:tool:\n\n\n\n\n\n:shiny-purse:\n\n\n\n\n\n:tool2:"
  text(str: embed_text, font: 'Sans 6', x: 600, y: 640, width: 180,
       height: 475, hint: :magenta) do |embed|
    embed.svg key: ':tool:', width: :native, height: :native,
              file: 'spanner.svg'
    embed.svg key: ':tool2:', width: :native, height: :native,
              data: File.open('spanner.svg','r').read
    embed.png key: ':shiny-purse:', width: :native, height: :native,
              file: 'shiny-purse.png'
  end

  save_png prefix: 'embed_'
end

Squib::Deck.new(cards: 3) do
  background color: :white
  str = 'Take 1 :tool: and gain 2 :health:.'
  text(str: str, font: 'Sans', font_size: [6, 8.5, 11.5],
       x: 0, y: 0, width: 180, height: 300, valign: :bottom,
       align: :left, ellipsize: false, justify: false, hint: :cyan) do |embed|
    embed.svg key: ':tool:',   width: [28, 42, 56], height: [28, 42, 56], file: 'spanner.svg'
    embed.svg key: ':health:', width: [28, 42, 56], height: [28, 42, 56], file: 'glass-heart.svg'
  end
  save_sheet prefix: 'embed_multisheet_', columns: 3
end

Sample: config_text_markup.rb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
require 'squib'

Squib::Deck.new(config: 'config_text_markup.yml') do
  background color: :white
  text str: %{"'Yaml ain't markup', he says"},
       x: 10, y: 10, width: 300, height: 200, font: 'Serif 7',
       markup: true, hint: :cyan

  text str: 'Notice also the antialiasing method.',
       x: 320, y: 10, width: 300, height: 200, font: 'Arial Bold 7'

  save_png prefix: 'config_text_'
end

Squib::Deck.new(config: 'config_disable_quotes.yml') do
  text str: %{This has typographic sugar --- and ``explicit'' quotes --- but the quotes are "dumb"},
       x: 10, y: 10, width: 300, height: 200, font: 'Serif 7',
       markup: true, hint: :cyan
  save_png prefix: 'config_disable_text_'
end
1
2
3
4
5
6
7
8
9
# We can configure what characters actually get replaced by quoting them with unicode code points.
lsquote: "\u2018" #note that Yaml wants double quotes here to use escape chars
rsquote: "\u2019"
ldquote: "\u201C"
rdquote: "\u201D"
em_dash: "\u2014"
en_dash: "\u2013"
ellipsis: "\u2026"
antialias: gray
1
2
3
# If we want to disable smart quoting and only allow explicit quoting within markup, 
# use this option
smart_quotes: false

Sample: _autoscale_font.rb

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
require 'squib'

# Autoscaling font is handy for a bunch of things:
#  * Picture-perfect text fitting for one-off
#  * Rapid prototyping where you don't have to think about sizes
#
# We've got three options...
#  Option 1. Use your data <--- good for picture-perfect
#  Option 2. Use ellipsize: :autoscale <--- good for rapid prototyping
#  Option 3. Use map ranges in your code <--- good for picture-perfect
#                                             or other weird cases

###########################
# Option 1: Use your data #
###########################
# If you want to tweak the font size per-card, you can always make font_size
# a column and map it from there. This is tedious but leads to perfectly
# customized results
my_data = Squib.csv data: <<~CSV
  "Title","Font Size"
  "Short & Big",10
  "Medium Length & Size", 5
  "Super duper long string here, therefore a smaller font.", 4
CSV

Squib::Deck.new(width: 300, height: 75, cards: 3) do
  background color: :white
  rect stroke_color: :black

  text str: my_data.title, font: 'Arial',
       font_size: my_data.font_size, # <-- key part
       x: 10, y:10, align: :center,
       width: 280, # <-- note how height does NOT need to be set
       ellipsize: false,
       hint: :red
  save_sheet columns: 3, prefix: 'autoscale_w_data_'
end

#######################################
# Option 2: Use ellipsize: :autoscale #
#######################################
# If set the height, you can set "autoscale" and it will incrementally
# downgrade the font size until the text does not ellipsize
#
# Great for rapid prototyping, set-it-and-forget-it
#
# NOTE: You MUST set the height for this to work. Otherwise, the text will
#       never ellipsize and Squib doesn't know when to start autoscaling
Squib::Deck.new(width: 300, height: 75, cards: 3) do
  background color: :white
  rect stroke_color: :black
  title = ['Short & Big',
           'Medium Length & Size',
           'Super duper long string here, therefore a smaller font.']

  # Automatically scale the text down from the specified font_size to the largest size that fits
  text str: title, font: 'Arial',
       font_size: 15, # <-- this is the MAX font size. Scale down from here
       ellipsize: :autoscale, # <-- key part
       height: 50, # <-- need this to be set to something
       width: 280, x: 10, y: 10, align: :center, valign: :middle, hint: :red

  save_sheet columns: 3, prefix: 'autoscale_w_ellipsize_'
end

############################################
# Option 3: Mapping to ranges in your code #
############################################
# Here's an in-between option that allows you to programmatically apply font
# sizes. This allows you a ton of flexibility.Probably more flexibility than
# you need, frankly. But one advantage is that you don't have to set the height
def autoscale(str_array)
  str_array.map do | str |
    case str.length
    when 0..15
      9
    when 16..20
      6
    else
      4
    end
  end
end

Squib::Deck.new(width: 300, height: 75, cards: 3) do
  background color: :white
  rect stroke_color: :black
  title = ['Short & Big',
           'Medium Length & Size',
           'Super duper long string here, therefore a smaller font.']

  # Scale text based on the string length
  text str: title, font: 'Arial',
       font_size: autoscale(title), # <-- key part
       x: 10, y:10, align: :center, width: 280, ellipsize: false, hint: :red

    save_sheet columns: 3, prefix: 'autoscale_w_range_'
end