ifmapper 0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,161 @@
1
+
2
+ # Common printing add-ons
3
+ class FXSection
4
+ attr_accessor :xoff, :yoff, :page, :pxlen, :pylen, :rotate
5
+ end
6
+
7
+ class Page
8
+ attr_accessor :xlen, :ylen, :sections, :rotate
9
+ def initialize(xlen = 0, ylen = 0)
10
+ @xlen = xlen
11
+ @ylen = ylen
12
+ @rotate = false
13
+ @sections = []
14
+ end
15
+ end
16
+
17
+ class Map
18
+ #
19
+ # This code section is largely a copy of similar code used in
20
+ # IFM's C code.
21
+ # It tries to pack multiple map sections into a single page.
22
+ #
23
+ def pack_sections(xmax, ymax)
24
+ spacing = 0.0
25
+
26
+ # initialize -- one section per page
27
+ pages = []
28
+ @sections.each { |sect|
29
+ xlen, ylen = sect.rooms_width_height
30
+ sect.xoff = 0.0
31
+ sect.yoff = 0.0
32
+
33
+ page = Page.new(xlen+2, ylen+2)
34
+ pages.push page
35
+ page.sections << sect
36
+ }
37
+
38
+ ratio = xmax.to_f / ymax
39
+
40
+ packed = 1
41
+ while packed > 0
42
+ newpages = []
43
+ pos = packed = 0
44
+ while pos < pages.size
45
+ p1 = pages[pos]
46
+ x1 = p1.xlen
47
+ y1 = p1.ylen
48
+
49
+ # Check if it's better off rotated
50
+ p1.rotate = ((x1 < y1 and xmax > ymax) or
51
+ (x1 > y1 and xmax < ymax))
52
+
53
+ # Check if this is the last page
54
+ if pos + 1 == pages.size
55
+ newpages.push p1
56
+ break
57
+ end
58
+
59
+ # Get following page
60
+ p2 = pages[pos+1]
61
+ x2 = p2.xlen
62
+ y2 = p2.ylen
63
+
64
+ # Try combining pages in X direction
65
+ xc1 = x1 + x2 + spacing
66
+ yc1 = [y1, y2].max
67
+ v1 = (xc1 <= xmax and yc1 <= ymax)
68
+ r1 = xc1.to_f / yc1
69
+
70
+ # Try combining pages in Y direction
71
+ xc2 = [x1, x2].max
72
+ yc2 = y1 + y2 + spacing
73
+ v2 = (xc2 <= xmax and yc2 <= ymax)
74
+ r2 = xc2.to_f / yc2
75
+
76
+ # See which is best
77
+ if v1 and v2
78
+ if (ratio - r1).abs < (ratio - r2).abs
79
+ v2 = false
80
+ else
81
+ v1 = false
82
+ end
83
+ end
84
+
85
+ # Just copy page if nothing can be done
86
+ if not v1 and not v2
87
+ newpages.push(p1)
88
+ pos += 1
89
+ next
90
+ end
91
+
92
+ # Create merged page
93
+ page = Page.new
94
+ xo1 = yo1 = xo2 = yo2 = 0
95
+
96
+ if v1
97
+ page.xlen = xc1
98
+ page.ylen = yc1
99
+ xo2 = x1 + spacing
100
+
101
+ if y1 < y2
102
+ yo1 = (yc1 - y1) / 2
103
+ else
104
+ yo2 = (yc1 - y2) / 2
105
+ end
106
+ end
107
+
108
+ if v2
109
+ page.xlen = xc2
110
+ page.ylen = yc2
111
+ yo1 = y2 + spacing
112
+
113
+ if x1 < x2
114
+ xo1 = (xc2 - x1) / 2
115
+ else
116
+ xo2 = (xc2 - x2) / 2
117
+ end
118
+ end
119
+
120
+ # Copy sections to new page, updating offsets
121
+ opsects = p1.sections
122
+ opsects.each { |sect|
123
+ page.sections.push sect
124
+ sect.xoff += xo1
125
+ sect.yoff += yo1
126
+ }
127
+
128
+ opsects = p2.sections
129
+ opsects.each { |sect|
130
+ page.sections.push sect
131
+ sect.xoff += xo2
132
+ sect.yoff += yo2
133
+ }
134
+
135
+ # Add merged page to list and go to next page pair
136
+ newpages.push page
137
+ pos += 2
138
+ packed += 1
139
+ end
140
+ pages = newpages
141
+ end
142
+
143
+ # Give each section its page info and clean up
144
+ num = 0
145
+ pages.each { |page|
146
+ psects = page.sections
147
+ xlen = page.xlen
148
+ ylen = page.ylen
149
+ rflag = page.rotate
150
+
151
+ num += 1
152
+ psects.each { |sect|
153
+ sect.page = num
154
+ sect.pxlen = xlen
155
+ sect.pylen = ylen
156
+ sect.rotate = rflag
157
+ }
158
+ }
159
+ return num
160
+ end
161
+ end
@@ -11,6 +11,8 @@ rescue => e
11
11
  raise "Please install 'pdf writer' library for Acrobat PDF support."
