Module: PdfWritingTools

Defined in:
lib/pdf_writing_tools.rb,
lib/pdf_writing_tools/version.rb

Constant Summary collapse

VERSION =
'0.0.10'.freeze

Class Method Summary collapse

Class Method Details

.check_no_empty_string_presence(string_list) ⇒ Object

Se tutte le stringhe nella lista sono “” (stringa vuota) produce false altrimenti produce true.



388
389
390
391
392
393
394
395
396
# File 'lib/pdf_writing_tools.rb', line 388

def self.check_no_empty_string_presence(string_list)
   string_list.each do |string_element|
		if string_element != "" and string_element != []
			return true
		end
	end

	return false
end

.draw_cell_auto_height(pdf, draw_simulation, x, y, w, t, opts = {}, auto_y = false, no_background = false) ⇒ Object

della funzione). Produce un dizionario, con l’altezza della cella disegnata ed eventuale testo non disegnato (es. nel caso di sopraggiunto fine pagina). Il campo draw_simulation, serve ad evitare che la cella venga realmente disegnata nel pdf. In questo modo, posso ottenere l’altezza, eventuale testo “avanzato” e prendere decisioni che non dipendano da un’unica cella, ma da un gruppo di celle, come ad esempio quando devo disegnare la riga di una tabella che essendo composta da più celle, ha un altezza che dipende dall’altezza massima delle celle “autoridimensionanti” che la compongono.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/pdf_writing_tools.rb', line 120

def self.draw_cell_auto_height(pdf, draw_simulation, x, y, w, t, opts={}, auto_y=false, no_background=false)
  font_size        = opts[:font_size] || 10
  style            = opts[:style] || :normal
  align            = opts[:align] || :left
  valign           = opts[:valign] || :top
  font_color       = opts[:font_color] || "000000"
  border_color     = opts[:border_color] || "000000"
  background_color = opts[:background_color] || "FFFFFF"
  left_padding     = opts[:left_padding] || 5#
  right_padding    = opts[:right_padding] || 5#
  top_padding      = opts[:top_padding] || 5#
  bottom_padding   = opts[:bottom_padding] || 5#
  pdf_height       = opts[:pdf_height] || 297.mm #
  pdf_width        = opts[:pdf_width] || 21.cm #

  t = (t.class == String ? [{text: t, size: font_size, color: font_color}] : t)



  result = 0

  # Il testo in modalità simulazione, verrà generato in posizione y_pos1, tenendo conto del padding.
  # In questo modo, quando andrò a disegnare la cella vera e propria in posizione y_pos2, il testo
  # avrà il suo "spazio" (padding)
  y_pos1 = auto_y ? (pdf.cursor - top_padding) : (pdf_height - y - top_padding)
  y_pos2 = auto_y ? pdf.cursor : (pdf_height - y)

  pdf.canvas do
    # Non utilizzo l'helper (pdf.formatted_text_box), in quanto scriverebbe direttamente nel pdf
    # ma io ho bisogno di conoscere l'altezza del box di testo formattato, prima di scriverlo, in
    # modo da poter disegnare PRIMA lo sfondo


    b = Prawn::Text::Formatted::Box.new(
          t,
          {:at => [x + left_padding, y_pos1 ],
          :width => w - left_padding-right_padding,
          :size => font_size,
          :style => style,
          :overflow => :expand,
          :document => pdf,
          :align => align,
          :valign => valign}) #valign ha un comportamento da indagare, mi fa uscire il testo fuori dal box

    # Effettuo il render, ma in modalità "prova" (dry_run = true), così posso conoscere quale sarà
    # l'altezza del box prima di disegnarlo

    text_overflow = b.render(:dry_run => true)
    #text_overflow = text_overflow[:text] #### Temporaneo

    # Altezza del box, non ancora disegnato
    h = b.height

    if not draw_simulation
      # Se non sono in simulazione...
      # ... ora che conosco quale sarà l'altezza del box di testo, posso disegnare lo sfondo
      pdf.fill_color(background_color) # colore dello sfondo
      pdf.stroke_color(border_color)   # Colore del bordo


      if no_background
      else
        pdf.fill_and_stroke_rectangle([x, y_pos2], (w + left_padding + right_padding), (h+top_padding+bottom_padding))
      end
      # ... e infine, sopra lo sfondo disegno il testo
      pdf.fill_color(font_color) # colore del testo
      text_overflow = b.render() # text_overflow è l'eventuale testo avanzato
    end

    # La cella potrebbe non riuscire ad espandersi a sufficienza (troppo vicina al
    # fine pagine, quindi può essere che del testo "avanzi" )
    result = {height: h + top_padding + bottom_padding, overflow: text_overflow}
  end

  result
