ifmapper 1.0.8 → 1.0.9
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/IFMapper.gemspec +1 -1
- data/TODO.txt +0 -2
- data/docs/en/index.html +1 -1
- data/lib/IFMapper/FXMap.rb +35 -23
- data/lib/IFMapper/FXMapperWindow.rb +2 -1
- data/lib/IFMapper/PDFMapExporter_pdfwriter.rb +526 -0
- data/lib/IFMapper/PDFMapExporter_prawn.rb +528 -0
- data/lib/IFMapper/Room.rb +1 -0
- data/lib/IFMapper/TranscriptReader.rb +61 -0
- data/lib/IFMapper/locales/en/Messages.rb +13 -1
- data/lib/IFMapper/locales/es/Messages.rb +13 -2
- data/maps/Bronze.map +0 -0
- data/maps/Bureaucracy.map +0 -0
- data/maps/Byzantine.map +0 -0
- data/maps/CityOfSecrets.map +0 -0
- data/maps/Condemned.map +0 -0
- data/maps/Duel_in_the_Snow.map +0 -0
- data/maps/Eruption.map +0 -0
- data/maps/Gatoron.map +0 -0
- data/maps/Spelunker's_Quest.map +0 -0
- metadata +66 -61
- data/docs/en/start.html~ +0 -516
@@ -0,0 +1,528 @@
|
|
1
|
+
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'prawn'
|
6
|
+
rescue LoadError => e
|
7
|
+
err = "Prawn PDF library not found. Please install it.\n"
|
8
|
+
if $rubygems
|
9
|
+
err += "You can usually do so if you do 'gem install prawn'."
|
10
|
+
else
|
11
|
+
err += "You can download it from www.rubyforge.net."
|
12
|
+
end
|
13
|
+
raise LoadError, err
|
14
|
+
end
|
15
|
+
|
16
|
+
require 'IFMapper/MapPrinting'
|
17
|
+
|
18
|
+
PDF_ZOOM = 0.5
|
19
|
+
PDF_ROOM_WIDTH = W * PDF_ZOOM
|
20
|
+
PDF_ROOM_HEIGHT = H * PDF_ZOOM
|
21
|
+
PDF_ROOM_WS = WS * PDF_ZOOM
|
22
|
+
PDF_ROOM_HS = HS * PDF_ZOOM
|
23
|
+
PDF_MARGIN = 20.0
|
24
|
+
|
25
|
+
#
|
26
|
+
# Open all the map class and add all pdf methods there
|
27
|
+
# Gotta love Ruby's flexibility to just inject in new methods.
|
28
|
+
#
|
29
|
+
class FXConnection
|
30
|
+
def _cvt_pt(p, opts)
|
31
|
+
x = (p[0] - WW / 2.0) / WW.to_f
|
32
|
+
y = (p[1] - HH / 2.0) / HH.to_f
|
33
|
+
x = x * opts['ww'] + opts['ws_2'] + opts['margin_2'] + opts['w'] / 2.0
|
34
|
+
y = (opts['height'] - y) * opts['hh'] + opts['hs_2'] + opts['margin_2'] + opts['hs']
|
35
|
+
return [x, y]
|
36
|
+
end
|
37
|
+
|
38
|
+
def pdf_draw_arrow(pdf, opts, x1, y1, x2, y2)
|
39
|
+
return if @dir == BOTH
|
40
|
+
|
41
|
+
pt1, d = _arrow_info( x1, y1, x2, y2, 0.5 )
|
42
|
+
|
43
|
+
pdf.stroke_color '000000'
|
44
|
+
pdf.fill_color '000000'
|
45
|
+
pdf.fill_polygon( [ pt1[0], pt1[1] ],
|
46
|
+
[ pt1[0] + d[0], pt1[1] - d[1] ],
|
47
|
+
[ pt1[0] + d[0], pt1[1] + d[1] ] )
|
48
|
+
end
|
49
|
+
|
50
|
+
def pdf_draw_complex_as_bspline( pdf, opts )
|
51
|
+
p = []
|
52
|
+
p << _cvt_pt(@pts[0], opts)
|
53
|
+
p << p[0]
|
54
|
+
p << p[0]
|
55
|
+
@pts.each { |pt|
|
56
|
+
p << _cvt_pt(pt, opts)
|
57
|
+
}
|
58
|
+
p << p[-1]
|
59
|
+
p << p[-1]
|
60
|
+
p << p[-1]
|
61
|
+
return FXSpline::bspline(p)
|
62
|
+
end
|
63
|
+
|
64
|
+
# PRE: If it's a loop exit that comes back to the same place, let's move
|
65
|
+
# it up and right
|
66
|
+
def pdf_draw_complex_as_lines( pdf, opts )
|
67
|
+
p = []
|
68
|
+
maxy = opts['height'] * opts['hh'] + opts['hs_2'] + opts['margin_2']
|
69
|
+
@pts.each { |pt|
|
70
|
+
if loop? == true
|
71
|
+
p << [ pt[0] * PDF_ZOOM + 10, maxy - pt[1] * PDF_ZOOM + 48 ]
|
72
|
+
else
|
73
|
+
p << [ pt[0] * PDF_ZOOM, maxy - pt[1] * PDF_ZOOM ]
|
74
|
+
end
|
75
|
+
}
|
76
|
+
return p
|
77
|
+
end
|
78
|
+
|
79
|
+
def pdf_draw_door( pdf, x1, y1, x2, y2 )
|
80
|
+
v = [ (x2-x1), (y2-y1) ]
|
81
|
+
t = 10 / Math.sqrt(v[0]*v[0]+v[1]*v[1])
|
82
|
+
v = [ v[0]*t, v[1]*t ]
|
83
|
+
m = [ (x2+x1)/2, (y2+y1)/2 ]
|
84
|
+
x1, y1 = [m[0] + v[1], m[1] - v[0]]
|
85
|
+
x2, y2 = [m[0] - v[1], m[1] + v[0]]
|
86
|
+
pdf.stroke_color '000000'
|
87
|
+
pdf.fill_color '000000'
|
88
|
+
if @type == LOCKED_DOOR
|
89
|
+
pdf.move_to(x1, y1)
|
90
|
+
pdf.line_to(x2, y2)
|
91
|
+
else
|
92
|
+
pdf.cap_style = :butt
|
93
|
+
pdf.join_style = :miter
|
94
|
+
pdf.undash
|
95
|
+
|
96
|
+
v = [ v[0] / 4, v[1] / 4]
|
97
|
+
pdf.move_to(x1 - v[0], y1 - v[1])
|
98
|
+
pdf.line_to(x1 + v[0], y1 + v[1])
|
99
|
+
pdf.line_to(x2 + v[0], y2 + v[1])
|
100
|
+
pdf.line_to(x2 - v[0], y2 - v[1])
|
101
|
+
pdf.line_to(x1 - v[0], y1 - v[1])
|
102
|
+
|
103
|
+
pdf.cap_style = :butt
|
104
|
+
pdf.join_style = :miter
|
105
|
+
pdf.undash
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def pdf_draw_complex( pdf, opts )
|
110
|
+
pdf.stroke_color '000000'
|
111
|
+
pdf.fill_color '000000'
|
112
|
+
if opts['Paths as Curves']
|
113
|
+
if @room[0] == @room[1]
|
114
|
+
dirA, dirB = dirs
|
115
|
+
if dirA == dirB
|
116
|
+
p = pdf_draw_complex_as_lines( pdf, opts )
|
117
|
+
else
|
118
|
+
p = pdf_draw_complex_as_bspline( pdf, opts )
|
119
|
+
end
|
120
|
+
else
|
121
|
+
p = pdf_draw_complex_as_bspline( pdf, opts )
|
122
|
+
end
|
123
|
+
else
|
124
|
+
p = pdf_draw_complex_as_lines( pdf, opts )
|
125
|
+
end
|
126
|
+
|
127
|
+
pdf.stroke_color '000000'
|
128
|
+
pdf.fill_color '000000'
|
129
|
+
pdf.move_to( p[0][0], p[0][1] )
|
130
|
+
p.each { |pt| pdf.line_to( pt[0], pt[1] ) }
|
131
|
+
|
132
|
+
x1, y1 = [p[0][0], p[0][1]]
|
133
|
+
x2, y2 = [p[-1][0], p[-1][1]]
|
134
|
+
pdf_draw_arrow(pdf, opts, x1, y1, x2, y2)
|
135
|
+
|
136
|
+
if @type == LOCKED_DOOR or @type == CLOSED_DOOR
|
137
|
+
t = p.size / 2
|
138
|
+
x1, y1 = [ p[t][0], p[t][1] ]
|
139
|
+
x2, y2 = [ p[t-2][0], p[t-2][1] ]
|
140
|
+
pdf_draw_door(pdf, x1, y1, x2, y2)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def pdf_draw_simple(pdf, opts)
|
145
|
+
return if not @room[1] # PDF does not print unfinished complex connections
|
146
|
+
|
147
|
+
dir = @room[0].exits.index(self)
|
148
|
+
x1, y1 = @room[0].pdf_corner(opts, self, dir)
|
149
|
+
x2, y2 = @room[1].pdf_corner(opts, self)
|
150
|
+
pdf.stroke_color '000000'
|
151
|
+
pdf.fill_color '000000'
|
152
|
+
pdf.move_to(x1, y1)
|
153
|
+
pdf.line_to(x2, y2)
|
154
|
+
pdf_draw_arrow(pdf, opts, x1, y1, x2, y2)
|
155
|
+
if @type == LOCKED_DOOR or @type == CLOSED_DOOR
|
156
|
+
pdf_draw_door(pdf, x1, y1, x2, y2)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# Draw the connection text next to the arrow ('I', 'O', etc)
|
162
|
+
#
|
163
|
+
def pdf_draw_text(pdf, x, y, dir, text, arrow)
|
164
|
+
if dir == 7 or dir < 6 and dir != 1
|
165
|
+
if arrow and (dir == 0 or dir == 4)
|
166
|
+
x += 5
|
167
|
+
end
|
168
|
+
x += 2.5
|
169
|
+
elsif dir == 6 or dir == 1
|
170
|
+
x -= 7.5
|
171
|
+
end
|
172
|
+
|
173
|
+
if dir > 5 or dir < 4
|
174
|
+
if arrow and (dir == 6 or dir == 2)
|
175
|
+
y += 5
|
176
|
+
end
|
177
|
+
y += 2.5
|
178
|
+
elsif dir == 4 or dir == 5
|
179
|
+
y -= 7.5
|
180
|
+
end
|
181
|
+
|
182
|
+
font_size = 8
|
183
|
+
pdf.text_box text, :at => [x, y], :size => font_size
|
184
|
+
end
|
185
|
+
|
186
|
+
def pdf_draw_exit_text(pdf, opts)
|
187
|
+
|
188
|
+
if @exitText[0] != 0
|
189
|
+
dir = @room[0].exits.index(self)
|
190
|
+
x, y = @room[0].pdf_corner(opts, self, dir)
|
191
|
+
pdf.move_to(x, y)
|
192
|
+
pdf_draw_text( pdf, x, y+4, dir,
|
193
|
+
EXIT_TEXT[@exitText[0]], @dir == BtoA)
|
194
|
+
end
|
195
|
+
|
196
|
+
if @exitText[1] != 0
|
197
|
+
dir = @room[1].exits.rindex(self)
|
198
|
+
x, y = @room[1].pdf_corner(opts, self, dir)
|
199
|
+
pdf_draw_text( pdf, x, y+4, dir,
|
200
|
+
EXIT_TEXT[@exitText[1]], @dir == AtoB)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def pdf_draw(pdf, opts)
|
205
|
+
pdf_draw_exit_text(pdf, opts)
|
206
|
+
if @type == SPECIAL
|
207
|
+
pdf.dash 4
|
208
|
+
else
|
209
|
+
pdf.cap_style = :butt
|
210
|
+
pdf.join_style = :miter
|
211
|
+
pdf.undash
|
212
|
+
end
|
213
|
+
pdf.stroke_color '000000'
|
214
|
+
pdf.fill_color '000000'
|
215
|
+
if @pts.size > 0
|
216
|
+
pdf_draw_complex(pdf, opts)
|
217
|
+
else
|
218
|
+
pdf_draw_simple(pdf, opts)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
class FXRoom
|
225
|
+
def pdf_corner( opts, c, idx = nil )
|
226
|
+
x, y = _corner(c, idx)
|
227
|
+
y = -y
|
228
|
+
|
229
|
+
ww = opts['ww']
|
230
|
+
hh = opts['hh']
|
231
|
+
w = opts['w']
|
232
|
+
h = opts['h']
|
233
|
+
|
234
|
+
ry = opts['height'] - @y
|
235
|
+
x = @x * ww + opts['ws_2'] + opts['margin_2'] + x * w
|
236
|
+
y = ry * hh + opts['hs_2'] + h + opts['margin_2'] + y * h
|
237
|
+
return [x, y]
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
def pdf_draw_box( pdf, opts, idx, pdflocationnos )
|
242
|
+
x = @x * opts['ww'] + opts['ws_2'] + opts['margin_2']
|
243
|
+
y = (opts['height'] - @y) * opts['hh'] + opts['hs_2'] + opts['margin_2']
|
244
|
+
|
245
|
+
pdf.cap_style = :butt
|
246
|
+
pdf.join_style = :miter
|
247
|
+
pdf.line_width 1
|
248
|
+
|
249
|
+
if @darkness
|
250
|
+
pdf.fill_color '808080'
|
251
|
+
pdf.stroke_color '000000'
|
252
|
+
else
|
253
|
+
pdf.fill_color 'ffffff'
|
254
|
+
pdf.stroke_color '000000'
|
255
|
+
end
|
256
|
+
|
257
|
+
pdf.stroke_rectangle [x, y], opts['w'], -opts['h']
|
258
|
+
|
259
|
+
if pdflocationnos == 1
|
260
|
+
# PRE: Draw a rectangle for the location number
|
261
|
+
pdf.stroke_rectangle( [x+opts['w']-opts['w']/4, y],
|
262
|
+
opts['w']/4, -opts['h']/4 )
|
263
|
+
|
264
|
+
# PRE: Pad out the number so it is three chars long
|
265
|
+
locationno = (idx+1).to_s
|
266
|
+
if (idx+1) < 10
|
267
|
+
locationno = ' '+locationno
|
268
|
+
elsif (idx+1) < 100
|
269
|
+
locationno = ' '+locationno
|
270
|
+
end
|
271
|
+
|
272
|
+
# PRE: Write the location number
|
273
|
+
pdf.stroke_color '000000'
|
274
|
+
pdf.fill_color '000000'
|
275
|
+
|
276
|
+
pdf.text_box locationno,
|
277
|
+
:at => [(x+((opts['w']/4)*3)+2), y+7], :size => 8
|
278
|
+
end
|
279
|
+
|
280
|
+
end
|
281
|
+
|
282
|
+
def pdf_draw_text( pdf, opts, x, y, text, font_size, pdflocationnos )
|
283
|
+
miny = (opts['height'] - @y) * opts['hh'] + opts['hs_2'] +
|
284
|
+
opts['margin_2']
|
285
|
+
pdf.text_box text, :at => [x, y+6], :size => font_size,
|
286
|
+
:width => opts['w'], :height => opts['h'], :valign => :top,
|
287
|
+
:align => :left, :overflow => :shrink_to_fit
|
288
|
+
return [x, y]
|
289
|
+
end
|
290
|
+
|
291
|
+
def pdf_draw_objects(pdf, opts, x, y, pdflocationnos)
|
292
|
+
font_size = 6
|
293
|
+
objs = @objects.split("\n")
|
294
|
+
objs = objs.join(', ')
|
295
|
+
return pdf_draw_text( pdf, opts, x, y-font_size,
|
296
|
+
objs, font_size, pdflocationnos )
|
297
|
+
end
|
298
|
+
|
299
|
+
def pdf_draw_name(pdf, opts, pdflocationnos)
|
300
|
+
# We could also use pdf_corner(7) here
|
301
|
+
x = @x * opts['ww'] + opts['margin_2'] + opts['ws_2'] + 2
|
302
|
+
y = opts['height'] - @y
|
303
|
+
font_size = 8
|
304
|
+
y = y * opts['hh'] + opts['margin_2'] + opts['hs_2'] + opts['h'] -
|
305
|
+
(font_size + 2)
|
306
|
+
pdf.stroke_color '000000'
|
307
|
+
pdf.fill_color '000000'
|
308
|
+
return pdf_draw_text( pdf, opts, x, y, @name, font_size, pdflocationnos )
|
309
|
+
end
|
310
|
+
|
311
|
+
# PRE: Send through the index so we can print the location number
|
312
|
+
# along with boolean value indicating whether the user wants them
|
313
|
+
def pdf_draw( pdf, opts, idx, pdflocationnos )
|
314
|
+
pdf_draw_box( pdf, opts, idx, pdflocationnos )
|
315
|
+
x, y = pdf_draw_name( pdf, opts, pdflocationnos )
|
316
|
+
pdf_draw_objects(pdf, opts, x, y, pdflocationnos)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
|
321
|
+
|
322
|
+
class FXSection
|
323
|
+
|
324
|
+
def pdf_draw_grid(pdf, opts, w, h )
|
325
|
+
(0...w).each { |xx|
|
326
|
+
(0...h).each { |yy|
|
327
|
+
x = xx * opts['ww'] + opts['ws_2'] + opts['margin_2']
|
328
|
+
y = yy * opts['hh'] + opts['hs_2'] + opts['margin_2']
|
329
|
+
pdf.rectangle([x, y], opts['w'], opts['h'])
|
330
|
+
}
|
331
|
+
}
|
332
|
+
end
|
333
|
+
|
334
|
+
|
335
|
+
def pdf_draw_section_name( pdf, opts, px, py )
|
336
|
+
return if not @name or @name == ''
|
337
|
+
xymin, xymax = min_max_rooms
|
338
|
+
text = @name
|
339
|
+
text += " (#{px}, #{py})" if px > 0 or py > 0
|
340
|
+
y = (opts['height']) * opts['hh'] + 16
|
341
|
+
w = xymax[0]
|
342
|
+
w = opts['width'] if w > opts['width']
|
343
|
+
x = (w + 2) * opts['ww'] / 2 - text.size / 2 * 16
|
344
|
+
x = 0 if x < 0
|
345
|
+
pdf.text_box( text, :at => [x,y], :font_size => 16 )
|
346
|
+
end
|
347
|
+
|
348
|
+
|
349
|
+
def pdf_draw(pdf, opts, mapname, pdflocationnos )
|
350
|
+
|
351
|
+
|
352
|
+
w, h = rooms_width_height
|
353
|
+
x, y = [0, 0]
|
354
|
+
|
355
|
+
loop do
|
356
|
+
|
357
|
+
pdf.save_graphics_state
|
358
|
+
|
359
|
+
if rotate
|
360
|
+
pdf.rotate 90.0
|
361
|
+
pdf.translate( 0, -pdf.margin_box.height )
|
362
|
+
end
|
363
|
+
|
364
|
+
# Move section to its position in page
|
365
|
+
tx1, ty1 = [@xoff * opts['ww'], @yoff * -opts['hh']]
|
366
|
+
pdf.translate( tx1, ty1 )
|
367
|
+
|
368
|
+
# Use times-roman as font
|
369
|
+
pdf.font 'Times-Roman'
|
370
|
+
pdf.stroke_color '000000'
|
371
|
+
|
372
|
+
pdf_draw_section_name( pdf, opts, x, y )
|
373
|
+
|
374
|
+
xymin, = min_max_rooms
|
375
|
+
|
376
|
+
# Move rooms, so that we don't print empty areas
|
377
|
+
tx2 = -(xymin[0]) * opts['ww'] - x * opts['ww']
|
378
|
+
ty2 = (xymin[1]) * opts['hh'] - 60 + (y - (y > 0? 1 : 0)) * opts['hh']
|
379
|
+
pdf.translate( tx2, ty2 )
|
380
|
+
|
381
|
+
|
382
|
+
# For testing purposes only, draw grid of boxes
|
383
|
+
# pdf_draw_grid( pdf, opts, w, h )
|
384
|
+
@connections.each { |c|
|
385
|
+
a = c.roomA
|
386
|
+
b = c.roomB
|
387
|
+
next if a.y < y and b and b.y < y
|
388
|
+
c.pdf_draw( pdf, opts )
|
389
|
+
}
|
390
|
+
@rooms.each_with_index { |r, idx|
|
391
|
+
next if r.y < y
|
392
|
+
r.pdf_draw( pdf, opts, idx, pdflocationnos)
|
393
|
+
}
|
394
|
+
|
395
|
+
# Reset axis
|
396
|
+
pdf.translate(-tx2, -ty2)
|
397
|
+
pdf.translate(-tx1, -ty1)
|
398
|
+
|
399
|
+
xi = opts['width']
|
400
|
+
yi = opts['height']
|
401
|
+
if rotate
|
402
|
+
xi = (pdf.margin_box.height / opts['ww']).to_i - 1
|
403
|
+
yi = (pdf.margin_box.width / opts['hh']).to_i - 1
|
404
|
+
end
|
405
|
+
|
406
|
+
x += xi
|
407
|
+
if x >= w
|
408
|
+
x = 0
|
409
|
+
y += yi
|
410
|
+
break if y >= h
|
411
|
+
end
|
412
|
+
|
413
|
+
if rotate
|
414
|
+
pdf.rotate(-90.0)
|
415
|
+
pdf.translate( 0, pdf.page_height )
|
416
|
+
end
|
417
|
+
|
418
|
+
pdf.restore_graphics_state
|
419
|
+
|
420
|
+
# We could not fit all rooms in page. Start new page
|
421
|
+
pdf.start_new_page
|
422
|
+
end
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
|
427
|
+
class FXMap
|
428
|
+
|
429
|
+
attr_accessor :pdfpapersize
|
430
|
+
# boolean value indicating whether the user wants to see location nos
|
431
|
+
attr_accessor :pdflocationnos
|
432
|
+
|
433
|
+
def pdf_draw_mapname( pdf, opts )
|
434
|
+
return if not @name or @name == ''
|
435
|
+
pdf.text( @name,
|
436
|
+
:font_size => 24,
|
437
|
+
:justification => :center
|
438
|
+
)
|
439
|
+
end
|
440
|
+
|
441
|
+
def pdf_draw_sections( pdf, opts )
|
442
|
+
old_section = @section
|
443
|
+
page = -1
|
444
|
+
@sections.each_with_index { |sect, idx|
|
445
|
+
if page != sect.page
|
446
|
+
page = sect.page
|
447
|
+
pdf.start_new_page if page > 1
|
448
|
+
pdf_draw_mapname( pdf, opts )
|
449
|
+
end
|
450
|
+
@section = idx
|
451
|
+
# For each page, we need to regenerate the pathmap so that complex
|
452
|
+
# paths will come out ok.
|
453
|
+
create_pathmap
|
454
|
+
# Now, we draw it
|
455
|
+
sect.pdf_draw(pdf, opts, @name, pdflocationnos)
|
456
|
+
}
|
457
|
+
|
458
|
+
# Restore original viewing page
|
459
|
+
@section = old_section
|
460
|
+
create_pathmap
|
461
|
+
end
|
462
|
+
|
463
|
+
|
464
|
+
def pdf_export(pdffile = Dir::tmpdir + "/ifmap.pdf", printer = nil)
|
465
|
+
|
466
|
+
# PRE: Let's set the PDF paper size to user's choice
|
467
|
+
paper = BOX_PDF_PAGE_SIZE_TEXT[pdfpapersize]
|
468
|
+
if printer
|
469
|
+
case printer.mediasize
|
470
|
+
when FXPrinter::MEDIA_LETTER
|
471
|
+
paper = 'LETTER'
|
472
|
+
when FXPrinter::MEDIA_LEGAL
|
473
|
+
paper = 'LEGAL'
|
474
|
+
when FXPrinter::MEDIA_A4
|
475
|
+
paper = 'A4'
|
476
|
+
when FXPrinter::MEDIA_ENVELOPE
|
477
|
+
paper = 'ENVELOPE'
|
478
|
+
when FXPrinter::MEDIA_CUSTOM
|
479
|
+
raise "Sorry, custom paper not supported"
|
480
|
+
end
|
481
|
+
end
|
482
|
+
|
483
|
+
# Open a new PDF writer with paper selected
|
484
|
+
# PRE: Let's also set the paper orientation based on user selection
|
485
|
+
|
486
|
+
pdf = Prawn::Document.new :page_size => paper
|
487
|
+
|
488
|
+
pdf_options = @options.dup
|
489
|
+
|
490
|
+
ww = PDF_ROOM_WIDTH + PDF_ROOM_WS
|
491
|
+
hh = PDF_ROOM_HEIGHT + PDF_ROOM_HS
|
492
|
+
|
493
|
+
pdf_options.merge!(
|
494
|
+
{
|
495
|
+
'ww' => ww,
|
496
|
+
'hh' => hh,
|
497
|
+
'w' => PDF_ROOM_WIDTH,
|
498
|
+
'h' => PDF_ROOM_HEIGHT,
|
499
|
+
'ws' => PDF_ROOM_WS,
|
500
|
+
'hs' => PDF_ROOM_HS,
|
501
|
+
'ws_2' => PDF_ROOM_WS / 2.0,
|
502
|
+
'hs_2' => PDF_ROOM_HS / 2.0,
|
503
|
+
'margin' => PDF_MARGIN,
|
504
|
+
'margin_2' => PDF_MARGIN / 2.0,
|
505
|
+
'width' => (pdf.margin_box.width / ww).to_i - 1,
|
506
|
+
'height' => (pdf.margin_box.height / hh).to_i - 1,
|
507
|
+
}
|
508
|
+
)
|
509
|
+
|
510
|
+
|
511
|
+
begin
|
512
|
+
# See if it is possible to pack several map sections (sections) into
|
513
|
+
# a single print page.
|
514
|
+
num = pack_sections( pdf_options['width'] + 2,
|
515
|
+
pdf_options['height'] + 2 )
|
516
|
+
pdf_draw_sections(pdf, pdf_options)
|
517
|
+
if pdffile !~ /\.pdf$/
|
518
|
+
pdffile << ".pdf"
|
519
|
+
end
|
520
|
+
status "Exporting PDF file '#{pdffile}'"
|
521
|
+
pdf.render_file pdffile
|
522
|
+
rescue => e
|
523
|
+
p e
|
524
|
+
p e.backtrace
|
525
|
+
raise e
|
526
|
+
end
|
527
|
+
end
|
528
|
+
end
|
data/lib/IFMapper/Room.rb
CHANGED
@@ -140,6 +140,7 @@ class TranscriptReader
|
|
140
140
|
SHORTNAME_MOONMIST = 2
|
141
141
|
SHORTNAME_WITNESS = 3
|
142
142
|
SHORTNAME_ADRIFT = 4
|
143
|
+
SHORTNAME_ALL_CAPS = 5
|
143
144
|
|
144
145
|
attr_reader :shortName
|
145
146
|
attr_accessor :identify, :map
|
@@ -843,6 +844,8 @@ class TranscriptReader
|
|
843
844
|
|
844
845
|
def room_name(line)
|
845
846
|
case @shortName
|
847
|
+
when SHORTNAME_ALL_CAPS
|
848
|
+
return room_name_all_caps(line)
|
846
849
|
when SHORTNAME_CAPITALIZED
|
847
850
|
return room_name_classic(line, false)
|
848
851
|
when SHORTNAME_MOONMIST
|
@@ -952,6 +955,64 @@ class TranscriptReader
|
|
952
955
|
return line
|
953
956
|
end
|
954
957
|
|
958
|
+
#
|
959
|
+
# Determine if line corresponds to a room name
|
960
|
+
#
|
961
|
+
def room_name_all_caps(line)
|
962
|
+
# Check if user/game has created a room with that name already
|
963
|
+
return line if find_room(line, nil)
|
964
|
+
|
965
|
+
# We have a room if we match darkness
|
966
|
+
return line if line =~ DARKNESS
|
967
|
+
|
968
|
+
# Remove unwanted stuff line (on the bed)
|
969
|
+
line.sub!(NAME_REMOVE, '')
|
970
|
+
|
971
|
+
# Check if user/game has created a room with that name already
|
972
|
+
return line if find_room(line, nil)
|
973
|
+
|
974
|
+
# Remove periods from salutations
|
975
|
+
line.sub!(SALUTATIONS, '\1')
|
976
|
+
|
977
|
+
# quick check for invalid format
|
978
|
+
return false if line =~ NAME_INVALID
|
979
|
+
|
980
|
+
# Qucik check for word characters
|
981
|
+
return false unless line =~ /\w/
|
982
|
+
|
983
|
+
# Check if we start line with uncapitalized words or symbols
|
984
|
+
return false if line =~ /^[ a-z\/\\\-\(\)']/
|
985
|
+
|
986
|
+
# Check if line holds only capitalized words or several spaces together
|
987
|
+
# or a quote or a 1) line. If so, not a room.
|
988
|
+
return false if line =~ /^[a-z\d,\.\/\-"'\s]+$/ or line =~ /\s\s/ or
|
989
|
+
line =~ /^".*"$/ or line =~ /^"[^"]+$/ or line =~ /^\d+\)/
|
990
|
+
|
991
|
+
# Check word count (if too many, not a room)
|
992
|
+
words = line.split(' ')
|
993
|
+
return false if words.size > NAME_MAXWORDS
|
994
|
+
|
995
|
+
|
996
|
+
# If not, check all words of 4 chars or more are capitalized
|
997
|
+
# and that there are no 3 or more short letter words together
|
998
|
+
# (which means a diagram)
|
999
|
+
num = 0
|
1000
|
+
words.each { |w|
|
1001
|
+
if w.size <= 2
|
1002
|
+
num += 1
|
1003
|
+
return false if num > 2
|
1004
|
+
else
|
1005
|
+
num = 0
|
1006
|
+
end
|
1007
|
+
}
|
1008
|
+
|
1009
|
+
# Restore period to salutations
|
1010
|
+
line.sub!(/\b#{SALUT}\b/, '\1.')
|
1011
|
+
|
1012
|
+
# Okay, it is a room.
|
1013
|
+
return line
|
1014
|
+
end
|
1015
|
+
|
955
1016
|
#
|
956
1017
|
# Create a new room
|
957
1018
|
#
|
@@ -133,6 +133,8 @@ Commands always begin with a > prompt.",
|
|
133
133
|
names where all words of 5 or more characters are capitalized).
|
134
134
|
However, commands do not begin with any type of prompt but start
|
135
135
|
with a lowercase word without any margin.",
|
136
|
+
"ALL CAPS mode is like Classic Mode but expects locations to be
|
137
|
+
spelled all in caps."
|
136
138
|
]
|
137
139
|
|
138
140
|
|
@@ -171,6 +173,12 @@ Front of Mall
|
|
171
173
|
spot of pavement is too narrow a place for them to stall. It is just
|
172
174
|
right for bicycles and motorbikes such as yours.
|
173
175
|
",
|
176
|
+
"
|
177
|
+
> look
|
178
|
+
WEST OF HOUSE
|
179
|
+
You are standing in an open field west of a white house, with a boarded
|
180
|
+
front door.
|
181
|
+
"
|
174
182
|
]
|
175
183
|
|
176
184
|
TRANSCRIPT_LOCATION2_TEXT = [
|
@@ -189,6 +197,9 @@ Women's change room
|
|
189
197
|
"
|
190
198
|
Front of Mall
|
191
199
|
",
|
200
|
+
"
|
201
|
+
WEST OF HALL
|
202
|
+
"
|
192
203
|
]
|
193
204
|
|
194
205
|
|
@@ -203,6 +214,7 @@ TRANSCRIPT_SHORTNAME_TYPE = [
|
|
203
214
|
'Moonmist',
|
204
215
|
'Witness',
|
205
216
|
'ADRIFT',
|
217
|
+
'ALL CAPS'
|
206
218
|
]
|
207
219
|
|
208
220
|
############ Window Titles
|
@@ -227,7 +239,7 @@ MSG_COMPLEX_CONNECTION_STOPPED = 'Complex connection interrupted.'
|
|
227
239
|
MSG_COMPLEX_CONNECTION_DONE = 'Complex connection done.'
|
228
240
|
|
229
241
|
MSG_CLICK_TO_SELECT_AND_MOVE = 'Click to select and move. Double click to edit.'
|
230
|
-
|
242
|
+
MSG_CLICK_TOGGLE_ONE_WAY_CONNECTION = 'Click to toggle one way connection.'
|
231
243
|
MSG_CLICK_CREATE_ROOM = 'Click to create new room.'
|
232
244
|
MSG_CLICK_CREATE_LINK = 'Click to create new connection.'
|
233
245
|
|
@@ -142,6 +142,8 @@ Los comandos siempre comienzan tras un >.",
|
|
142
142
|
"Modo ADRIFT espera las localidades como en el modo Clásico
|
143
143
|
(encabezados de palabras de 5 o más letras en mayúsculas).
|
144
144
|
Los comandos comienzan sólo con una palabra en minúscula sin margen.",
|
145
|
+
"Modo TODO MAYUSCULAS es como el modo Classic pero espera que los encabezados
|
146
|
+
de la localidad esten todo en mayusculas."
|
145
147
|
]
|
146
148
|
|
147
149
|
|
@@ -180,6 +182,11 @@ Entrada del Shopping
|
|
180
182
|
del pavimento es demasiado angosto para que estacionen. Es apenas
|
181
183
|
apropiado para bicicletas y motocicletas como la tuya.
|
182
184
|
",
|
185
|
+
"> mira
|
186
|
+
AL OESTE DE LA CASA
|
187
|
+
Estás parado en un campo abierto al oeste de una casa blanca, con una
|
188
|
+
puerta clausurada.
|
189
|
+
"
|
183
190
|
]
|
184
191
|
|
185
192
|
TRANSCRIPT_LOCATION2_TEXT = [
|
@@ -198,6 +205,9 @@ Vestidor de mujeres
|
|
198
205
|
"
|
199
206
|
Entrada del Shopping
|
200
207
|
",
|
208
|
+
"
|
209
|
+
AL OESTE DE LA CASA
|
210
|
+
"
|
201
211
|
]
|
202
212
|
|
203
213
|
|
@@ -212,6 +222,7 @@ TRANSCRIPT_SHORTNAME_TYPE = [
|
|
212
222
|
'Moonmist',
|
213
223
|
'Witness',
|
214
224
|
'ADRIFT',
|
225
|
+
'Todo Mayúsculas'
|
215
226
|
]
|
216
227
|
|
217
228
|
############ Títulos de Ventanas
|
@@ -233,7 +244,7 @@ MSG_COMPLEX_CONNECTION_STOPPED = 'Creación de la conexión compleja interrumpid
|
|
233
244
|
MSG_COMPLEX_CONNECTION_DONE = 'Conexión compleja completada.'
|
234
245
|
|
235
246
|
MSG_CLICK_TO_SELECT_AND_MOVE = 'Cliquée para seleccionar y mover. Cliquée dos veces para editar.'
|
236
|
-
|
247
|
+
MSG_CLICK_TOGGLE_ONE_WAY_CONNECTION = 'Cliquée para intercambiar conexión de un solo lado.'
|
237
248
|
MSG_CLICK_CREATE_ROOM = 'Cliquée para crear una nueva localidad.'
|
238
249
|
MSG_CLICK_CREATE_LINK = 'Cliquée para crear una nueva conexión.'
|
239
250
|
|
@@ -354,7 +365,7 @@ BOX_OBJECTS = 'Objetos: '
|
|
354
365
|
BOX_DARKNESS = 'Oscuridad'
|
355
366
|
BOX_TASKS = 'Tareas: '
|
356
367
|
BOX_DESCRIPTION = 'Descripción: '
|
357
|
-
BOX_COMMENTS = '
|
368
|
+
BOX_COMMENTS = 'Comentarios: '
|
358
369
|
|
359
370
|
BOX_CONNECTION_TYPE = 'Tipo de Conexión: '
|
360
371
|
BOX_CONNECTION_TYPE_TEXT = [
|