12
12
  end
13
13
 
14
+ require 'IFMapper/MapPrinting'
15
+
14
16
  PDF_ZOOM = 0.5
15
17
  PDF_ROOM_WIDTH = W * PDF_ZOOM # 60
16
18
  PDF_ROOM_HEIGHT = H * PDF_ZOOM # 37.5
@@ -18,7 +20,6 @@ PDF_ROOM_WS = WS * PDF_ZOOM
18
20
  PDF_ROOM_HS = HS * PDF_ZOOM
19
21
  PDF_MARGIN = 20
20
22
 
21
-
22
23
  #
23
24
  # Open all the map class and add all pdf methods there
24
25
  # Gotta love Ruby's flexibility to just inject in new methods.
@@ -87,8 +88,8 @@ class FXConnection
87
88
  return if not @roomB # PDF does not print unfinished complex connections
88
89
 
89
90
  dir = @roomA.exits.index(self)
90
- x1, y1 = @roomA.pdf_corner(pdf, opts, self, dir)
91
- x2, y2 = @roomB.pdf_corner(pdf, opts, self)
91
+ x1, y1 = @roomA.pdf_corner(opts, self, dir)
92
+ x2, y2 = @roomB.pdf_corner(opts, self)
92
93
  pdf.move_to(x1, y1)
93
94
  pdf.line_to(x2, y2).stroke
94
95
  pdf_draw_arrow(pdf, opts, x1, y1, x2, y2)
@@ -102,8 +103,49 @@ class FXConnection
102
103
  end
103
104
  end
104
105
 
106
+ #
107
+ # Draw the connection text next to the arrow ('I', 'O', etc)
108
+ #
109
+ def pdf_draw_text(pdf, x, y, dir, text, arrow)
110
+ if dir == 7 or dir < 6 and dir != 1
111
+ if arrow and (dir == 0 or dir == 4)
112
+ x += 5
113
+ end
114
+ x += 2.5
115
+ elsif dir == 6 or dir == 1
116
+ x -= 7.5
117
+ end
118
+
119
+ if dir > 5 or dir < 4
120
+ if arrow and (dir == 6 or dir == 2)
121
+ y += 5
122
+ end
123
+ y += 2.5
124
+ elsif dir == 4 or dir == 5
125
+ y -= 7.5
126
+ end
127
+
128
+ font_size = 8
129
+ pdf.add_text(x, y, text, font_size)
130
+ end
131
+
132
+ def pdf_draw_exit_text(pdf, opts)
133
+ if @exitAtext != 0
134
+ dir = @roomA.exits.index(self)
135
+ x, y = @roomA.pdf_corner(opts, self, dir)
136
+ pdf_draw_text( pdf, x, y, dir,
137
+ EXIT_TEXT[@exitAtext], @dir == BtoA)
138
+ end
139
+ if @exitBtext != 0
140
+ dir = @roomB.exits.rindex(self)
141
+ x, y = @roomB.pdf_corner(opts, self, dir)
142
+ pdf_draw_text( pdf, x, y, dir,
143
+ EXIT_TEXT[@exitBtext], @dir == AtoB)
144
+ end
145
+ end
146
+
105
147
  def pdf_draw(pdf, opts)
106
- # pdf_draw_exit_text(pdf, opts)
148
+ pdf_draw_exit_text(pdf, opts)
107
149
  if @type == SPECIAL