end

.draw_cell_fixed_height(pdf, x, y, w, h, t, opts = {}, auto_y = false, no_background = false) ⇒ Object

Disegna una cella di dimensioni fissate, nella data posizione. ###### E’ Possibile indicare il colore del bordo, dello sfondo, del font e della relativa dimensione (oltre a tutta un’altra serie di parametri (opts), vedere prima parte della funzione) La cella, viene disegnata “globalmente”, rispetto al pdf, ossia NON relativamente ad altri contenitori. x e y, indicano rispettivamente le coordinate x e y del vertice in alto a sinistra del box. Il vertice è relativo al margine superiore del pdf, contrariamente a quanto accade quando si utilizzano le primitive prawn (dove il margine di riferimento è quello basso della pagina). Bisogna pertanto prestare attenzione quando si dovessero mischiare primitive prawn con queste funzioni.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/pdf_writing_tools.rb', line 62

def self.draw_cell_fixed_height(pdf, x, y, w, h, t, opts={}, auto_y=false, no_background=false)
  t = (t.class == String ? [{text: t}] : t)
  font_size = opts[:font_size] || 10
  style = opts[:style] || :normal
  align = opts[:align] || :left
  valign = opts[:valign] || :top
  font_color = opts[:font_color] || '000000'
  border_color = opts[:border_color] || '000000'
  background_color = opts[:background_color] || 'FFFFFF'
  left_padding = opts[:left_padding] || 5
  right_padding = opts[:right_padding] || 5
  top_padding = opts[:top_padding] || 5
  bottom_padding = opts[:bottom_padding] || 5
  pdf_height = opts[:pdf_height] || 297.mm
  pdf_width = opts[:pdf_width] || 21.cm

  result = ''
  y_pos1 = auto_y ? pdf.cursor : (pdf_height - y)
  y_pos2 = auto_y ? pdf.cursor - top_padding : (pdf_height - y - top_padding)

  pdf.canvas do
    pdf.line_width = 0.5

    # Colore di sfondo della cella
    pdf.fill_color(background_color)

    # Disegna lo sfondo della cella
    if no_background
    else
      pdf.fill_rectangle([x, y_pos1], w, h)
    end

    pdf.stroke_color border_color
    pdf.stroke_rectangle([x, y_pos1], w, h)

    # Colore del testo nella cella
    pdf.fill_color(font_color)

    at = [x + left_padding, y_pos2]
    width = w - left_padding - right_padding
    height = h - top_padding - bottom_padding + 1.cm
    result = pdf.formatted_text_box(t, width: width, height: height, at: at, size: font_size, style: style, align: align, valign: valign)
  end

  result
end

.draw_row_auto_height(pdf, draw_simulation, x, y, widths, texts, opts = {}, auto_y = true) ⇒ Object

Produce la y su pdf, dove disegnare la prossima riga



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
# File 'lib/pdf_writing_tools.rb', line 246

