Navigation Menu

Skip to content

Commit

Permalink
initial version
Browse files Browse the repository at this point in the history
  • Loading branch information
madrobby committed Sep 26, 2009
0 parents commit f0cfb77
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
.DS_Store
15 changes: 15 additions & 0 deletions README
@@ -0,0 +1,15 @@
textorize produces beautifully sub-pixel-antialiased text graphics on OS X. Output format is always PNG.

Usage: ./textorize.rb [options] string
-f, --font=[FONT] Font name
-s, --size=[SIZE] Font size in point
-l, --lineheight=[HEIGHT] Line height in point
-k, --kerning=[STEPS] Tighten or loosen kerning by the given amount
-w, --width=[WIDTH] Wrapping width in pixels
-o, --output=[FILENAME] Specify filename for saving
-b, --obliqueness=[ANGLE] Slant angle
-t, --stencil=[COLOR] Render background with color and stencil text
-r, --reverse Reverse stencil (color on transparent background)
-c, --color=[COLOR] Render text in specific color
--background=[COLOR] Render background in specific color
-h, --help Display this message and exit
16 changes: 16 additions & 0 deletions Rakefile
@@ -0,0 +1,16 @@
require "rubygems"
require "rake/testtask"
require "rake/gempackagetask"

task :default => :test

Rake::TestTask.new do |t|
t.libs << "test"
t.test_files = FileList["test/test_*.rb"]
t.verbose = true
end

Rake::GemPackageTask.new(eval(IO.read(File.join(File.dirname(__FILE__), "textorize.gemspec")))) do |pkg|
pkg.need_zip = true
pkg.need_tar = true
end
70 changes: 70 additions & 0 deletions bin/textorize.rb
@@ -0,0 +1,70 @@
#!/usr/bin/env ruby
require "optparse"
require "../lib/textorize/renderer"
require "../lib/textorize/saver"
require "../lib/textorize/runner"

options = {}
opts = OptionParser.new do |opts|
opts.banner = "Usage: #$0 [options] string"

opts.on('-f', '--font=[FONT]', String, 'Font name') do |v|
options[:font] = v
end

opts.on('-s', '--size=[SIZE]', Float, 'Font size in point') do |v|
options[:size] = v
end

opts.on('-l', '--lineheight=[HEIGHT]', Float, 'Line height in point') do |v|
options[:lineheight] = v
end

opts.on('-k', '--kerning=[STEPS]', Integer, 'Tighten or loosen kerning by the given amount') do |v|
options[:kerning] = v
end

opts.on('-w', '--width=[WIDTH]', Integer, 'Wrapping width in pixels') do |v|
options[:width] = v
end

opts.on('-o', '--output=[FILENAME]', String, 'Specify filename for saving') do |v|
options[:output] = v
end

opts.on('-b', '--obliqueness=[ANGLE]', Float, 'Slant angle') do |v|
options[:obliqueness] = v
end

opts.on('-t', '--stencil=[COLOR]', String, 'Render background with color and stencil text') do |v|
options[:stencil] = v
end

opts.on('-r', '--reverse', 'Reverse stencil (color on transparent background)') do
options[:reverse_stencil] = true
end

opts.on('-c', '--color=[COLOR]', String, 'Render text in specific color') do |v|
options[:color] = v
end

opts.on('-b', '--background=[COLOR]', String, 'Render background in specific color') do |v|
options[:background] = v
end

opts.on_tail('-h', '--help', 'Display this message and exit') do
puts opts
exit
end
end.parse!

options[:font] ||= 'Arial'
options[:size] ||= 28.0
options[:kerning] ||= 0
options[:lineheight] ||= options[:size]
options[:output] ||= 'output.png'
options[:strings] = ARGV.first || 'Hello World'
options[:width] ||= 250
options[:obliqueness] ||= 0

renderer = Textorize::Runner.new(options[:strings], options[:output], options)
5 changes: 5 additions & 0 deletions lib/textorize.rb
@@ -0,0 +1,5 @@
$:.unshift File.dirname(__FILE__)

require "textorize/runner"
require "textorize/renderer"
require "textorize/saver"
58 changes: 58 additions & 0 deletions lib/textorize/renderer.rb
@@ -0,0 +1,58 @@
require 'osx/cocoa'

module Textorize
class Renderer
include OSX

def initialize(window, string, options)
@text_view = NSTextView.alloc.initWithFrame([0,0,1000,100])

