dvi 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.
- data/History.txt +4 -0
- data/License.txt +56 -0
- data/Manifest.txt +37 -0
- data/README.txt +10 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +72 -0
- data/config/requirements.rb +17 -0
- data/lib/dvi.rb +99 -0
- data/lib/dvi/lsr.rb +41 -0
- data/lib/dvi/opcode.rb +515 -0
- data/lib/dvi/tfm.rb +68 -0
- data/lib/dvi/tfm/format.rb +290 -0
- data/lib/dvi/util.rb +37 -0
- data/lib/dvi/version.rb +9 -0
- data/log/debug.log +0 -0
- data/misc/latex/latex.dvi +0 -0
- data/misc/latex/latex.tex +4 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/spec/dvi_spec.rb +17 -0
- data/spec/lsr_spec.rb +11 -0
- data/spec/opcode_spec.rb +881 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/tfm_spec.rb +167 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/dvi.rake +16 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- data/website/index.html +119 -0
- data/website/index.txt +55 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +138 -0
- data/website/template.rhtml +48 -0
- metadata +87 -0
data/lib/dvi/tfm.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require "stringio"
|
2
|
+
|
3
|
+
module Dvi
|
4
|
+
class Tfm
|
5
|
+
|
6
|
+
class Char
|
7
|
+
# Returns the width(in design-size units) of the character index number.
|
8
|
+
attr_reader :width, :height, :depth, :italic_correction
|
9
|
+
attr_reader :kerning, :ligature
|
10
|
+
def initialize(width, height, depth, italic_correction, kerning, ligature)
|
11
|
+
@width = width
|
12
|
+
@height = height
|
13
|
+
@depth = depth
|
14
|
+
@italic_correction = italic_correction
|
15
|
+
@kerning = kerning
|
16
|
+
@ligature = ligature
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Ligature
|
21
|
+
attr_reader :a, :b, :c, :index
|
22
|
+
def initialize(a, b, c, index)
|
23
|
+
@a = a
|
24
|
+
@b = b
|
25
|
+
@c = c
|
26
|
+
@index = index
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Kerning
|
31
|
+
attr_reader :next_char, :amount
|
32
|
+
def initialize(next_char, real_amount)
|
33
|
+
@next_char = next_char
|
34
|
+
@amount = real_amount * (2**(-20.0))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Data
|
39
|
+
attr_reader :design_size, :font_coding_scheme, :font_identifier
|
40
|
+
attr_reader :char, :param
|
41
|
+
attr_reader :slant, :space, :strech, :shrink, :xheight, :quad, :extraspace
|
42
|
+
def initialize(design_size, font_coding_scheme, font_identifier, char, param)
|
43
|
+
@design_size = design_size
|
44
|
+
@font_coding_scheme = font_coding_scheme
|
45
|
+
@font_identifier = font_identifier
|
46
|
+
@char = char
|
47
|
+
@param = param
|
48
|
+
@slant = @param[1]
|
49
|
+
@space = @param[2]
|
50
|
+
@stretch = @param[3]
|
51
|
+
@shrink = @param[4]
|
52
|
+
@xheight = @param[5]
|
53
|
+
@quad = @param[6]
|
54
|
+
@extraspace = @param[7]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Read the TFM file.
|
59
|
+
# path:: TFM file path string
|
60
|
+
def self.read(path)
|
61
|
+
raise ArgumentError, path unless path.kind_of?(String) && File.exist?(path)
|
62
|
+
Format.new(File.open(path)).build
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
require "dvi/tfm/format"
|
@@ -0,0 +1,290 @@
|
|
1
|
+
class Dvi::Tfm::Format
|
2
|
+
class Error < StandardError; end
|
3
|
+
class NotImplemented < StandardError; end
|
4
|
+
|
5
|
+
# CharInfo is a class for char_info section.
|
6
|
+
class CharInfo
|
7
|
+
attr_reader :width_index, :height_index, :depth_index, :italic_index
|
8
|
+
attr_reader :tag, :remainder
|
9
|
+
def initialize(width_index, height_index, depth_index, italic_index,
|
10
|
+
tag, remainder)
|
11
|
+
@width_index = width_index
|
12
|
+
@height_index = height_index
|
13
|
+
@depth_index = depth_index
|
14
|
+
@italic_index = italic_index
|
15
|
+
@tag = tag
|
16
|
+
@remainder = remainder
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# LigKern is a class for lig/kern section.
|
21
|
+
class LigKern
|
22
|
+
attr_reader :skip_byte, :next_char, :op_byte, :remainder
|
23
|
+
def initialize(skip_byte, next_char, op_byte, remainder)
|
24
|
+
@skip_byte = skip_byte
|
25
|
+
@next_char = next_char
|
26
|
+
@op_byte = op_byte
|
27
|
+
@remainder = remainder
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# ExtensibleRecipe is a class for extensible recipe section.
|
32
|
+
class ExtensibleRecipe
|
33
|
+
attr_reader :top, :mid, :bot, :rep
|
34
|
+
def initialize(top, mid, bot, rep)
|
35
|
+
@top = top
|
36
|
+
@mid = mid
|
37
|
+
@bot = bot
|
38
|
+
@rep = rep
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :lf, :lh, :bc, :ec, :nw, :nh, :nd, :ni, :nl, :nk, :ne, :np
|
43
|
+
attr_accessor :checksum, :design_size, :font_coding_scheme, :font_identifier
|
44
|
+
attr_accessor :seven_bit_safe_flag, :face
|
45
|
+
attr_reader :charinfo, :lig_kern_table, :kern_table, :extensible_recipe, :param
|
46
|
+
|
47
|
+
def initialize(io)
|
48
|
+
raise ArgumentError unless io.kind_of?(IO)
|
49
|
+
read_tfm_header(io)
|
50
|
+
read_header_data(io)
|
51
|
+
read_char_info_table(io)
|
52
|
+
read_width_table(io)
|
53
|
+
read_height_table(io)
|
54
|
+
read_depth_table(io)
|
55
|
+
read_italic_table(io)
|
56
|
+
read_lig_kern_table(io)
|
57
|
+
read_kern_table(io)
|
58
|
+
read_extensible_recipes(io)
|
59
|
+
read_params(io)
|
60
|
+
end
|
61
|
+
|
62
|
+
def build
|
63
|
+
@chars = Array.new
|
64
|
+
@char_info_table.each_with_index do |char_info, idx|
|
65
|
+
unit = (2**(-20.0))
|
66
|
+
|
67
|
+
# sizes
|
68
|
+
w = @width_table[char_info.width_index] * unit
|
69
|
+
h = @height_table[char_info.height_index] * unit
|
70
|
+
d = @depth_table[char_info.depth_index] * unit
|
71
|
+
i = @italic_table[char_info.italic_index] * unit
|
72
|
+
|
73
|
+
# lig/kern
|
74
|
+
k = Hash.new
|
75
|
+
l = Hash.new
|
76
|
+
|
77
|
+
case char_info.tag
|
78
|
+
when 0
|
79
|
+
# do nothing
|
80
|
+
when 1
|
81
|
+
idx = char_info.remainder
|
82
|
+
next_lig_kern = true
|
83
|
+
|
84
|
+
while next_lig_kern do
|
85
|
+
lk = @lig_kern_table[idx]
|
86
|
+
|
87
|
+
if lk.op_byte >= 128
|
88
|
+
# kerning
|
89
|
+
amount = @kern_table[256*(lk.op_byte-128)+lk.remainder]
|
90
|
+
k[lk.next_char] = Dvi::Tfm::Kerning.new(lk.next_char, amount)
|
91
|
+
else
|
92
|
+
# ligature
|
93
|
+
a, b, c = case lk.op_byte
|
94
|
+
when 0; [0, 0, 0]
|
95
|
+
when 1; [0, 0, 1]
|
96
|
+
when 2; [0, 1, 0]
|
97
|
+
when 3; [0, 1, 1]
|
98
|
+
when 5; [1, 0, 0]
|
99
|
+
when 6; [1, 1, 0]
|
100
|
+
when 7; [1, 1, 1]
|
101
|
+
when 11; [2, 1, 1]
|
102
|
+
else raise Error end
|
103
|
+
l[lk.next_char] = Dvi::Tfm::Ligature.new(a, b, c, lk.remainder)
|
104
|
+
end
|
105
|
+
|
106
|
+
# next?
|
107
|
+
if lk.skip_byte >= 128
|
108
|
+
next_lig_kern = false
|
109
|
+
else
|
110
|
+
idx += (1 + lk.skip_byte)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
when 2
|
114
|
+
raise NotImplemented
|
115
|
+
when 3
|
116
|
+
raise NotImplemented
|
117
|
+
else
|
118
|
+
raise Error
|
119
|
+
end
|
120
|
+
|
121
|
+
@chars << Dvi::Tfm::Char.new(w, h, d, i, k, l)
|
122
|
+
end
|
123
|
+
Dvi::Tfm::Data.new(@design_size,
|
124
|
+
@font_coding_scheme,
|
125
|
+
@font_identifier,
|
126
|
+
@chars,
|
127
|
+
@param)
|
128
|
+
end
|
129
|
+
|
130
|
+
### PRIVATE ###
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def read_tfm_header(io) #:nodoc:
|
135
|
+
# change the position
|
136
|
+
io.seek(0)
|
137
|
+
|
138
|
+
# section positions
|
139
|
+
@lf, @lh, @bc, @ec, @nw, @nh, @nd, @ni, @nl, @nk, @ne, @np =
|
140
|
+
io.read(24).unpack("n12")
|
141
|
+
|
142
|
+
# set positions
|
143
|
+
@pos = Hash.new
|
144
|
+
@pos[:ci] = (6 + @lh) * 4
|
145
|
+
@pos[:nw] = @pos[:ci] + (@ec - @bc + 1) * 4
|
146
|
+
@pos[:nh] = @pos[:nw] + @nw * 4
|
147
|
+
@pos[:nd] = @pos[:nh] + @nh * 4
|
148
|
+
@pos[:ni] = @pos[:nd] + @nd * 4
|
149
|
+
@pos[:nl] = @pos[:ni] + @ni * 4
|
150
|
+
@pos[:nk] = @pos[:nl] + @nl * 4
|
151
|
+
@pos[:ne] = @pos[:nk] + @nk * 4
|
152
|
+
@pos[:np] = @pos[:ne] + @ne * 4
|
153
|
+
|
154
|
+
# validation
|
155
|
+
raise Error unless @bc - 1 <= @ec and @ec <= 255 and ne <= 256
|
156
|
+
lf = 7 + @lh + @ec - @bc + @nw + @nh + @nd + @ni + @nl + @nk + @ne + @np
|
157
|
+
raise Error unless @lf == lf
|
158
|
+
end
|
159
|
+
|
160
|
+
def read_header_data(io) #:nodoc:
|
161
|
+
# change the position
|
162
|
+
io.seek(24)
|
163
|
+
|
164
|
+
# checksum
|
165
|
+
@checksum = io.read(4)
|
166
|
+
|
167
|
+
# design size
|
168
|
+
@real_design_size = io.read(4).unpack("N").first
|
169
|
+
@design_size = @real_design_size * (2**(-20.0))
|
170
|
+
|
171
|
+
# font coding scheme
|
172
|
+
if @lh > 2
|
173
|
+
size = io.read(1).unpack("C").first
|
174
|
+
@font_coding_scheme = io.read(size)
|
175
|
+
end
|
176
|
+
|
177
|
+
# font identifier / font family
|
178
|
+
if @lh > 12
|
179
|
+
io.seek(72)
|
180
|
+
size = io.read(1).unpack("C").first
|
181
|
+
@font_identifier = io.read(size)
|
182
|
+
end
|
183
|
+
|
184
|
+
# other data
|
185
|
+
if @lh > 17
|
186
|
+
io.seek(92)
|
187
|
+
byte = io.read(4).unpack("C4")
|
188
|
+
@seven_bit_safe_flag = byte[0]
|
189
|
+
@face = byte[3]
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def read_char_info_table(io) #:nodoc:
|
194
|
+
# change the position
|
195
|
+
io.seek @pos[:ci]
|
196
|
+
|
197
|
+
@char_info_table = (0..(@ec - @bc)).map do
|
198
|
+
# read 4 bytes
|
199
|
+
byte = io.read(4).unpack("c4")
|
200
|
+
|
201
|
+
CharInfo.new(byte[0], # width index (8 bits)
|
202
|
+
byte[1] >> 4, # height index (4 bits)
|
203
|
+
byte[1] & 0b00001111, # depth index (4 bits)
|
204
|
+
byte[2] >> 2, # italic index (6 bits)
|
205
|
+
byte[2] & 0b00000011, # tag index (2 bits)
|
206
|
+
byte[3]) # remainder (8 bits)
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def read_width_table(io)
|
211
|
+
# change the position
|
212
|
+
io.seek @pos[:nw]
|
213
|
+
|
214
|
+
# collect each word
|
215
|
+
@width_table = (1..@nw).map{ io.read(4).unpack("N").first }
|
216
|
+
|
217
|
+
# validation
|
218
|
+
raise Error unless @width_table[0] == 0
|
219
|
+
end
|
220
|
+
|
221
|
+
def read_height_table(io)
|
222
|
+
# change the position
|
223
|
+
io.seek @pos[:nh]
|
224
|
+
|
225
|
+
# collect each word
|
226
|
+
@height_table = (1..@nh).map{ io.read(4).unpack("N").first }
|
227
|
+
|
228
|
+
# validation
|
229
|
+
raise Error unless @height_table[0] == 0
|
230
|
+
end
|
231
|
+
|
232
|
+
def read_depth_table(io)
|
233
|
+
# change the position
|
234
|
+
io.seek @pos[:nd]
|
235
|
+
|
236
|
+
# collect each word
|
237
|
+
@depth_table = (1..@nd).map{ io.read(4).unpack("N").first }
|
238
|
+
|
239
|
+
# validation
|
240
|
+
raise Error unless @depth_table[0] == 0
|
241
|
+
end
|
242
|
+
|
243
|
+
def read_italic_table(io)
|
244
|
+
# change the position
|
245
|
+
io.seek @pos[:ni]
|
246
|
+
|
247
|
+
# collect each word
|
248
|
+
@italic_table = (1..@ni).map{ io.read(4).unpack("N").first }
|
249
|
+
|
250
|
+
# validation
|
251
|
+
raise Error unless @italic_table[0] == 0
|
252
|
+
end
|
253
|
+
|
254
|
+
def read_lig_kern_table(io)
|
255
|
+
# change the position
|
256
|
+
io.seek @pos[:nl]
|
257
|
+
|
258
|
+
# collect each word
|
259
|
+
@lig_kern_table = (1..@nl).map{ LigKern.new(*io.read(4).unpack("C4")) }
|
260
|
+
end
|
261
|
+
|
262
|
+
def read_kern_table(io)
|
263
|
+
# change the position
|
264
|
+
io.seek @pos[:nk]
|
265
|
+
|
266
|
+
# collect each word
|
267
|
+
@kern_table = (1..@nk).map do
|
268
|
+
# signed long little endian
|
269
|
+
io.read(4).unpack("N").pack("l").unpack("l").first
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
def read_extensible_recipes(io)
|
274
|
+
# change the position
|
275
|
+
io.seek @pos[:ne]
|
276
|
+
|
277
|
+
# collect each word
|
278
|
+
@extensible_recipe = (1..@ne).map do
|
279
|
+
ExtensibleRecipe.new(*io.read(1).unpack("C4"))
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def read_params(io)
|
284
|
+
# change the position
|
285
|
+
io.seek @pos[:np]
|
286
|
+
|
287
|
+
# collect each word
|
288
|
+
@param = (1..@np).map{ io.read(4).unpack("N").first }
|
289
|
+
end
|
290
|
+
end
|
data/lib/dvi/util.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Dvi::Util
|
2
|
+
def read_uint1
|
3
|
+
readchar
|
4
|
+
end
|
5
|
+
|
6
|
+
def read_uint2
|
7
|
+
(readchar << 8) | readchar
|
8
|
+
end
|
9
|
+
|
10
|
+
def read_uint3
|
11
|
+
(readchar << 16) | read_uint2
|
12
|
+
end
|
13
|
+
|
14
|
+
def read_uint4
|
15
|
+
(readchar << 24) | read_uint3
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_int1
|
19
|
+
ui = read_uint1
|
20
|
+
ui & 128 != 0 ? ui - 256 : ui
|
21
|
+
end
|
22
|
+
|
23
|
+
def read_int2
|
24
|
+
ui = read_uint2
|
25
|
+
ui & 32768 != 0 ? ui - 65536 : ui
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_int3
|
29
|
+
ui = read_uint3
|
30
|
+
ui & 8388608 != 0 ? ui - 16777216 : ui
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_int4
|
34
|
+
ui = read_uint4
|
35
|
+
ui & 2147483648 != 0 ? ui - 4294967296 : ui
|
36
|
+
end
|
37
|
+
end
|
data/lib/dvi/version.rb
ADDED
data/log/debug.log
ADDED
File without changes
|
Binary file
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.join(File.dirname(__FILE__), '..')
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.join(File.dirname(__FILE__), '..')
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|