def self.draw_row_auto_height(pdf, draw_simulation, x, y, widths, texts, opts = {}, auto_y = true)
	font_sizes        = opts[:font_sizes] || [10]
	styles            = opts[:styles] || [:normal]
	alignments        = opts[:alignments] || [:left]
	valignments       = opts[:valignments] || [:top]
	font_colors       = opts[:font_colors] || ["000000"]
	border_colors     = opts[:border_colors] || ["000000"]
	background_colors = opts[:background_colors] || ["FFFFFF"]
	paddings          = opts[:paddings] || [{left_padding: 5, right_padding: 5, top_padding: 5, bottom_padding: 5}]
	pdf_height        = opts[:pdf_height] || 297.mm
	pdf_width         = opts[:pdf_width] || 21.cm
	pdf_margin_top    = opts[:pdf_margin_top] || 2.cm
	pdf_margin_bottom = opts[:pdf_margin_bottom] || 2.cm
	pdf_margin_left   = opts[:pdf_margin_left] || 2.cm
	pdf_margin_right  = opts[:pdf_margin_right] || 2.cm

	new_y = pdf_margin_top

   
   # Se la y della nuova riga (angolo superiore sinistro), esce dal margine di pagina,
   # non posso disegnare la riga in questa pagina, ma devo passare alla successiva
   if (y) > (pdf_height - pdf_margin_bottom)
     pdf.start_new_page
     y = pdf_margin_top
   end

	loop do
		max_cell_height = 0

		# 1 - Cerco l'altezza della riga
		# Per prima cosa, simulo il disegno delle varie celle che compongono la riga.
		# In questo modo, posso sapere quale sarà la massima altezza raggiunta da una
		# cella, ossia l'altezza che deve avere la riga
		offset = 0
     widths.each_with_index do |width, i|
			font_size = font_sizes[i] || font_sizes[0]
			style = styles[i] || styles[0]
			align = alignments[i] || alignments[0]
			valign =  valignments[i] || valignments[0]
			font_color = font_colors[i] || font_colors[0]
			border_color = border_colors[i] || border_colors[0]
			background_color = background_colors[i] || background_colors[0]
			padding = paddings[i] || paddings[0]

       cell_opts = {}
       cell_opts[:font_size] = font_size
       cell_opts[:style] = style
       cell_opts[:align] = align
       cell_opts[:valign] = valign
       cell_opts[:font_color] = font_color
       cell_opts[:border_color] = border_color
       cell_opts[:background_color] = background_color
       cell_opts[:left_padding] = padding[:left_padding]
       cell_opts[:right_padding] = padding[:right_padding]
       cell_opts[:top_padding] = padding[:top_padding]
       cell_opts[:bottom_padding] = padding[:bottom_padding]
       cell_opts[:pdf_height] = 297.mm
       cell_opts[:pdf_weigth] = 21.cm

       draw_simulation = true
			r = draw_cell_auto_height(pdf, draw_simulation, x+offset, y, width, texts[i], cell_opts, auto_y)


			if r[:height] > max_cell_height
				max_cell_height = r[:height]
			end

			offset += width
		end


     # Non voglio che la riga ecceda il margine di pagina, quindi se così fosse
     # cambio pagina
		if (y + max_cell_height) > (pdf_height - pdf_margin_bottom)
			#max_cell_height = pdf_height - pdf_margin_bottom - y
       pdf.start_new_page
       y = pdf_margin_top
		end

		# A seguito della simulazione, ho ottenuto l'altezza di riga...
		# ... ora passo al disegno vero e proprie delle celle...
		offset = 0
		rtexts = []
		widths.each_with_index do |width, i|
			font_size = font_sizes[i] || font_sizes[0]
			style = styles[i] || styles[0]
			align = alignments[i] || alignments[0]
			valign =  valignments[i] || valignments[0]
			font_color = font_colors[i] || font_colors[0]
			border_color = border_colors[i] || border_colors[0]
			background_color = background_colors[i] || background_colors[0]
			padding = paddings[i] || paddings[0]

       cell_opts = {}
       cell_opts[:font_size] = font_size
       cell_opts[:style] = style
       cell_opts[:align] = align
       cell_opts[:valign] = valign
       cell_opts[:font_color] = font_color
       cell_opts[:border_color] = border_color
       cell_opts[:background_color] = background_color
       cell_opts[:left_padding] = padding[:left_padding]
       cell_opts[:right_padding] = padding[:right_padding]
       cell_opts[:top_padding] = padding[:top_padding]
       cell_opts[:bottom_padding] = padding[:bottom_padding]
       cell_opts[:pdf_height] = 297.mm
       cell_opts[:pdf_weigth] = 21.cm

			# ...disegno le celle vere e proprie ad altezza fissa, con l'altezza
			# ricavata dal passo precedente.
			r = draw_cell_fixed_height(pdf, x+offset, y, width, max_cell_height, texts[i], cell_opts, auto_y)

			# Gli eventuali "testi residui" (es. raggiunto fine pagina) li raccolgo
			# nel seguente array
			rtexts << r

			offset += width
		end

		texts = rtexts

     # Se nei testi residui, sono presenti solo stringhe vuote, posso uscire dal
     # loop, altrimenti, devo cambiare pagina e disegnare una nuova riga con i
     # testi rimanenti
     if !check_no_empty_string_presence(texts)
       new_y = y + max_cell_height
       break
     else
       pdf.start_new_page
       y = pdf_margin_top # Posiziono il cursore ad inizio della nuova pagina
     end
	end

   

   pdf.y = (pdf_height - new_y)

	return new_y
