cheapredwine 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +61 -0
- data/Rakefile +1 -0
- data/cheapredwine.gemspec +23 -0
- data/lib/cheapredwine/image/params.rb +16 -0
- data/lib/cheapredwine/image/writer.rb +44 -0
- data/lib/cheapredwine/image.rb +2 -0
- data/lib/cheapredwine/ttx/extractor.rb +23 -0
- data/lib/cheapredwine/ttx/parser.rb +37 -0
- data/lib/cheapredwine/ttx.rb +27 -0
- data/lib/cheapredwine/version.rb +3 -0
- data/lib/cheapredwine.rb +51 -0
- data/spec/cheapredwine_spec.rb +23 -0
- data/spec/fixtures/extractor/hobo.otf +0 -0
- data/spec/fixtures/hobo.otf +0 -0
- data/spec/fixtures/hobo.ttx +8195 -0
- data/spec/fixtures/lato-regular.ttf +0 -0
- data/spec/fixtures/parser/features.ttx +129 -0
- data/spec/fixtures/parser/hobo.ttx +8195 -0
- data/spec/fixtures/parser/lato-regular.ttx +43112 -0
- data/spec/fixtures/test.png +0 -0
- data/spec/fixtures/ttx/hobo.otf +0 -0
- data/spec/fixtures/ttx/hobo.ttx +8195 -0
- data/spec/image/params_spec.rb +24 -0
- data/spec/image/writer_spec.rb +22 -0
- data/spec/ttx/extrator_spec.rb +22 -0
- data/spec/ttx/parser_spec.rb +17 -0
- data/spec/ttx_spec.rb +23 -0
- metadata +129 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Hugo Bastien
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
# CheapRedWine
|
2
|
+
|
3
|
+
[![Code Climate](https://codeclimate.com/github/hugobast/cheapredwine.png)](https://codeclimate.com/github/hugobast/cheapredwine)
|
4
|
+
|
5
|
+
|
6
|
+
|
7
|
+
I needed a way to test fonts on the web. I based this library on myfonts.com. CheapRedWine makes use to Harfbuzz' hb-view utility to generate images from fonts with a slew of different parameters. It also uses fontTools' ttx utility for font introspection.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Make sure the dependencies are satisfied
|
12
|
+
|
13
|
+
$ gem install cheapredwine
|
14
|
+
|
15
|
+
## Dependencies
|
16
|
+
|
17
|
+
It assumes the following is installed and in the case where it applies, accessible from the $PATH env variable.
|
18
|
+
|
19
|
+
* [cairo](http://www.cairographics.org/releases/)
|
20
|
+
* [harfbuzz](http://www.freedesktop.org/software/harfbuzz/release/)
|
21
|
+
* [ttx](git@github.com:mcolyer/fonttools.git)
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
#### Getting a font object from a simple ttf or otf file:
|
26
|
+
|
27
|
+
font = CheapRedWine.font(font_file)
|
28
|
+
font.name # => "Font Name"
|
29
|
+
font.features # => ["liga", "onum", "dlig", … "salt"]
|
30
|
+
|
31
|
+
#### Generating images with text for the font:
|
32
|
+
|
33
|
+
image = CheapRedWine.image(font, "some text", options)
|
34
|
+
|
35
|
+
`image` is an IO object that can then be use to write to disk
|
36
|
+
|
37
|
+
|
38
|
+
##### Options
|
39
|
+
|
40
|
+
options = {
|
41
|
+
margin: 5, # margin around the text
|
42
|
+
size: 40, # size of the text eq to px
|
43
|
+
color: red, # the text color
|
44
|
+
features: [liga, salt] # list of otf features to be applied
|
45
|
+
}
|
46
|
+
|
47
|
+
##### Configuration
|
48
|
+
|
49
|
+
CheapRedWine needs to know where to put ttx files
|
50
|
+
|
51
|
+
CheapRedWine::TTX.configure do |config|
|
52
|
+
config.output_folder = '/path/to/folder'
|
53
|
+
end
|
54
|
+
|
55
|
+
## Contributing
|
56
|
+
|
57
|
+
1. Fork it
|
58
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
59
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
60
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
61
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cheapredwine/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "cheapredwine"
|
8
|
+
gem.version = CheapRedWine::VERSION
|
9
|
+
gem.authors = ["Hugo Bastien"]
|
10
|
+
gem.email = ["hugo@hbastien.com"]
|
11
|
+
gem.description = %q{I needed a way to test fonts on the web. I based this library on myfonts.com. CheapRedWine makes use to Harfbuzz' hb-view utility to generate images from fonts with a slew of different parameters. It also uses fontTools' ttx utility for font introspection.}
|
12
|
+
gem.summary = %q{I needed a way to test fonts on the web. I based this library on myfonts.com. CheapRedWine makes use to Harfbuzz' hb-view utility to generate images from fonts with a slew of different parameters. It also uses fontTools' ttx utility for font introspection.}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_development_dependency 'rspec'
|
21
|
+
|
22
|
+
gem.add_dependency 'nokogiri'
|
23
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module CheapRedWine
|
2
|
+
module Image
|
3
|
+
class Params
|
4
|
+
attr_reader :font, :color, :text, :features, :size, :margin
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
@font = options.fetch(:font)
|
8
|
+
@color = options.fetch(:color) { 'black' }
|
9
|
+
@text = options.fetch(:text) { '' }
|
10
|
+
@features = options.fetch(:features) { [] }
|
11
|
+
@size = options.fetch(:size) { 20 }
|
12
|
+
@margin = options.fetch(:margin) { 5 }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module CheapRedWine
|
2
|
+
module Image
|
3
|
+
class Writer
|
4
|
+
def initialize(image, utility = 'hb-view')
|
5
|
+
@utility = utility
|
6
|
+
@image = image
|
7
|
+
end
|
8
|
+
|
9
|
+
def args
|
10
|
+
[font_file, text, margin, foreground, features, size]
|
11
|
+
end
|
12
|
+
|
13
|
+
def exec
|
14
|
+
IO.popen(args.unshift(@utility))
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def font_file
|
20
|
+
"--font-file=#{@image.font.path}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def text
|
24
|
+
"--text=#{@image.text}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def size
|
28
|
+
"--font-size=#{@image.size}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def foreground
|
32
|
+
"--foreground=#{@image.color}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def margin
|
36
|
+
"--margin=#{@image.margin}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def features
|
40
|
+
"--features=#{@image.features.join(",")}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module CheapRedWine
|
2
|
+
module TTX
|
3
|
+
class Extractor
|
4
|
+
def initialize(font_file, folder)
|
5
|
+
path = File.join(folder, filename(font_file))
|
6
|
+
unless File.exists?("#{path}.ttx")
|
7
|
+
IO.popen(['ttx', "-d#{folder}", "#{font_file.path}"]).read
|
8
|
+
end
|
9
|
+
@file = File.new("#{path}.ttx")
|
10
|
+
end
|
11
|
+
|
12
|
+
def ttx_file
|
13
|
+
@file
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def filename(file)
|
19
|
+
File.basename(file, File.extname(file))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module CheapRedWine
|
4
|
+
class NokogiriParser
|
5
|
+
@@parser = Nokogiri::XML::Document
|
6
|
+
|
7
|
+
def self.parse(file)
|
8
|
+
@@parser.parse(file)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module TTX
|
13
|
+
class Parser
|
14
|
+
def initialize(file, xml_parser = NokogiriParser)
|
15
|
+
@document = xml_parser.parse(file)
|
16
|
+
end
|
17
|
+
|
18
|
+
def features
|
19
|
+
@document.css('FeatureTag').map do |feature|
|
20
|
+
feature.attr('value')
|
21
|
+
end.uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
def font_name
|
25
|
+
namerecord(4).first.text.strip
|
26
|
+
end
|
27
|
+
|
28
|
+
def family_name
|
29
|
+
namerecord(1).first.text.strip
|
30
|
+
end
|
31
|
+
|
32
|
+
def namerecord(id)
|
33
|
+
@document.xpath("//namerecord[@nameID=#{id}]")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'cheapredwine/ttx/parser'
|
2
|
+
require 'cheapredwine/ttx/extractor'
|
3
|
+
|
4
|
+
module CheapRedWine
|
5
|
+
module TTX
|
6
|
+
class Configuration
|
7
|
+
attr_accessor :output_folder
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@output_folder = 'ttx'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.configuration
|
15
|
+
@configuration ||= Configuration.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.configure
|
19
|
+
yield(configuration) if block_given?
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.for_font(font)
|
23
|
+
extractor = Extractor.new(font, configuration.output_folder)
|
24
|
+
parser = Parser.new(extractor.ttx_file)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/cheapredwine.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "cheapredwine/version"
|
2
|
+
require "cheapredwine/ttx"
|
3
|
+
require "cheapredwine/image"
|
4
|
+
|
5
|
+
CheapRedWine::TTX.configure do |config|
|
6
|
+
config.output_folder = 'spec/fixtures'
|
7
|
+
end
|
8
|
+
|
9
|
+
module CheapRedWine
|
10
|
+
class Font
|
11
|
+
attr_accessor :name, :family, :features, :path
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
yield(self) if block_given?
|
15
|
+
end
|
16
|
+
|
17
|
+
def file
|
18
|
+
File.new(path)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.font(file)
|
23
|
+
parser = TTX.for_font(file)
|
24
|
+
Font.new do |font|
|
25
|
+
font.name = parser.font_name
|
26
|
+
font.family = parser.family_name
|
27
|
+
font.features = parser.features
|
28
|
+
font.path = file
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.image(font, text, options = {})
|
33
|
+
features = merge_features(font.features, options.fetch(:features) { [] })
|
34
|
+
options.merge!({
|
35
|
+
features: features,
|
36
|
+
font: font.file,
|
37
|
+
text: text
|
38
|
+
})
|
39
|
+
params = Image::Params.new(options)
|
40
|
+
Image::Writer.new(params).exec
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def self.merge_features(all_features, selected_features)
|
46
|
+
all_features.map do |feature|
|
47
|
+
prefix = selected_features.include?(feature) ? '+' : '-'
|
48
|
+
prefix + feature
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'cheapredwine'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe CheapRedWine do
|
5
|
+
let(:file) { File.new('spec/fixtures/hobo.otf') }
|
6
|
+
let(:font) { CheapRedWine.font(file) }
|
7
|
+
|
8
|
+
it "creates a Font object from a font file" do
|
9
|
+
font.name.should eq "Hobo Std Medium"
|
10
|
+
font.file.path.should match file.path
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can create images from text" do
|
14
|
+
options = { size: 26, features: ['liga', 'frac'] }
|
15
|
+
image = CheapRedWine.image(font, 'ffi 1/2', options)
|
16
|
+
tempfile = Tempfile.new('image')
|
17
|
+
tempfile.write(image.read)
|
18
|
+
tempfile.close
|
19
|
+
mimetype = IO.popen(["file", "--brief", "--mime-type", tempfile.path]).
|
20
|
+
read.chomp
|
21
|
+
mimetype.should eq "image/png"
|
22
|
+
end
|
23
|
+
end
|
Binary file
|
Binary file
|