From ee0d232478c411aa31cf88aa5c7058fae26d4d7b Mon Sep 17 00:00:00 2001 From: Andy Meneely Date: Mon, 25 Apr 2016 23:36:10 -0400 Subject: [PATCH] text: rewrite how image space is carved Embedded images avoid zero-sized fonts by using non-printable characters instead. This is for #153 and #103 --- CHANGELOG.md | 10 ++-- lib/squib/graphics/text.rb | 12 +---- samples/embed_text.rb | 21 ++++++++ spec/data/samples/embed_text.rb.txt | 79 +++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 684b953..8d1282d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,17 +4,19 @@ Squib follows [semantic versioning](http://semver.org). ## v0.10.0 / Unreleased Features: -* Build groups! Simplify the process of building your deck different ways (e.g. one for color, one for PNP). Can be enabled explicitly or via command line. [See our shiny new docs for how these work](http://squib.readthedocs.org). -* The `csv` method now supports a `data` option to read CSV data directly. When set, it overrides the `file` option. -* The `csv` method now supports all of the Ruby CSV options (e.g. `col_sep`, `quote_char`). These options simply get passed through to Ruby, so as they change in Ruby, so the support changes in Squib. (#149) Special thanks to Qgel's initial pull request (#146). +* Build groups! Simplify the process of building your deck different ways (e.g. one for color, one for PNP). Can be enabled explicitly or via command line. [See our shiny new docs for how these work](http://squib.readthedocs.org/en/latest/build_groups.html). * New `use_layout` method will allow you to load a layout file as a DSL method instead of in the constructor. Useful in conjunction with build groups! (#141) +* The `csv` method now supports a `data` option to read CSV data directly. When set, it overrides the `file` option. +* The `csv` method now supports all of the Ruby CSV options (e.g. `col_sep`, `quote_char`). These options simply get passed through to Ruby, so as they change in Ruby, so the support changes in Squib (#149). Special thanks to Qgel's initial pull request (#146). +* The `csv` method now supports a block that it yields to for each element for pre-processing data (#145). Oh and `xlsx` has had that functionality for a while now, and now it's actually documented (#151). +* Rewrote the entire API doc and placed it on [squib.readthedocs.org](http://squib.readthedocs.org). :tada: Bugs: * The `save_pdf` method will flush to file upon exit so that the PDF is available immediately. (#150, thanks for the bug report Qgel!) +* The `text` embedding now supports both stroke-n-fill operations AND embedded images (#103 - aka "andy's nemesis"). Also: no more bizzare zero-sized fonts that made your OS secretly cry in the corner every time you embedded an image (#153). Chores: * Switched to `require_relative` internally throughout the codebase to be more pry-friendly (#130) -* Rewrote the entire API doc and placed it on [squib.readthedocs.org](http://squib.readthedocs.org). :tada: * Bumped dependency ruby-progressbar to 1.8. Compatibility: diff --git a/lib/squib/graphics/text.rb b/lib/squib/graphics/text.rb index b34b1d5..ff1b513 100644 --- a/lib/squib/graphics/text.rb +++ b/lib/squib/graphics/text.rb @@ -73,15 +73,6 @@ module Squib ret_key end - # When we do embedded icons, we create a 3-character string that has a font - # size of zero and a letter-spacing that fits the icon we need. That gives - # us the wrapping behavior we need but no clutter beneath. On most - # platforms, this works fine. On Linux, this creates - # a Cairo transformation matrix that - ZERO_WIDTH_CHAR_SIZE = 0 # this works on most platforms - # some platforms make this Pango pixels (1/1024), others a 1 pt font - ZERO_WIDTH_CHAR_SIZE = 1 if RbConfig::CONFIG['host_os'] === 'linux-gnu' - # :nodoc: # @api private def process_embeds(embed, str, layout) @@ -94,8 +85,7 @@ module Squib rule = embed.rules[key] spacing = rule[:box].width[@index] * Pango::SCALE kindex = clean_str.index(key) - kindex = clean_str[0..kindex].bytesize # convert to byte index (bug #57) - # str = str.sub(key, "aaa") + kindex = clean_str[0..kindex].bytesize # byte index (bug #57) str = str.sub(key, "\u0091\u0091\u0091") layout.markup = str clean_str = layout.text diff --git a/samples/embed_text.rb b/samples/embed_text.rb index 1028030..0d1e22c 100644 --- a/samples/embed_text.rb +++ b/samples/embed_text.rb @@ -73,6 +73,27 @@ Squib::Deck.new do 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 21', 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 21', 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 24', stroke_width: 2, + color: :red, stroke_color: :blue, dash: '3 3', align: :center, + 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 + save_png prefix: 'embed_' end diff --git a/spec/data/samples/embed_text.rb.txt b/spec/data/samples/embed_text.rb.txt index 66d5cbd..74c10e3 100644 --- a/spec/data/samples/embed_text.rb.txt +++ b/spec/data/samples/embed_text.rb.txt @@ -198,6 +198,85 @@ cairo: set_line_width([2.0]) cairo: stroke([]) pango: ellipsized?([]) cairo: restore([]) +cairo: save([]) +cairo: set_source_color(["black"]) +cairo: translate([0, 640]) +cairo: rotate([0]) +cairo: move_to([0, 0]) +pango: font_description=([MockDouble]) +pango: text=([":tool:"]) +pango: markup=(["foo"]) +pango: width=([184320]) +pango: height=([51200]) +pango: wrap=([#]) +pango: ellipsize=([#]) +pango: alignment=([#]) +pango: justify=([false]) +pango: markup=(["foo"]) +cairo: move_to([0, 0.0]) +cairo: move_to([0, 0.0]) +cairo: show_pango_layout([MockDouble]) +cairo: rounded_rectangle([0, 0, 0, 0, 0, 0]) +cairo: set_source_color([:red]) +cairo: set_line_width([2.0]) +cairo: stroke([]) +pango: ellipsized?([]) +cairo: restore([]) +cairo: save([]) +cairo: set_source_color(["black"]) +cairo: translate([200, 640]) +cairo: rotate([0]) +cairo: move_to([0, 0]) +pango: font_description=([MockDouble]) +pango: text=([":purse:"]) +pango: markup=(["foo"]) +pango: width=([184320]) +pango: height=([51200]) +pango: wrap=([#]) +pango: ellipsize=([#]) +pango: alignment=([#]) +pango: justify=([false]) +pango: markup=(["foo"]) +cairo: move_to([0, 0.0]) +cairo: move_to([0, 0.0]) +cairo: show_pango_layout([MockDouble]) +cairo: rounded_rectangle([0, 0, 0, 0, 0, 0]) +cairo: set_source_color([:red]) +cairo: set_line_width([2.0]) +cairo: stroke([]) +pango: ellipsized?([]) +cairo: restore([]) +cairo: save([]) +cairo: set_source_color(["red"]) +cairo: translate([0, 700]) +cairo: rotate([0]) +cairo: move_to([0, 0]) +pango: font_description=([MockDouble]) +pango: text=([":tool: Death to Nemesis bug 103!! :purse:"]) +pango: width=([389120]) +pango: height=([153600]) +pango: wrap=([#]) +pango: ellipsize=([#]) +pango: alignment=([#]) +pango: justify=([false]) +pango: markup=([":tool: Death to Nemesis bug 103!! :purse:"]) +cairo: move_to([0, 0.0]) +cairo: move_to([0, 0.0]) +cairo: show_pango_layout([MockDouble]) +cairo: pango_layout_path([MockDouble]) +cairo: set_source_color(["blue"]) +cairo: set_line_width([2]) +cairo: set_line_join([0]) +cairo: set_line_cap([0]) +cairo: set_dash([[3.0, 3.0]]) +cairo: stroke([]) +cairo: set_source_color(["red"]) +cairo: rounded_rectangle([0, 0, 0, 0, 0, 0]) +cairo: set_source_color([:magenta]) +cairo: set_line_width([2.0]) +cairo: stroke([]) +pango: ellipsized?([]) +cairo: restore([]) surface: write_to_png(["_output/embed_00.png"]) cairo: antialias=(["subpixel"]) cairo: antialias=(["subpixel"])