end

.draw_row_fixed_height(pdf, x, y, widths, height, texts, opts = {}, auto_y = false) ⇒ Object



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/pdf_writing_tools.rb', line 198

def self.draw_row_fixed_height(pdf, x, y, widths, height, texts, opts={}, auto_y=false)
	font_sizes        = opts[:font_sizes] || [10]
	styles            = opts[:styles] || [:normal]
	alignments        = opts[:alignments] || [:left]
	valignments       = opts[:valignments] || [:top]
	font_colors       = opts[:font_colors] || ["000000"]
	border_colors     = opts[:border_colors] || ["000000"]
	background_colors = opts[:background_colors] || ["FFFFFF"]
	paddings          = opts[:paddings] || [{left_padding: 5, right_padding: 5, top_padding: 5, bottom_padding: 5}]
	pdf_height        = opts[:pdf_height] || 297.mm
	pdf_width         = opts[:pdf_width] || 21.cm

	offset = 0

	widths.each_with_index do |width, i|
		font_size = font_sizes[i] || font_sizes[0]
		style = styles[i] || styles[0]
		align = alignments[i] || alignments[0]
		valign =  valignments[i] || valignments[0]
		font_color = font_colors[i] || font_colors[0]
		border_color = border_colors[i] || border_colors[0]
		background_color = background_colors[i] || background_colors[0]
		padding = paddings[i] || paddings[0]

     cell_opts = {}

     cell_opts[:font_size] = font_size
     cell_opts[:style] = style
     cell_opts[:align] = align
     cell_opts[:valign] = valign
     cell_opts[:font_color] = font_color
     cell_opts[:border_color] = border_color
     cell_opts[:background_color] = background_color
     cell_opts[:left_padding] = padding[:left_padding]
     cell_opts[:right_padding] = padding[:right_padding]
     cell_opts[:top_padding] = padding[:top_padding]
     cell_opts[:bottom_padding] = padding[:bottom_padding]
     cell_opts[:pdf_width] = 21.cm
     cell_opts[:pdf_height] = 297.mm

		draw_cell_fixed_height( pdf, x+offset, y, width, height, texts[i], cell_opts, auto_y)

		offset += width
	end
   pdf.y = (pdf.cursor - height)
end

.draw_xml_object(pdf, xml_object) ⇒ Object

L’oggetto xml, viene letto ricorsivamente. Si crea una lista, contenente dei dizionari. Ciascun dizionario contiene: Il nome di un’azione: :action_name Una lista “data”, contenente un dizionario con al suo interno le specifiche da dare a prawn, per “disegnare” del testo o per disegnare un’immagine

Le p



27
28
29
30
31
32
33
34
# File 'lib/pdf_writing_tools.rb', line 27

def self.draw_xml_object(pdf, xml_object)
  # Ottengo una lista di azioni, ciascuna delle quali, quando eseguita,
  # permette di disegnare una parte del documento xml all'interno del pdf
  actions_list = get_actions_list(xml_object)

  # "Eseguo" le azioni contenute nella lista
  PdfWritingToolsActions.execute_actions(pdf, actions_list, nil, [])
end

.get_actions_list(xml_object) ⇒ Object

Produce le actions necessarie per disegnare nel PDF l’intero documento XML



38
39
40
41
42
43
44
45
46
# File 'lib/pdf_writing_tools.rb', line 38

def self.get_actions_list(xml_object)
  actions_list = []
  if xml_object.name == 'nothtml'
    xml_object.children.each do |child|
      actions_list += PdfWritingToolsProcess.process_xml_obj(child, [])
    end
  end
  actions_list + PdfWritingToolsActions.tr_action + PdfWritingToolsActions.tr_action + actions_list + actions_list
end

.get_cleaned_xml_from_file(file_path) ⇒ Object

Dato il percorso file_path, genera un documento xml, a cui sono stati rimossi gli a capo e gli spazi multipli



400
401
402
403
404
405
406
407
408
409
410
# File 'lib/pdf_writing_tools.rb', line 400

def self.get_cleaned_xml_from_file(file_path)
  text = File.read(file_path)

  # Rimuove gli a capo e le tabulazioni sostituendoli con uno spazio
  text = text.gsub(/\n|\t/, ' ')

  # Rimuove le spaziature multiple sostituendole con uno spazio
  text = text.gsub(/\s+/, ' ')

  Nokogiri::XML(text)
end