Skip to content

Commit

Permalink
Merge pull request #22 from javan/sbix
Browse files Browse the repository at this point in the history
Parse bitmap data from sbix tables
  • Loading branch information
practicingruby committed Sep 20, 2014
2 parents 96a19f3 + a55ba91 commit 12926d3
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 1 deletion.
7 changes: 6 additions & 1 deletion lib/ttfunk.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,11 @@ def glyph_locations
def glyph_outlines
@glyph_outlines ||= TTFunk::Table::Glyf.new(self)
end
end

def sbix
@sbix ||= TTFunk::Table::Sbix.new(self)
end
end
end

require_relative "ttfunk/table/cmap"
Expand All @@ -120,3 +124,4 @@ def glyph_outlines
require_relative "ttfunk/table/name"
require_relative "ttfunk/table/os2"
require_relative "ttfunk/table/post"
require_relative "ttfunk/table/sbix"
54 changes: 54 additions & 0 deletions lib/ttfunk/table/sbix.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require_relative '../table'

module TTFunk
class Table
class Sbix < Table
attr_reader :version
attr_reader :flags
attr_reader :num_strikes
attr_reader :strikes

BitmapData = Struct.new(:x, :y, :type, :data, :ppem, :resolution)

def bitmap_data_for(glyph_id, strike_index)
strike = strikes[strike_index]
return if strike.nil?

glyph_offset = strike[:glyph_data_offset][glyph_id]
next_glyph_offset = strike[:glyph_data_offset][glyph_id + 1]

if glyph_offset && next_glyph_offset
bytes = next_glyph_offset - glyph_offset
if bytes > 0
parse_from(offset + strike[:offset] + glyph_offset) do
x, y, type = read(8, "s2A4")
data = StringIO.new(io.read(bytes - 8))
BitmapData.new(x, y, type, data, strike[:ppem], strike[:resolution])
end
end
end
end

def all_bitmap_data_for(glyph_id)
strikes.each_index.map do |strike_index|
bitmap_data_for(glyph_id, strike_index)
end.compact
end

private

def parse!
@version, @flags, @num_strikes = read(8, "n2N")
strike_offsets = num_strikes.times.map { read(4, "N").first }

@strikes = strike_offsets.map do |strike_offset|
parse_from(offset + strike_offset) do
ppem, resolution = read(4, "n2")
data_offsets = (file.maximum_profile.num_glyphs + 1).times.map { read(4, "N").first }
{ ppem: ppem, resolution: resolution, offset: strike_offset, glyph_data_offset: data_offsets }
end
end
end
end
end
end
Binary file added spec/fonts/ColorTestSbix.ttf
Binary file not shown.
30 changes: 30 additions & 0 deletions spec/integration/file_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,33 @@
it "should extract the correct value"
end
end

describe TTFunk::File, "#sbix" do

context "with ColorTestSbix" do
# Thank you http://typophile.com/node/103268 for ColorTestSbix.ttf
let!(:file) { TTFunk::File.open(test_font("ColorTestSbix"))}

it "should should extract headers" do
expect(file.sbix.version).to eq(1)
expect(file.sbix.flags).to eq(1)
expect(file.sbix.num_strikes).to eq(1)
end

it "should extract bitmap data given a glyph id and strike index" do
bitmap = file.sbix.bitmap_data_for(4, 0)
expect(bitmap.x).to eq(0)
expect(bitmap.y).to eq(0)
expect(bitmap.type).to eq("png")
expect(bitmap.data.read).to match(/IHDR.*ImageReady.*IEND/m)
expect(bitmap.ppem).to eq(150)
expect(bitmap.resolution).to eq(72)
end

it "should extract an array of all bitmap data given a glyph id" do
all_bitmaps = file.sbix.all_bitmap_data_for(4)
expect(all_bitmaps.size).to eq(1)
expect(all_bitmaps[0].ppem).to eq(150)
end
end
end

0 comments on commit 12926d3

Please sign in to comment.