108
150
  s = PDF::Writer::StrokeStyle.new(2, :dash => {
109
151
  :pattern => [2],
@@ -128,7 +170,7 @@ end
128
170
 
129
171
 
130
172
  class FXRoom
131
- def pdf_corner( pdf, opts, c, idx = nil )
173
+ def pdf_corner( opts, c, idx = nil )
132
174
  x, y = _corner(c, idx)
133
175
  y = -y
134
176
 
@@ -160,30 +202,46 @@ class FXRoom
160
202
  pdf.rectangle(x, y, opts['w'], opts['h']).fill_stroke
161
203
  end
162
204
 
205
+ def pdf_draw_text( pdf, opts, x, y, text, font_size )
206
+ miny = (opts['height'] - @y) * opts['hh'] + opts['hs_2'] +
207
+ opts['margin_2']
208
+ while text != ''
209
+ text = pdf.add_text_wrap(x, y, opts['w'] - 2, text, font_size)
210
+ y -= font_size
211
+ break if y <= miny
212
+ end
213
+ return [x, y]
214
+ end
215
+
216
+ def pdf_draw_objects(pdf, opts, x, y)
217
+ font_size = 6
218
+ objs = @objects.split("\n")
219
+ objs = objs.join(', ')
220
+ return pdf_draw_text( pdf, opts, x, y, objs, font_size )
221
+ end
222
+
163
223
  def pdf_draw_name(pdf, opts)
164
224
  # We could also use pdf_corner(7) here
165
225
  x = @x * opts['ww'] + opts['margin_2'] + opts['ws_2'] + 2
166
226
  y = opts['height'] - @y
167
- y = y * opts['hh'] + opts['margin_2'] + opts['hs_2'] + opts['h'] - 10
168
227
  font_size = 8
228
+ y = y * opts['hh'] + opts['margin_2'] + opts['hs_2'] + opts['h'] -
229
+ (font_size + 2)
169
230
  pdf.stroke_color(Color::RGB::Black)
170
231
  pdf.fill_color(Color::RGB::Black)
171
- text = @name
172
- while text != ''
173
- text = pdf.add_text_wrap(x, y, opts['w'], text, font_size)
174
- y -= font_size
175
- end
232
+ return pdf_draw_text( pdf, opts, x, y, @name, font_size )
176
233
  end
177
234
 
178
235
  def pdf_draw( pdf, opts, idx )
179
236
  pdf_draw_box( pdf, opts )
180
- pdf_draw_name( pdf, opts )
237
+ x, y = pdf_draw_name( pdf, opts )
238
+ pdf_draw_objects(pdf, opts, x, y)
181
239
  end
182
240
  end
183
241
 
184
242
 
185
243
 
186
- class FXPage
244
+ class FXSection
187
245
 
188
246
  def pdf_draw_grid(pdf, opts, w, h )
189
247
  (0...w).each { |xx|
@@ -195,68 +253,80 @@ class FXPage
195
253
  }
196
254
  end
197
255
 
198
- def pdf_draw_mapname( pdf, opts, mapname )
199
- return if not mapname or mapname == ''
200
- pdf.text( mapname,
201
- :font_size => 24,
202
- :justification => :center
203
- )
204
- end
205
256
 
206
- def pdf_draw_pagename( pdf, opts )
257
+ def pdf_draw_section_name( pdf, opts )
207
258
  return if not @name or @name == ''
208
- pdf.text( @name,
209
- :font_size => 16,
210
- :justification => :center
211
- )
259
+ y = (opts['height']) * opts['hh'] + 16
260
+ xymin, xymax = min_max_rooms
261
+ x = (xymax[0] + 2) * opts['ww'] / 2
262
+ pdf.add_text( x, y, @name, 16 )
212
263
  end
213
264
 
214
265
 
215
266
  def pdf_draw(pdf, opts, mapname )
216
- width, height = rooms_width_height
217
-
218
- #
219
- # Determine if better to print page in landscape mode
220
- #
221
- landscape = false
222
- if landscape
267
+ if rotate
223
268
  pdf.rotate_axis(90.0)
224
- pdf.translate_axis( 0, -pdf.page_width )
269
+ pdf.translate_axis( 0, -pdf.page_height )
225
270
  end
226
271
 
272
+ # Move section to its position in page
273
+ pack = [@xoff * opts['ww'], @yoff * -opts['hh']]
274
+ pdf.translate_axis( pack[0], pack[1] )
275
+
227
276
  # Use times-roman as font
228
277
  pdf.select_font 'Times-Roman'
229
278
  pdf.stroke_color(Color::RGB::Black)
230
279
  pdf.fill_color(Color::RGB::Black)
231
280
 
232
- pdf_draw_mapname( pdf, opts, mapname )
233
- pdf_draw_pagename( pdf, opts )
281
+ pdf_draw_section_name( pdf, opts )
282
+
283
+ xymin, = min_max_rooms
284
+
285
+ x = -(xymin[0]-1) * opts['ww']
286
+ y = (xymin[1]-1) * opts['hh']
287
+ pdf.translate_axis( x, y )
234
288
 
235
289
  # For testing purposes only, draw grid of boxes
236
290
  # pdf_draw_grid( pdf, opts, width, height )
237
-
238
291
  @connections.each { |c| c.pdf_draw( pdf, opts ) }
239
292
  @rooms.each_with_index { |r, idx| r.pdf_draw( pdf, opts, idx) }
293
+
294
+ # Reset axis
295
+ pdf.translate_axis(-x, -y)
296
+ pdf.translate_axis(-pack[0], -pack[1])
240
297
  end
241
298
  end
242
299
 
243
300
 
244
301
  class FXMap
245
302
 
246
- def pdf_draw_pages( pdf, opts )
247
- old_page = @page
248
- @pages.each_with_index { |p, idx|
249
- pdf.start_new_page if idx > 0
250
- @page = idx
303
+ def pdf_draw_mapname( pdf, opts )
304
+ return if not @name or @name == ''
305
+ pdf.text( @name,
306
+ :font_size => 24,
307
+ :justification => :center
308
+ )
309
+ end
310
+
311
+ def pdf_draw_sections( pdf, opts )
312
+ old_section = @section
313
+ page = -1
314
+ @sections.each_with_index { |sect, idx|
315
+ if page != sect.page
316
+ page = sect.page
317
+ pdf.start_new_page if page > 1
318
+ pdf_draw_mapname( pdf, opts )
319
+ end
320
+ @section = idx
251
321
  # For each page, we need to regenerate the pathmap so that complex
252
322
  # paths will come out ok.
253
323
  create_pathmap
254
324
  # Now, we draw it
255
- p.pdf_draw(pdf, opts, @name)
325
+ sect.pdf_draw(pdf, opts, @name)
256
326
  }
257
327
 
258
328
  # Restore original viewing page
259
- @page = old_page
329
+ @section = old_section
260
330
  create_pathmap
261
331
  end
262
332
 
@@ -265,6 +335,8 @@ class FXMap
265
335
  paper = 'LETTER'
266
336
  if printer
267
337
  case printer.mediasize
338
+ when FXPrinter::MEDIA_LETTER
339
+ paper = 'LETTER'
268
340
  when FXPrinter::MEDIA_LEGAL
269
341
  paper = 'LEGAL'
270
342
  when FXPrinter::MEDIA_A4
@@ -281,10 +353,14 @@ class FXMap
281
353
 
282
354
 
283
355
  pdf_options = @options.dup
356
+
357
+ ww = PDF_ROOM_WIDTH + PDF_ROOM_WS
358
+ hh = PDF_ROOM_HEIGHT + PDF_ROOM_HS
359
+
284
360
  pdf_options.merge!(
285
361
  {
286
- 'ww' => PDF_ROOM_WIDTH + PDF_ROOM_WS,
287
- 'hh' => PDF_ROOM_HEIGHT + PDF_ROOM_HS,
362
+ 'ww' => ww,
363
+ 'hh' => hh,
288
364
  'w' => PDF_ROOM_WIDTH,
289
365
  'h' => PDF_ROOM_HEIGHT,
290
366
  'ws' => PDF_ROOM_WS,
@@ -293,18 +369,19 @@ class FXMap
293
369
  'hs_2' => PDF_ROOM_HS / 2.0,
294
370
  'margin' => PDF_MARGIN,
295
371
  'margin_2' => PDF_MARGIN / 2.0,
296
- 'width' => @width - 1,
297
- 'height' => @height - 1,
372
+ 'width' => (pdf.page_width / ww).to_i - 1,
373
+ 'height' => (pdf.page_height / hh).to_i - 1,
298
374
  }
299
375
  )
300
376
 
301
377
 
302
378
  begin
303
- # See if it is possible to pack several map sections (pages) into
379
+ # See if it is possible to pack several map sections (sections) into
304
380
  # a single print page.
305
- # pack_sections
306
- pdf_draw_pages(pdf, pdf_options)
307
- p "Saving pdf to '#{pdffile}'..."
381
+ num = pack_sections( pdf_options['width'] + 2,
382
+ pdf_options['height'] + 2 )
383
+ pdf_draw_sections(pdf, pdf_options)
384
+ status "Exporting PDF file '#{pdffile}'"
308
385
  pdf.save_as(pdffile)
309
386
  rescue => e
310
387
  p e