set_attribs options
window.setContentView @text_view
@text_view.setString string
@text_view.sizeToFit

window.display
window.orderFrontRegardless
end

def bitmap
@text_view.lockFocus
bitmap = NSBitmapImageRep.alloc.initWithFocusedViewRect(@text_view.bounds)
@text_view.unlockFocus
bitmap
end

private

def set_attribs(options)
@text_view.setHorizontallyResizable(true)
@text_view.useAllLigatures(nil)

color = (options[:color] || '0,0,0').split(',')
fgcolor = NSColor.colorWithDeviceRed_green_blue_alpha(color[0], color[1], color[2], 1)
bgcolor = (options[:background] || '1,1,1').split(',')
@text_view.setBackgroundColor(
NSColor.colorWithDeviceRed_green_blue_alpha(bgcolor[0], bgcolor[1], bgcolor[2], 1)
)
@text_view.setTextColor(fgcolor)

puts @text_view.inspect

para = NSMutableParagraphStyle.alloc.init
para.setLineSpacing(options[:lineheight])

attribs = NSMutableDictionary.alloc.init
attribs.setObject_forKey(NSFont.fontWithName_size(options[:font], options[:size]), NSFontAttributeName)
attribs.setObject_forKey(options[:kerning], NSKernAttributeName)
attribs.setObject_forKey(para, NSParagraphStyleAttributeName)
attribs.setObject_forKey(0, NSBaselineOffsetAttributeName)
attribs.setObject_forKey(options[:obliqueness], NSObliquenessAttributeName)

@text_view.setTypingAttributes(attribs)
@text_view.lowerBaseline(nil)
end

end

end
38 changes: 38 additions & 0 deletions lib/textorize/runner.rb
@@ -0,0 +1,38 @@
require 'osx/cocoa'

module Textorize
class Runner

def initialize(string, output, options)
app = OSX::NSApplication.sharedApplication

delegate = RunnerApplication.alloc.init
delegate.options = options
delegate.string = string
delegate.output = output

app.setDelegate delegate
app.run
end

end

class RunnerApplication < OSX::NSObject
include OSX
attr_accessor :options
attr_accessor :string
attr_accessor :output

def initialize
@window = NSWindow.alloc.initWithContentRect_styleMask_backing_defer([150, 1500, 1000, 500], NSBorderlessWindowMask, 2, 0)
end

def applicationDidFinishLaunching(notification)
renderer = Renderer.new(@window, @string, @options)
Saver.new(renderer).write_to_file(@output)
NSApplication.sharedApplication.terminate(nil)
end

end

end
16 changes: 16 additions & 0 deletions lib/textorize/saver.rb
@@ -0,0 +1,16 @@
module Textorize
class Saver
include OSX
attr_reader :png

def initialize(renderer)
bitmap = renderer.bitmap
@png = bitmap.representationUsingType_properties(NSPNGFileType, nil)
end

def write_to_file(file)
@png.writeToFile_atomically(file, true)
end

end
end
18 changes: 18 additions & 0 deletions test/test_runner.rb
@@ -0,0 +1,18 @@
require File.join(File.dirname(__FILE__), *%w".. lib textorize")
require "test/unit"

class RunnerTest < Test::Unit::TestCase

def test_runner
options = {}
options[:font] ||= 'Arial'
options[:size] ||= 28.0
options[:kerning] ||= 0
options[:lineheight] ||= options[:size]
options[:width] ||= 250
options[:obliqueness] ||= 0

Textorize::Runner.new 'Hallo!', 'output.png', options
end

end
14 changes: 14 additions & 0 deletions textorize.gemspec
@@ -0,0 +1,14 @@
Gem::Specification.new do |s|
s.name = "textorize"
s.version = "0.0.1"
s.date = "2009-05-15"
s.summary = "OS X sub-pixel-antialiased PNG string renderer."
s.email = "thomas@fesch.at"
s.homepage = "http://github.com/madrobby/textorize"
s.description = "Textorize is a OS X utility to render sub-pixel-antialised strings into PNG files."
s.has_rdoc = false
s.authors = ["Thomas Fuchs"]
s.files = Dir["Rakefile", "bin/**/*", "lib/**/*", "test/**/*"]
s.test_files = Dir["test/test_*.rb"] unless $SAFE > 0
s.executables = ["textorize"]
end

0 comments on commit f0cfb77

Please sign in to comment.