Skip to content

Commit

Permalink
TTC file support (#33)
Browse files Browse the repository at this point in the history
Add support for TTC files
  • Loading branch information
jamis authored and pointlessone committed Feb 13, 2017
1 parent 9267175 commit 6fa049f
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).

## [Unreleased]

### Added

* Support for reading TTF fonts from TTC files

### Changed

* Subset font naming is consistent now and depends on content
Expand Down
9 changes: 7 additions & 2 deletions lib/ttfunk.rb
Expand Up @@ -3,6 +3,7 @@

require_relative 'ttfunk/directory'
require_relative 'ttfunk/resource_file'
require_relative 'ttfunk/collection'

module TTFunk
class File
Expand All @@ -17,6 +18,10 @@ def self.from_dfont(file, which = 0)
new(ResourceFile.open(file) { |dfont| dfont['sfnt', which] })
end

def self.from_ttc(file, which = 0)
Collection.open(file) { |ttc| ttc[which] }
end

def self.verify_and_open(io_or_path)
# File or IO
if io_or_path.respond_to?(:rewind)
Expand All @@ -36,9 +41,9 @@ def self.verify_and_open(io_or_path)
io
end

def initialize(contents)
def initialize(contents, offset = 0)
@contents = StringIO.new(contents)
@directory = Directory.new(@contents)
@directory = Directory.new(@contents, offset)
end

def ascent
Expand Down
41 changes: 41 additions & 0 deletions lib/ttfunk/collection.rb
@@ -0,0 +1,41 @@
require 'ttfunk'

module TTFunk
class Collection
include Enumerable

def self.open(path)
::File.open(path, 'rb') do |io|
yield new(io)
end
end

def initialize(io)
tag = io.read(4)
raise ArgumentError, 'not a TTC file' unless tag == 'ttcf'

_major, _minor = io.read(4).unpack('n*')
count = io.read(4).unpack('N').first
@offsets = io.read(count * 4).unpack('N*')

io.rewind
@contents = io.read
@cache = []
end

def count
@offsets.length
end

def each
count.times do |index|
yield self[index]
end
self
end

def [](index)
@cache[index] ||= TTFunk::File.new(@contents, @offsets[index])
end
end
end
3 changes: 2 additions & 1 deletion lib/ttfunk/directory.rb
Expand Up @@ -3,7 +3,8 @@ class Directory
attr_reader :tables
attr_reader :scaler_type

def initialize(io)
def initialize(io, offset = 0)
io.seek(offset)
@scaler_type, table_count = io.read(12).unpack('Nn')

@tables = {}
Expand Down
Binary file added spec/fonts/DejaVuSans.ttc
Binary file not shown.
28 changes: 28 additions & 0 deletions spec/integration/collection_spec.rb
@@ -0,0 +1,28 @@
# coding: utf-8

require 'spec_helper'

describe TTFunk::Collection, '::open' do
it 'will not open non-TTC files' do
expect { TTFunk::Collection.open test_font('DejaVuSans') }
.to raise_error(ArgumentError)
end

it 'will open TTC files' do
success = false

TTFunk::Collection.open(test_font('DejaVuSans', :ttc)) do |_ttc|
success = true
end

expect(success).to be true
end

it 'will report fonts in TTC' do
TTFunk::Collection.open(test_font('DejaVuSans', :ttc)) do |ttc|
expect(ttc.count).to eq 2
expect(ttc[0].name.font_name.first).to eq 'DejaVu Sans'
expect(ttc[1].name.font_name.first).to eq 'DejaVu Sans Bold'
end
end
end
7 changes: 7 additions & 0 deletions spec/integration/file_spec.rb
Expand Up @@ -13,6 +13,13 @@
end
end

describe TTFunk::File, '::from_ttc' do
it 'returns font at requested index in TTC file' do
font = TTFunk::File.from_ttc(test_font('DejaVuSans', :ttc), 1)
expect(font.name.font_name.first).to eq 'DejaVu Sans Bold'
end
end

describe TTFunk::File, '#ascent' do
context 'with DejaVuSans' do
let!(:file) { TTFunk::File.open(test_font('DejaVuSans')) }
Expand Down
4 changes: 2 additions & 2 deletions spec/support/path_helpers.rb
@@ -1,7 +1,7 @@
module PathHelpers
def test_font(name)
def test_font(name, ext = :ttf)
base_path = File.expand_path(File.dirname(__FILE__) + '/../fonts')
valid_filename = File.join(base_path, "#{name}.ttf")
valid_filename = File.join(base_path, "#{name}.#{ext}")
if File.file?(valid_filename)
return valid_filename
else
Expand Down

0 comments on commit 6fa049f

Please sign in to comment.