ruby-bitmap-fonts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,83 @@
1
+ STARTFONT 2.1
2
+ COMMENT ter-u20b
3
+ FONT -xos4-Terminus-Bold-R-Normal--20-200-72-72-C-100-ISO10646-1
4
+ SIZE 20 72 72
5
+ FONTBOUNDINGBOX 10 20 0 -4
6
+ STARTPROPERTIES 20
7
+ FAMILY_NAME "Terminus"
8
+ FOUNDRY "xos4"
9
+ SETWIDTH_NAME "Normal"
10
+ ADD_STYLE_NAME ""
11
+ COPYRIGHT "Copyright (C) 2015 Dimitar Toshkov Zhekov - Modified for testing purposes by Markus Fenske"
12
+ NOTICE "Licensed under the SIL Open Font License, Version 1.1"
13
+ WEIGHT_NAME "Bold"
14
+ SLANT "R"
15
+ PIXEL_SIZE 20
16
+ POINT_SIZE 200
17
+ RESOLUTION_X 72
18
+ RESOLUTION_Y 72
19
+ SPACING "C"
20
+ AVERAGE_WIDTH 100
21
+ CHARSET_REGISTRY "ISO10646"
22
+ CHARSET_ENCODING "1"
23
+ MIN_SPACE 10
24
+ FONT_ASCENT 16
25
+ FONT_DESCENT 4
26
+ DEFAULT_CHAR 65533
27
+ ENDPROPERTIES
28
+ CHARS 2
29
+ STARTCHAR exclam
30
+ ENCODING 33
31
+ SWIDTH 500 0
32
+ DWIDTH 10 0
33
+ BBX 10 20 0 -4
34
+ BITMAP
35
+ 0000
36
+ 0000
37
+ 0000
38
+ 0C00
39
+ 0C00
40
+ 0C00
41
+ 0C00
42
+ 0C00
43
+ 0C00
44
+ 0C00
45
+ 0C00
46
+ 0C00
47
+ 0000
48
+ 0000
49
+ 0C00
50
+ 0C00
51
+ 0000
52
+ 0000
53
+ 0000
54
+ 0000
55
+ ENDCHAR
56
+ STARTCHAR X
57
+ ENCODING 88
58
+ SWIDTH 500 0
59
+ DWIDTH 10 0
60
+ BBX 10 20 0 -4
61
+ BITMAP
62
+ 0000
63
+ 0000
64
+ 0000
65
+ 6180
66
+ 6180
67
+ 6180
68
+ 3300
69
+ 3300
70
+ 1E00
71
+ 0C00
72
+ 1E00
73
+ 3300
74
+ 3300
75
+ 6180
76
+ 6180
77
+ 6180
78
+ 0000
79
+ 0000
80
+ 0000
81
+ 0000
82
+ ENDCHAR
83
+ ENDFONT
data/lib/bdf.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "bdf/font"
2
+ require "bdf/char"
3
+ require "bdf/renderer"
4
+ require "bdf/canvas"
5
+ require "bdf/version"
data/lib/bdf/canvas.rb ADDED
@@ -0,0 +1,44 @@
1
+ module BDF
2
+ class Canvas
3
+ def initialize(width, height)
4
+ @width = width
5
+ @height = height
6
+ @array = Array.new(height){Array.new(width, 0)}
7
+ end
8
+
9
+ def set(x, y)
10
+ unless x < @width && y < @height
11
+ # TODO: Maybe resize to other size to improve speed.
12
+ resize(x+1, y+1)
13
+ end
14
+
15
+ @array[y][x] = 1
16
+ end
17
+
18
+ def resize(width, height)
19
+ @array.map! do |line|
20
+ if width > line.size
21
+ line + [0]*(width - line.size)
22
+ else
23
+ line
24
+ end
25
+ end
26
+
27
+ @width = width
28
+
29
+ if height > @array.size
30
+ # This is a loop, because the multiplication op on arrays does not work
31
+ # with non-scalars. You have been warned.
32
+ (height - @array.size).times do
33
+ @array += [[0]*@width]
34
+ end
35
+ end
36
+
37
+ @height = height
38
+ end
39
+
40
+ def to_a
41
+ @array.dup
42
+ end
43
+ end
44
+ end
data/lib/bdf/char.rb ADDED
@@ -0,0 +1,51 @@
1
+ module BDF
2
+ class Char
3
+ def initialize(opts = {})
4
+ @encoding = opts[:encoding]
5
+ @swidth = opts[:swidth]
6
+ @dwidth = opts[:dwidth]
7
+ @bbx = opts[:bbx]
8
+ @bitmap = parse(opts[:bitmap])
9
+ end
10
+
11
+ def render(canvas, cursor)
12
+ @bitmap.each_with_index do |line, y|
13
+ line.each_with_index do |val, x|
14
+ if val == 1
15
+ canvas.set(x+cursor[0]+@bbx[:off_x], y+cursor[1]+@bbx[:off_y])
16
+ end
17
+ end
18
+ end
19
+
20
+ [cursor[0]+@dwidth[:x], cursor[1]+@dwidth[:y]]
21
+ end
22
+
23
+ private
24
+ def parse(bitmap)
25
+ lookup = {
26
+ "0" => [0, 0, 0, 0],
27
+ "1" => [0, 0, 0, 1],
28
+ "2" => [0, 0, 1, 0],
29
+ "3" => [0, 0, 1, 1],
30
+ "4" => [0, 1, 0, 0],
31
+ "5" => [0, 1, 0, 1],
32
+ "6" => [0, 1, 1, 0],
33
+ "7" => [0, 1, 1, 1],
34
+ "8" => [1, 0, 0, 0],
35
+ "9" => [1, 0, 0, 1],
36
+ "A" => [1, 0, 1, 0],
37
+ "B" => [1, 0, 1, 1],
38
+ "C" => [1, 1, 0, 0],
39
+ "D" => [1, 1, 0, 1],
40
+ "E" => [1, 1, 1, 0],
41
+ "F" => [1, 1, 1, 1]
42
+ }
43
+
44
+ bitmap = bitmap.each.map do |line|
45
+ line.chars.map do |char|
46
+ lookup.fetch(char)
47
+ end.flatten[0...@bbx[:w]] # Shorten to bounding box width
48
+ end[0...@bbx[:h]] # Shorten to bounding box height
49
+ end
50
+ end
51
+ end
data/lib/bdf/font.rb ADDED
@@ -0,0 +1,141 @@
1
+ module BDF
2
+ class Font
3
+ class ParseError < Exception; end
4
+
5
+ def self.from_file(filename)
6
+ self.new(filename)
7
+ end
8
+
9
+ def initialize(filename)
10
+ @file = File.open(filename)
11
+ parse
12
+ end
13
+
14
+ def char(name)
15
+ Char.new(@chars[name])
16
+ end
17
+
18
+ def glyph(char)
19
+ # TODO: We could use a glyph list here to get the name from unicode point
20
+ name, _ = @chars.find do |name, char_|
21
+ char_[:encoding] == char.ord
22
+ end
23
+ char(name)
24
+ end
25
+
26
+ attr_reader :version, :name, :size, :x_resolution, :y_resolution,
27
+ :bounding_box_x, :bounding_box_y, :displacement_x, :displacement_y,
28
+ :properties
29
+
30
+ private
31
+ # Specification:
32
+ # https://www.adobe.com/content/dam/Adobe/en/devnet/font/pdfs/5005.BDF_Spec.pdf
33
+ def parse
34
+ @state = :start
35
+
36
+ @file.each_line.each_with_index do |line, line_no|
37
+ case @state
38
+ when :start
39
+ case line
40
+ when /^STARTFONT (.*)$/
41
+ @version = $1
42
+ @state = :body
43
+ else
44
+ raise ParseError, "Expected 'STARTFONT' command"
45
+ end
46
+ when :body
47
+ case line
48
+ when /^COMMENT /
49
+ # Ignore
50
+ when /^FONT (.*)$/
51
+ @name = $1
52
+ when /^SIZE (\d+) (\d+) (\d+)$/
53
+ @size = $1.to_i
54
+ @x_resolution = $2.to_i
55
+ @y_resolution = $3.to_i
56
+ when /^FONTBOUNDINGBOX (-?\d+) (-?\d+) (-?\d+) (-?\d+)$/
57
+ @bounding_box_x = $1.to_i
58
+ @bounding_box_y = $2.to_i
59
+ @displacement_x = $3.to_i
60
+ @displacement_y = $4.to_i
61
+ when /^STARTPROPERTIES (\d+)$/
62
+ @state = :properties
63
+ @properties_count = $1.to_i
64
+ when /^CHARS (\d+)$/
65
+ @chars_count = $1.to_i
66
+ when /^STARTCHAR (.+)$/
67
+ @current_glyph_name = $1
68
+ @state = :char
69
+ when /^ENDFONT$/
70
+ if @chars.size != @chars_count
71
+ raise ParseError, "Expected #{@chars_count} chars, but got #{@chars.size}"
72
+ end
73
+ @state = :end
74
+ else
75
+ raise ParseError, "Unknown error in line #{line_no+1}: #{line}"
76
+ end
77
+ when :properties
78
+ case line
79
+ when /^ENDPROPERTIES$/
80
+ @state = :body
81
+ # They lied :(
82
+ if @properties.size != @properties_count
83
+ raise ParseError, "Expected #{@properties_count} properties, but got #{@properties.size}"
84
+ end
85
+ else
86
+ @properties ||= {}
87
+ key, value = line.split(" ", 2)
88
+ @properties[key] = parse_value(value)
89
+ end
90
+ when :char
91
+ @chars ||= {}
92
+ @chars[@current_glyph_name] ||= {}
93
+
94
+ case line
95
+ when /^ENCODING (\d+)$/
96
+ @chars[@current_glyph_name][:encoding] = $1.to_i
97
+ when /^SWIDTH (\d+) (\d+)$/
98
+ @chars[@current_glyph_name][:swidth] = {:x => $1.to_i, :y => $2.to_i}
99
+ when /^DWIDTH (\d+) (\d+)$/
100
+ @chars[@current_glyph_name][:dwidth] = {:x => $1.to_i, :y => $2.to_i}
101
+ when /^BBX (-?\d+) (-?\d+) (-?\d+) (-?\d+)$/
102
+ @chars[@current_glyph_name][:bbx] = {:w => $1.to_i, :h => $2.to_i, :off_x => $3.to_i, :off_y => $4.to_i}
103
+ when /^BITMAP$/
104
+ @state = :bitmap
105
+ else
106
+ raise ParseError, "Unknown error in line #{line_no+1}: #{line}"
107
+ end
108
+ when :bitmap
109
+ case line
110
+ when /^([A-F0-9]+)$/
111
+ @chars[@current_glyph_name][:bitmap] ||= []
112
+ @chars[@current_glyph_name][:bitmap] << $1
113
+ when /^ENDCHAR$/
114
+ @chars[@current_glyph_name][:bitmap] = parse_bitmap(@chars[@current_glyph_name][:bitmap])
115
+ @state = :body
116
+ else
117
+ raise ParseError, "Expected bitmap or ENDCHAR line #{line_no+1}: #{line}"
118
+ end
119
+ end
120
+ end
121
+
122
+ if @state != :end
123
+ raise ParseError, "Premature EOF"
124
+ end
125
+ end
126
+
127
+ def parse_bitmap(bitmap)
128
+ # FIXME
129
+ bitmap
130
+ end
131
+
132
+ def parse_value(value)
133
+ # That's not correct parsing, but it will work for most things.
134
+ if value[0] == "\""
135
+ value[1...-2].gsub('""','"')
136
+ else
137
+ value.to_i
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,22 @@
1
+ module BDF
2
+ class Renderer
3
+ def self.render(text, opts = {})
4
+ font = opts[:font]
5
+
6
+ # Get baseline for initial cursor
7
+ cursor = [0, -font.displacement_y]
8
+
9
+ # Initial size of one char. resizes automatically
10
+ canvas = Canvas.new(font.bounding_box_x, font.bounding_box_y)
11
+
12
+ text.chars.each do |char|
13
+ # Lookup glyph
14
+ glyph = font.glyph(char)
15
+
16
+ cursor = glyph.render(canvas, cursor)
17
+ end
18
+
19
+ canvas
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module BDF
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bdf.rb'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ruby-bitmap-fonts"
8
+ spec.version = BDF::VERSION
9
+ spec.authors = ["Markus Fenske"]
10
+ spec.email = ["iblue@gmx.net"]
11
+
12
+ spec.summary = %q{A BDF (Glyph Bitmap Distribution Format) renderer}
13
+ spec.description = %q{This gem allows you to render bitmap fonts in the BDF format}
14
+ spec.homepage = "https://github.com/iblue/ruby-bitmap-fonts"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.14"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "byebug"
27
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-bitmap-fonts
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Markus Fenske
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-02-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.14'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.14'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: This gem allows you to render bitmap fonts in the BDF format
70
+ email:
71
+ - iblue@gmx.net
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - README.md
81
+ - Rakefile
82
+ - bin/console
83
+ - bin/setup
84
+ - fixtures/ter-u12b.bdf
85
+ - fixtures/ter-u20b.bdf
86
+ - lib/bdf.rb
87
+ - lib/bdf/canvas.rb
88
+ - lib/bdf/char.rb
89
+ - lib/bdf/font.rb
90
+ - lib/bdf/renderer.rb
91
+ - lib/bdf/version.rb
92
+ - ruby-bitmap-fonts.gemspec
93
+ homepage: https://github.com/iblue/ruby-bitmap-fonts
94
+ licenses: []
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.6.10
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: A BDF (Glyph Bitmap Distribution Format) renderer
116
+ test_files: []