diff --git a/lib/squib/api/settings.rb b/lib/squib/api/settings.rb new file mode 100644 index 0000000..446c532 --- /dev/null +++ b/lib/squib/api/settings.rb @@ -0,0 +1,9 @@ +module Squib + class Deck + + def hint(text: nil) + @text_hint = colorify(text, nillable: true) + end + + end +end diff --git a/lib/squib/api/shapes.rb b/lib/squib/api/shapes.rb index 3aeb8e4..9ba831c 100644 --- a/lib/squib/api/shapes.rb +++ b/lib/squib/api/shapes.rb @@ -2,10 +2,11 @@ module Squib class Deck def rect(range: :all, x: 0, y: 0, width: 825, height: 1125, \ - x_radius: 0, y_radius: 0) + x_radius: 0, y_radius: 0, color: :black) range = rangeify(range) + color = colorify(color) range.each do |i| - @cards[i].draw_rectangle(x, y, width, height, x_radius, y_radius) + @cards[i].draw_rectangle(x, y, width, height, x_radius, y_radius, color) end end diff --git a/lib/squib/api/text.rb b/lib/squib/api/text.rb index 50bf819..62cdd9c 100644 --- a/lib/squib/api/text.rb +++ b/lib/squib/api/text.rb @@ -1,10 +1,5 @@ module Squib class Deck - def fontify (font) - font = 'Arial 36' if font==:use_set - font - end - def font(type: 'Arial', size: 12, **options) raise 'Not implemented!' end @@ -17,7 +12,8 @@ module Squib range = rangeify(range) str = [str] * @cards.size unless str.respond_to? :each font = fontify(font) - color = colorify(options[:color]) + color = colorify(options[:color], nillable: false) + options['hint'] = colorify(options['hint']) unless options['hint'].nil? range.each do |i| cards[i].text(str[i], font, x, y, color, options) end diff --git a/lib/squib/card.rb b/lib/squib/card.rb index 0247589..1e6cda7 100644 --- a/lib/squib/card.rb +++ b/lib/squib/card.rb @@ -1,12 +1,14 @@ require 'cairo' +require 'squib/input_helpers' module Squib class Card + include Squib::InputHelpers attr_reader :width, :height attr_accessor :cairo_surface, :cairo_context - def initialize(width, height) - @width=width; @height=height + def initialize(deck, width, height) + @deck=deck; @width=width; @height=height @cairo_surface = Cairo::ImageSurface.new(width,height) @cairo_context = Cairo::Context.new(@cairo_surface) end diff --git a/lib/squib/deck.rb b/lib/squib/deck.rb index 3055132..5bb5be3 100644 --- a/lib/squib/deck.rb +++ b/lib/squib/deck.rb @@ -1,15 +1,18 @@ require 'squib/card' +require 'squib/input_helpers' module Squib class Deck include Enumerable + include Squib::InputHelpers attr_reader :width, :height attr_reader :cards + attr_reader :text_hint def initialize(width: 825, height: 1125, cards: 1, &block) @width=width; @height=height @cards = [] - cards.times{ @cards << Squib::Card.new(width, height) } + cards.times{ @cards << Squib::Card.new(self, width, height) } if block_given? instance_eval(&block) end @@ -24,26 +27,6 @@ module Squib @cards.each { |card| block.call(card) } end - def rangeify (range) - range = 0..(@cards.size-1) if range == :all - range = range..range if range.is_a? Integer - if range.max > (@cards.size-1) - raise "#{range} is outside of deck range of 0..#{@card.size-1}" - end - return range - end - - def fileify(file) - raise 'File #{file} does not exist!' unless File.exists? file - file - end - - def colorify(color) - color ||= :black - color = Cairo::Color.parse(color) - color - end - ################## ### PUBLIC API ### ################## @@ -51,6 +34,7 @@ module Squib require 'squib/api/data' require 'squib/api/image' require 'squib/api/save' + require 'squib/api/settings' require 'squib/api/shapes' require 'squib/api/text' diff --git a/lib/squib/graphics/shapes.rb b/lib/squib/graphics/shapes.rb index d946f84..2631ef8 100644 --- a/lib/squib/graphics/shapes.rb +++ b/lib/squib/graphics/shapes.rb @@ -1,9 +1,9 @@ module Squib class Card - def draw_rectangle(x, y, width, height, x_radius, y_radius) + def draw_rectangle(x, y, width, height, x_radius, y_radius, color) cc = cairo_context - cc.set_source_rgb(0.0,0.0,0.0) + cc.set_source_color(color) cc.rounded_rectangle(x, y, width, height, x_radius, y_radius) cc.stroke end diff --git a/lib/squib/graphics/text.rb b/lib/squib/graphics/text.rb index 48091cc..4873329 100644 --- a/lib/squib/graphics/text.rb +++ b/lib/squib/graphics/text.rb @@ -3,25 +3,84 @@ require 'pango' module Squib class Card + def draw_text_hint(x,y,layout, color) + return if color.nil? && @deck.text_hint.nil? + color ||= @deck.text_hint + w = layout.width / Pango::SCALE + w = layout.extents[1].width / Pango::SCALE if w < 0 #i.e. was never set + h = layout.height / Pango::SCALE + h = layout.extents[1].height / Pango::SCALE if h < 0 #i.e. was never set + draw_rectangle(x,y,w,h,0,0,color) + end + + def ellipsize(layout, options) + unless options[:ellipsize].nil? + h = { :none => Pango::Layout::ELLIPSIZE_NONE, + :start => Pango::Layout::ELLIPSIZE_START, + :middle => Pango::Layout::ELLIPSIZE_MIDDLE, + :end => Pango::Layout::ELLIPSIZE_END, + true => Pango::Layout::ELLIPSIZE_END, + false => Pango::Layout::ELLIPSIZE_NONE + } + layout.ellipsize = h[options[:ellipsize]] + end + layout + end + + def wrap(layout, options) + unless options[:wrap].nil? + h = { :word => Pango::Layout::WRAP_WORD, + :char => Pango::Layout::WRAP_CHAR, + :word_char => Pango::Layout::WRAP_WORD_CHAR, + true => Pango::Layout::WRAP_WORD_CHAR, + } + layout.wrap = h[options[:wrap]] + end + layout + end + + def align(layout, options) + unless options[:align].nil? + h = { :left => Pango::ALIGN_LEFT, + :right => Pango::ALIGN_RIGHT, + :center => Pango::ALIGN_CENTER + } + layout.alignment = h[options[:align]] + end + layout + end + + def setwh(layout, options) + layout.width = options[:width] * Pango::SCALE unless options[:width].nil? + layout.height = options[:height] * Pango::SCALE unless options[:height].nil? + layout + end + + def fitxy(layout, x,y, options) + w = options[:width] ; h = options[:height] + w ||= (@width - 2*x); h ||= (@height - 2*y) # default centers to x,y + w *= Pango::SCALE ; h *= Pango::SCALE + layout.width=w ; layout.height=h + layout + end + def text(str, font, x, y, color, options) cc = cairo_context cc.set_source_color(color) cc.move_to(x,y) layout = cc.create_pango_layout layout.text = str.to_s - w = options[:width] ; h = options[:height] - w ||= (@width - 2*x); h ||= (@height - 2*y) # default centers to x,y - w *= Pango::SCALE ; h *= Pango::SCALE - layout.width=w ; layout.height=h - layout.wrap = Pango::WRAP_WORD - layout.justify = true - layout.alignment = Pango::ALIGN_LEFT + layout.markup = str.to_s if options[:markup] + layout = setwh(layout, options) unless options[:width].nil? && options[:height].nil? + layout = fitxy(layout, x, y , options) if options[:fitxy] + layout = wrap(layout, options) + layout = ellipsize(layout, options) + layout = align(layout, options) + layout.justify = options[:justify] unless options[:justify].nil? layout.font_description = Pango::FontDescription.new(font) - #Center it vertically? - #puts "Height: #{layout.extents[1].height / Pango::SCALE}" - #puts "Height: #{layout.pixel_size[1]*layout.line_count}" cc.update_pango_layout(layout) cc.show_pango_layout(layout) + draw_text_hint(x,y,layout,options[:hint]) end end diff --git a/lib/squib/input_helpers.rb b/lib/squib/input_helpers.rb new file mode 100644 index 0000000..f730317 --- /dev/null +++ b/lib/squib/input_helpers.rb @@ -0,0 +1,38 @@ +module Squib + module InputHelpers + + def rangeify (range) + range = 0..(@cards.size-1) if range == :all + range = range..range if range.is_a? Integer + if range.max > (@cards.size-1) + raise "#{range} is outside of deck range of 0..#{@card.size-1}" + end + return range + end + module_function :rangeify + + def fileify(file) + raise 'File #{file} does not exist!' unless File.exists? file + file + end + module_function :fileify + + def colorify(color, nillable: false) + if nillable # for optional color arguments like text hints + color = Cairo::Color.parse(color) unless color.nil? + else + color ||= :black + color = Cairo::Color.parse(color) + end + color + end + module_function :colorify + + def fontify (font) + font = 'Arial 36' if font==:use_set + font + end + module_function :fontify + + end +end \ No newline at end of file diff --git a/samples/text.rb b/samples/text.rb new file mode 100644 index 0000000..1be53b4 --- /dev/null +++ b/samples/text.rb @@ -0,0 +1,51 @@ +#!/usr/bin/env ruby +require 'squib' + +data = {'name' => ['Thief', 'Grifter', 'Mastermind'], + 'level' => [1,2,3]} +longtext = "This is left-justified text centered on the card based on x and y.\nWhat do you know about tweetle beetles? well... \nWhen 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. AND... When beetles fight these battles in a bottle with their paddles and the bottle's on a poodle and the poodle's eating noodles... ...they call this a muddle puddle tweetle poodle beetle noodle bottle paddle battle." + +Squib::Deck.new(width: 825, height: 1125, cards: 128) 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 + + text str: data['name'], x: 250, y: 55, font: 'Arial 54' + text str: data['level'], x: 65, y: 40, font: 'Arial 72', color: :burnt_orange + + text str: "This text has a hint, fixed width, and fixed height", + hint: :red, + x: 65, y: 400, + width: 300, height: 200, + font: 'Arial 24' + + text str: "Ellipsization!\nThe ultimate question of life, the universe, and everything to life and everything is 42", + hint: :green, font: 'Arial 22', + x: 450, y: 400, + width: 280, height: 180, + ellipsize: true + + hint text: :cyan + text str: "Text hints are also globally togglable!", + x: 65, y: 625, + font: 'Arial 22' + hint text: nil + text str: "See? No hint here.", + x: 565, y: 625, + font: 'Arial 22' + + text str: longtext, font: 'Arial 16', + x: 65, y: 700, + fitxy: true, justify: true + + text str: "Markup is also quite easy awesome", + markup: true, + x: 50, y: 1000, + font: 'Arial 32' + + save prefix: 'text_', format: :png +end + +puts "Done!" + +