Class: RBPDF

Inherits:
Object
  • Object
show all
Includes:
ActionView::Helpers, Html_colors, Rbpdf, Unicode_data
Defined in:
lib/rbpdf.rb

Overview

This is a Ruby class for generating PDF files on-the-fly without requiring external extensions.

  • This class is a Ruby port of the TCPDF class by Nicola Asuni (www.tcpdf.org).

  • This class is an extension and improvement of the FPDF class by Olivier Plathey (www.fpdf.org).

  • This version contains some changes: [porting to Ruby, support for UTF-8 Unicode, code style and formatting, php documentation (www.phpdoc.org), ISO page formats, minor improvements, image scale factor]

  • TCPDF project (www.tcpdf.org) has been originally derived in 2002 from the Public Domain FPDF class by Olivier Plathey (www.fpdf.org), but now is almost entirely rewritten.

  • To add your own TTF fonts please read /fonts/README.TXT

@name

RBPDF

@@version

5.1.002

@author

Nicola Asuni

@license

www.gnu.org/copyleft/lesser.html LGPL 2.1

Constant Summary collapse

@@version =
"5.1.002"
@@fpdf_charwidths =
{}
@@k_cell_height_ratio =
1.25
@@k_blank_image =
""
@@k_small_ratio =
2/3.0
@@k_path_images =
""
@@k_thai_topchars =
nil

Constants included from Rbpdf

Rbpdf::VERSION

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Rbpdf

#getimagesize

Constructor Details

#initialize(orientation = 'P', unit = 'mm', format = 'A4', unicode = true, encoding = "UTF-8", diskcache = false) ⇒ RBPDF

This is the class constructor. It allows to set up the page format, the orientation and the measure unit used in all the methods (except for the font sizes).

@param string :orientation

page orientation. Possible values are (case insensitive):

  • P or Portrait (default)

  • L or Landscape

@param string :unit

User measure unit. Possible values are:

  • pt: point

  • mm: millimeter (default)

  • cm: centimeter

  • in: inch

A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit.

@param mixed :format

The format used for pages. It can be either: A string indicating the page format:

  • 4A0,2A0,A0,A1,A2,A3,A4 (default),A5,A6,A7,A8,A9,A10

  • B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10

  • C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10

  • RA0,RA1,RA2,RA3,RA4

  • SRA0,SRA1,SRA2,SRA3,SRA4

  • LETTER,LEGAL,EXECUTIVE,FOLIO

An array containing page measures and advanced options: see setPageFormat()

@param boolean :unicode

TRUE means that the input text is unicode (default = true)

@param String :encoding

charset encoding; default is UTF-8

@param boolean :diskcache

if TRUE reduce the RAM memory usage by caching temporary data on filesystem (slower).

@access public

Since:

  • 1.0



244
245
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
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
# File 'lib/rbpdf.rb', line 244

def initialize(orientation = 'P',  unit = 'mm', format = 'A4', unicode = true, encoding = "UTF-8", diskcache = false)
  
  # Set internal character encoding to ASCII#
  #FIXME 2007-05-25 (EJM) Level=0 - 
  # if (respond_to?("mb_internal_encoding") and mb_internal_encoding())
  #   @internal_encoding = mb_internal_encoding();
  #   mb_internal_encoding("ASCII");
  # }

  @@k_path_cache = Rails.root.join('tmp').to_s
  @@k_path_main = Rails.root.join('tmp').to_s
  @@k_path_url = Rails.root.join('tmp').to_s

  # set disk caching
  @diskcache = diskcache ? true : false
 
  # set language direction
  @rtl = false
  @tmprtl = false

  @x ||= 0 
  @y ||= 0 

  #######################
  @offsets ||= []

  @alias_nb_pages = '{nb}'
  @alias_num_page = '{pnb}'
  @img_scale ||= 1
  @r_margin ||= 0
  @l_margin ||= 0
  @page_annots ||= []

  @header_font ||= ['', '', 10]
  @footer_font ||= ['', '', 8]
  @l ||= {}

  @header_margin ||= 10
  @footer_margin ||= 10

  @barcode ||= false
  @print_header ||= true
  @print_footer ||= true
  @header_width ||= 0
  @header_logo ||= ""
  @header_logo_width ||= 30
  @header_title ||= ""
  @header_string ||= ""
  @listordered ||= []
  @listcount ||= []
  @listindent ||= 0
  @listindentlevel ||= 0
  @lispacer ||= ""

  # bookmark
  @outlines ||= []

  # --- javascript and form ---
  @javascript ||= ''
  @js_objects ||= []

  @dpi = 72.0
  @newpagegroup ||= []
  @pagegroups ||= {}
  @visibility ||= 'all'
  @cell_height_ratio = @@k_cell_height_ratio
  @viewer_preferences ||= {}

  @intmrk ||= []
  @cntmrk ||= []
  @footerpos ||= []
  @footerlen ||= []
  @newline ||= true
  @endlinex ||= 0

  @open_marked_content ||= false
  @htmlvspace ||= 0
  @spot_colors ||= {}
  @lisymbol ||= ''
  @epsmarker ||= 'x#!#EPS#!#x'
  @transfmatrix ||= []
  @transfmatrix_key ||= 0
  @booklet ||= false
  @feps ||= 0.005
  @tagvspaces ||= {}
  @customlistindent ||= -1
  @opencell = true
  @embeddedfiles ||= {}

  @html_link_color_array ||= [0, 0, 255]
  @html_link_font_style ||= 'U'
  @numpages ||= 0
  @pagelen ||= []
  @numimages ||= 0
  @imagekeys ||= []
  @bufferlen ||= 0

  @numfonts ||= 0
  @fontkeys ||= []
  @font_obj_ids ||= {}
  @pageopen ||= []
  @default_monospaced_font = 'courier'


  @cache_file_length = {}
  @thead ||= ''
  @thead_margins ||= {}
  @cache_utf8_string_to_array = {}
  @cache_maxsize_utf8_string_to_array = 8
  @cache_size_utf8_string_to_array = 0
  
  @signature_data ||= {}
  @sig_annot_ref ||= '***SIGANNREF*** 0 R'
  @page_obj_id ||= []
  @embedded_start_obj_id ||= 100000
  @form_obj_id ||= []
  @apxo_start_obj_id ||= 400000
  @apxo_obj_id ||= 400000
  @annotation_fonts ||= {}
  @radiobutton_groups ||= []
  @radio_groups ||= []
  @textindent ||= 0
  @nested_table = false

  @start_transaction_y ||= 0
  @in_thead ||= false
  @columns ||= []
  @num_columns ||= 0
  @current_column ||= 0
  @column_start_page ||= 0

  # Text rendering mode: 
  # 0 = Fill text;
  # 1 =            Stroke text;
  # 2 = Fill, then stroke text;
  # 3 = Neither fill nor stroke text (invisible);
  # 4 =              Fill text and add to path for clipping;
  # 5 =            Stroke text and add to path for clipping;
  # 6 = Fill, then stroke text and add to path for clipping;
  # 7 = Add text to path for clipping.
  @textrendermode ||= 0
  @textstrokewidth ||= 0

  @pdfunit ||= 'mm'
  @tocpage ||= false

  #######################

  #Some checks
  dochecks();
  
  begin
    @@decoder = HTMLEntities.new 
  rescue
    @@decoder = nil
  end
  
  #Initialization of properties
  @is_unicode = unicode
  @page ||= 0
  @transfmrk ||= []
  @pagedim ||= []
  @n ||= 2
  if @diskcache
    @buffer ||= nil
  else
    @buffer ||= ''
  end
  @pages ||= []
  @prev_pages ||= []
  @state ||= 0
  @fonts ||= {}
  @font_files ||= {}
  @diffs ||= []
  @images ||= {}
  @links ||= []
  @gradients ||= []
  @in_footer ||= false
  @lasth ||= 0
  @font_family ||= 'helvetica'
  @font_style ||= ''
  @font_size_pt ||= 12
  @underline ||= false
  @overline ||= false
  @linethrough ||= false
  @draw_color ||= '0 G'
  @fill_color ||= '0 g'
  @text_color ||= '0 g'
  @color_flag ||= false

  # encryption values
  @encrypted ||= false
  @last_enc_key ||= ''
   
  # Standard Unicode fonts
  @core_fonts = {
  'courier'=>'Courier',
  'courierB'=>'Courier-Bold',
  'courierI'=>'Courier-Oblique',
  'courierBI'=>'Courier-BoldOblique',
  'helvetica'=>'Helvetica',
  'helveticaB'=>'Helvetica-Bold',
  'helveticaI'=>'Helvetica-Oblique',
  'helveticaBI'=>'Helvetica-BoldOblique',
  'times'=>'Times-Roman',
  'timesB'=>'Times-Bold',
  'timesI'=>'Times-Italic',
  'timesBI'=>'Times-BoldItalic',
  'symbol'=>'Symbol',
  'zapfdingbats'=>'ZapfDingbats'}

  # Set scale factor
  setPageUnit(unit)
  # set page format and orientation
  setPageFormat(format, orientation)
  # Page margins (1 cm)
  margin = 28.35/@k
  SetMargins(margin, margin)
  #Interior cell margin (1 mm)
  @c_margin = margin / 10
  #Line width (0.2 mm)
  @line_width = 0.57 / @k
  @linestyle_width ||= sprintf('%.2f w', (@line_width * @k))
  @linestyle_cap ||= '0 J'
  @linestyle_join ||= '0 j'
  @linestyle_dash ||= '[] 0 d'
  #Automatic page break
  SetAutoPageBreak(true, 2 * margin)
  #Full width display mode
  SetDisplayMode('fullwidth')
  #Compression
  SetCompression(true)
  #Set default PDF version number
  @pdf_version ||= "1.7"
  @encoding = encoding
  @href ||= {}
  @fontlist ||= []
  getFontsList()
  @fgcolor = ActiveSupport::OrderedHash.new
  @fgcolor['R'] = 0
  @fgcolor['G'] = 0
  @fgcolor['B'] = 0
  @strokecolor = ActiveSupport::OrderedHash.new
  @strokecolor['R'] = 0
  @strokecolor['G'] = 0
  @strokecolor['B'] = 0
  @bgcolor = ActiveSupport::OrderedHash.new
  @bgcolor['R'] = 255
  @bgcolor['G'] = 255
  @bgcolor['B'] = 255
  @extgstates ||= []

  # user's rights
  @sign ||= false
  @ur = false
  @ur_document = "/FullSave"
  @ur_annots = "/Create/Delete/Modify/Copy/Import/Export"
  @ur_form = "/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate"
  @ur_signature = "/Modify"

  # set default JPEG quality
  @jpeg_quality ||= 75

  # initialize some settings
#    utf8Bidi([''], '')
  # set default font
  SetFont(@font_family, @font_style, @font_size_pt)

  @annots_start_obj_id ||= 200000
  @annot_obj_id ||= @annots_start_obj_id
  @curr_annot_obj_id ||= @annots_start_obj_id
  @apxo_obj_id ||= @apxo_start_obj_id
end

Instance Attribute Details

#barcodeObject

Returns the value of attribute barcode.



132
133
134
# File 'lib/rbpdf.rb', line 132

def barcode
  @barcode
end

#bufferObject

Returns the value of attribute buffer.



134
135
136
# File 'lib/rbpdf.rb', line 134

def buffer
  @buffer
end

#cache_file_lengthObject

Returns the value of attribute cache_file_length.



210
211
212
# File 'lib/rbpdf.rb', line 210

def cache_file_length
  @cache_file_length
end

#color_flagObject

Returns the value of attribute color_flag.



138
139
140
# File 'lib/rbpdf.rb', line 138

def color_flag
  @color_flag
end

#default_fontObject

Returns the value of attribute default_font.



140
141
142
# File 'lib/rbpdf.rb', line 140

def default_font
  @default_font
end

#diffsObject

Returns the value of attribute diffs.



136
137
138
# File 'lib/rbpdf.rb', line 136

def diffs
  @diffs
end

#diskcacheObject

Returns the value of attribute diskcache.



208
209
210
# File 'lib/rbpdf.rb', line 208

def diskcache
  @diskcache
end

#draw_colorObject

Returns the value of attribute draw_color.



142
143
144
# File 'lib/rbpdf.rb', line 142

def draw_color
  @draw_color
end

#encodingObject

Returns the value of attribute encoding.



144
145
146
# File 'lib/rbpdf.rb', line 144

def encoding
  @encoding
end

#fill_colorObject

Returns the value of attribute fill_color.



146
147
148
# File 'lib/rbpdf.rb', line 146

def fill_color
  @fill_color
end

#font_familyObject

Returns the value of attribute font_family.



150
151
152
# File 'lib/rbpdf.rb', line 150

def font_family
  @font_family
end

#font_filesObject

Returns the value of attribute font_files.



152
153
154
# File 'lib/rbpdf.rb', line 152

def font_files
  @font_files
end

#font_size_ptObject

Returns the value of attribute font_size_pt.



158
159
160
# File 'lib/rbpdf.rb', line 158

def font_size_pt
  @font_size_pt
end

#font_styleObject

Returns the value of attribute font_style.



156
157
158
# File 'lib/rbpdf.rb', line 156

def font_style
  @font_style
end

#fontsObject

Returns the value of attribute fonts.



148
149
150
# File 'lib/rbpdf.rb', line 148

def fonts
  @fonts
end

#header_logoObject

Returns the value of attribute header_logo.



162
163
164
# File 'lib/rbpdf.rb', line 162

def 
  @header_logo
end

#header_logo_widthObject

Returns the value of attribute header_logo_width.



164
165
166
# File 'lib/rbpdf.rb', line 164

def header_logo_width
  @header_logo_width
end

#header_stringObject

Returns the value of attribute header_string.



168
169
170
# File 'lib/rbpdf.rb', line 168

def header_string
  @header_string
end

#header_titleObject

Returns the value of attribute header_title.



166
167
168
# File 'lib/rbpdf.rb', line 166

def header_title
  @header_title
end

#header_widthObject

Returns the value of attribute header_width.



160
161
162
# File 'lib/rbpdf.rb', line 160

def header_width
  @header_width
end

#imagesObject

Returns the value of attribute images.



170
171
172
# File 'lib/rbpdf.rb', line 170

def images
  @images
end

#img_scaleObject

Returns the value of attribute img_scale.



172
173
174
# File 'lib/rbpdf.rb', line 172

def img_scale
  @img_scale
end

Returns the value of attribute in_footer.



174
175
176
# File 'lib/rbpdf.rb', line 174

def in_footer
  @in_footer
end

#is_unicodeObject

Returns the value of attribute is_unicode.



176
177
178
# File 'lib/rbpdf.rb', line 176

def is_unicode
  @is_unicode
end

#lasthObject

Returns the value of attribute lasth.



178
179
180
# File 'lib/rbpdf.rb', line 178

def lasth
  @lasth
end

Returns the value of attribute links.



180
181
182
# File 'lib/rbpdf.rb', line 180

def links
  @links
end

#lispacerObject

Returns the value of attribute lispacer.



186
187
188
# File 'lib/rbpdf.rb', line 186

def lispacer
  @lispacer
end

#listcountObject

Returns the value of attribute listcount.



184
185
186
# File 'lib/rbpdf.rb', line 184

def listcount
  @listcount
end

#listorderedObject

Returns the value of attribute listordered.



182
183
184
# File 'lib/rbpdf.rb', line 182

def listordered
  @listordered
end

#nObject

Returns the value of attribute n.



188
189
190
# File 'lib/rbpdf.rb', line 188

def n
  @n
end

#offsetsObject

Returns the value of attribute offsets.



190
191
192
# File 'lib/rbpdf.rb', line 190

def offsets
  @offsets
end

#pageObject

Returns the value of attribute page.



192
193
194
# File 'lib/rbpdf.rb', line 192

def page
  @page
end

#pagesObject

Returns the value of attribute pages.



194
195
196
# File 'lib/rbpdf.rb', line 194

def pages
  @pages
end

#pdf_versionObject

Returns the value of attribute pdf_version.



196
197
198
# File 'lib/rbpdf.rb', line 196

def pdf_version
  @pdf_version
end

#prev_pagesObject

Returns the value of attribute prev_pages.



212
213
214
# File 'lib/rbpdf.rb', line 212

def prev_pages
  @prev_pages
end

Returns the value of attribute print_footer.



200
201
202
# File 'lib/rbpdf.rb', line 200

def print_footer
  @print_footer
end

Returns the value of attribute print_header.



198
199
200
# File 'lib/rbpdf.rb', line 198

def print_header
  @print_header
end

#stateObject

Returns the value of attribute state.



202
203
204
# File 'lib/rbpdf.rb', line 202

def state
  @state
end

#text_colorObject

Returns the value of attribute text_color.



204
205
206
# File 'lib/rbpdf.rb', line 204

def text_color
  @text_color
end

#underlineObject

Returns the value of attribute underline.



206
207
208
# File 'lib/rbpdf.rb', line 206

def underline
  @underline
end

Instance Method Details

#AcceptPageBreakObject Also known as: accept_page_break

Whenever a page break condition is met, the method is called, and the break is issued or not depending on the returned value. The default implementation returns a value according to the mode selected by SetAutoPageBreak(). This method is called automatically and should not be called directly by the application.

@return boolean
@access public
@since 1.4
@see

SetAutoPageBreak()



3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
# File 'lib/rbpdf.rb', line 3142

def AcceptPageBreak()
  #if @num_columns > 1
  #  # multi column mode
  #  if @current_column < (@num_columns - 1)
  #    # go to next column
  #    selectColumn(@current_column + 1)
  #  else
  #    # add a new page
  #    AddPage()
  #    # set first column
  #    selectColumn(0)
  #  end
  #  # avoid page breaking from checkPageBreak()
  #  return false
  #end
  return @auto_page_break;
end

#AddFont(family, style = '', fontfile = '') ⇒ Object Also known as: add_font

Imports a TrueType, Type1, core, or CID0 font and makes it available. It is necessary to generate a font definition file first with the makefont.rb utility. The definition file (and the font file itself when embedding) must be present either in the current directory or in the one indicated by FPDF_FONTPATH if the constant is defined. If it could not be found, the error “Could not include font definition file” is generated.

Example

:pdf.add_font('Comic','I')
# is equivalent to:
:pdf.add_font('Comic','I','comici.rb')
@param string :family

Font family. The name can be chosen arbitrarily. If it is a standard family name, it will override the corresponding font.

@param string :style

Font style. Possible values are (case insensitive):

  • empty string: regular (default)

  • B: bold

  • I: italic

  • BI or IB: bold italic

@param string :fontfile

The font definition file. By default, the name is built from the family and style, in lower case with no space.

@return array

containing the font data, or false in case of error.

@access public
@since 1.5
@see

SetFont()



2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
# File 'lib/rbpdf.rb', line 2566

def AddFont(family, style='', fontfile='')
  if empty_string(family)
    if !empty_string(@font_family)
      family = @font_family
    else
      Error('Empty font family')
    end
  end

  family = family.downcase
  if ((!@is_unicode) and (family == 'arial'))
    family = 'helvetica';
  end
  if (family == "symbol") or (family == "zapfdingbats")
    style = ''
  end

  tempstyle = style.upcase
  style = ''
  # underline
  if tempstyle.index('U') != nil
    @underline = true
  else
    @underline = false
  end
  # line-through (deleted)
  if tempstyle.index('D') != nil
    @linethrough = true
  else
    @linethrough = false
  end
  # overline
  if tempstyle.index('O') != nil
    @overline = true
  else
    @overline = false
  end
  # bold
  if tempstyle.index('B') != nil
    style << 'B';
  end
  # oblique
  if tempstyle.index('I') != nil
    style << 'I';
  end
  bistyle = style
  fontkey = family + style;
  font_style = style + (@underline ? 'U' : '') + (@linethrough ? 'D' : '') + (@overline ? 'O' : '')
  fontdata = {'fontkey' => fontkey, 'family' => family, 'style' => font_style}
  # check if the font has been already added
  if getFontBuffer(fontkey) != false
    return fontdata
  end

  # get specified font directory (if any)
  fontdir = false
  if !empty_string(fontfile)
    fontdir = File.dirname(fontfile)
    if empty_string(fontdir) or (fontdir == '.')
      fontdir = ''
    else
      fontdir << '/'
    end
  end

  # search and include font file
  if empty_string(fontfile)
    # build a standard filenames for specified font
    fontfile1 = family.gsub(' ', '') + style.downcase + '.rb'
    fontfile2 = family.gsub(' ', '') + '.rb'
    # search files on various directories
    if (fontdir != false) and File.exists?(fontdir + fontfile1)
      fontfile = fontdir + fontfile1
      fontname = fontfile1
    elsif fontfile = getfontpath(fontfile1)
      fontname = fontfile1
    elsif File.exists?(fontfile1)
      fontfile = fontfile1
      fontname = fontfile1
    elsif (fontdir != false) and File.exists?(fontdir + fontfile2)
      fontfile = fontdir + fontfile2
      fontname = fontfile2
    elsif fontfile = getfontpath(fontfile2)
      fontname = fontfile2
    else
      fontfile = fontfile2
      fontname = fontfile2
    end
  end

  # include font file
  if File.exists?(fontfile)
    require(fontfile)
  else
    Error('Could not include font definition file: ' + family + '')
  end

  font_desc = RBPDFFontDescriptor.font(fontname)
  if font_desc[:desc].nil?
    desc = {}
  else
    desc = font_desc[:desc].dup
  end

  # check font parameters
  if font_desc[:type].nil? or font_desc[:cw].nil?
    Error('The font definition file has a bad format: ' + fontfile + '')
  end

  # SET default parameters
  font_desc[:file] ||= ''
  font_desc[:enc] ||= ''
  if font_desc[:cidinfo].nil?
    font_desc[:cidinfo] = {'Registry'=>'Adobe', 'Ordering'=>'Identity', 'Supplement'=>0}
    font_desc[:cidinfo]['uni2cid'] = {}
  end
  font_desc[:ctg] ||= ''
  font_desc[:up] ||= -100
  font_desc[:ut] ||= 50
  font_desc[:cw] ||= {}

  if empty_string(font_desc[:dw])
    # set default width
    if !desc['MissingWidth'].nil? and (desc['MissingWidth'] > 0)
      font_desc[:dw] = desc['MissingWidth']
    elsif font_desc[:cw][32]
      font_desc[:dw] = font_desc[:cw][32]
    else
      font_desc[:dw] = 600
    end
  end

  @numfonts += 1
  if font_desc[:type] == 'cidfont0'
    #  register CID font (all styles at once)
    styles = {'' => '', 'B' => ',Bold', 'I' => ',Italic', 'BI' => ',BoldItalic'}
    sname = font_desc[:name] + styles[bistyle]
    # artificial bold
    if bistyle.index('B') != nil
      if desc['StemV']
        desc['StemV'] *= 2
      else
        desc['StemV'] = 120
      end
    end
    # artificial italic
    if bistyle.index('I') != nil
      if desc['ItalicAngle']
        desc['ItalicAngle'] -= 11
      else
        desc['ItalicAngle'] = -11 
      end
    end
    setFontBuffer(fontkey, {'i' => @numfonts, 'type' => font_desc[:type], 'name' => sname, 'desc' => desc, 'cidinfo' => font_desc[:cidinfo], 'up' => font_desc[:up], 'ut' => font_desc[:ut], 'cw' => font_desc[:cw], 'dw' => font_desc[:dw], 'enc' => font_desc[:enc]})
  elsif font_desc[:type] == 'core'
    font_desc[:name] = @core_fonts[fontkey]
  elsif (font_desc[:type] == 'TrueType') or (font_desc[:type] == 'Type1')
    # ...
  elsif font_desc[:type] == 'TrueTypeUnicode'
    font_desc[:enc] = 'Identity-H'
  else
    Error('Unknow font type: ' + type + '')
  end
  setFontBuffer(fontkey, {'i' => @numfonts, 'type' => font_desc[:type], 'name' => font_desc[:name], 'desc' => desc, 'up' => font_desc[:up], 'ut' => font_desc[:ut], 'cw' => font_desc[:cw], 'dw' => font_desc[:dw], 'enc' => font_desc[:enc], 'cidinfo' => font_desc[:cidinfo], 'file' => font_desc[:file], 'ctg' => font_desc[:ctg]})

  if (!font_desc[:diff].nil? and (!font_desc[:diff].empty?))
    #Search existing encodings
    d=0;
    nb=@diffs.length;
    1.upto(nb) do |i|
      if (@diffs[i]== font_desc[:diff])
        d = i;
        break;
      end
    end
    if (d==0)
      d = nb+1;
      @diffs[d] = font_desc[:diff];
    end
    setFontSubBuffer(fontkey, 'diff', d)
  end
  if !empty_string(font_desc[:file])
    if (font_desc[:type] == 'TrueType') or (font_desc[:type] == 'TrueTypeUnicode')
      @font_files[font_desc[:file]] = {'length1' => font_desc[:originalsize], 'fontdir' => fontdir}
    elsif font_desc[:type] != 'core'
      @font_files[font_desc[:file]] = {'length1' => font_desc[:size1], 'length2' => font_desc[:size2], 'fontdir' => fontdir}
    end
  end
  return fontdata
end

Output anchor link.

@param string :url

link URL or internal link (i.e.: <a href=“#23”>link to page 23</a>)

@param string :name

link name

@param int :fill

Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.

@param boolean :firstline

if true prints only the first line and return the remaining string.

@param array :color

array of RGB text color

@param string :style

font style (U, D, B, I)

@param boolean :firstblock

if true the string is the starting of a line.

@return

the number of cells used or the remaining text if :firstline = true

@access public


7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
# File 'lib/rbpdf.rb', line 7914

def addHtmlLink(url, name, fill=0, firstline=false, color='', style=-1, firstblock=false)
  if !empty_string(url) and (url[0, 1] == '#')
    # convert url to internal link
    page = url.sub(/^#/, "").to_i
    url = AddLink()
    SetLink(url, 0, page)
  end
  # store current settings
  prevcolor = @fgcolor
  prevstyle = @font_style
  if color.empty?
    SetTextColorArray(@html_link_color_array)
  else
    SetTextColorArray(color)
  end
  if style == -1
    SetFont('', @font_style + @html_link_font_style)
  else
    SetFont('', @font_style + style)
  end
  ret = Write(@lasth, name, url, fill, '', false, 0, firstline, firstblock, 0)
  # restore settings
  SetFont('', prevstyle)
  SetTextColorArray(prevcolor)
  return ret
end

#addHTMLTOC(page = '', toc_name = 'TOC', templates = [], correct_align = true) ⇒ Object Also known as: add_html_toc

Output a Table Of Content Index (TOC) using HTML templates. Before calling this method you have to open the page using the addTOCPage() method. After calling this method you have to call endTOCPage() to close the TOC page.

@param int :page

page number where this TOC should be inserted (leave empty for current page).

@param string :toc_name

name to use for TOC bookmark.

@param array :templates

array of html templates. Use: #TOC_DESCRIPTION# for bookmark title, #TOC_PAGE_NUMBER# for page number.

@parma boolean :correct_align

if true correct the number alignment (numbers must be in monospaced font like courier and right aligned on LTR, or left aligned on RTL)

@access public
@author

Nicola Asuni

@since 5.0.001 (2010-05-06)
@see

addTOCPage(), endTOCPage(), addTOC()



14183
14184
14185
14186
14187
14188
14189
14190
14191
14192
14193
14194
14195
14196
14197
14198
14199
14200
14201
14202
14203
14204
14205
14206
14207
14208
14209
14210
14211
14212
14213
14214
14215
14216
14217
14218
14219
14220
14221
14222
14223
14224
14225
14226
14227
14228
14229
14230
14231
14232
14233
14234
14235
14236
14237
14238
14239
14240
14241
14242
14243
14244
14245
14246
14247
14248
14249
14250
14251
14252
14253
14254
14255
14256
14257
14258
14259
14260
14261
14262
14263
14264
14265
14266
14267
14268
14269
14270
14271
# File 'lib/rbpdf.rb', line 14183

def addHTMLTOC(page='', toc_name='TOC', templates=[], correct_align=true)
  prev_htmlLinkColorArray = @html_link_color_array
  prev_htmlLinkFontStyle = @html_link_font_style
  # set new style for link
  @html_link_color_array = []
  @html_link_font_style = ''
  page_first = getPage()
  @outlines.each_with_index do |outline, key|
    if empty_string(page)
      pagenum = outline[:p].to_s
    else 
      # placemark to be replaced with the correct number
      pagenum = '{#' + outline[:p].to_s + '}'
      if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
        pagenum = '{' + pagenum + '}'
      end
    end
    # get HTML template
    row = templates[outline[:l]]
    # replace templates with current values
    row = row.gsub('#TOC_DESCRIPTION#', outline[:t])
    row = row.gsub('#TOC_PAGE_NUMBER#', pagenum)
    # add link to page
    row = '<a href="#' + outline[:p].to_s + '">' + row + '</a>'
    # write bookmark entry
    writeHTML(row, false, false, true, false, '')
  end
  # restore link styles
  @html_link_color_array = prev_htmlLinkColorArray
  @html_link_font_style = prev_htmlLinkFontStyle
  # move TOC page and replace numbers
  page_last = getPage()
  numpages = page_last - page_first + 1
  if !empty_string(page)
    page_first.upto(page_last) do |p|
      # get page data
      temppage = getPageBuffer(p)
      1.upto(@numpages) do |n|
        # update page numbers
        k = '{#' + n.to_s + '}'
        ku = '{' + k + '}'
        alias_a = escape(k)
        alias_au = escape('{' + k + '}')
        if @is_unicode
          alias_b = escape(UTF8ToLatin1(k))
          alias_bu = escape(UTF8ToLatin1(ku))
          alias_c = escape(utf8StrRev(k, false, @tmprtl))
          alias_cu = escape(utf8StrRev(ku, false, @tmprtl))
        end
        if n >= page
          np = n + numpages
        else
          np = n
        end
        ns = formatTOCPageNumber(np)
        nu = ns
        if correct_align
          sdiff = k.length - ns.length
          sdiffu = ku.length - ns.length
          sfill = ' ' * sdiff
          sfillu = ' ' * sdiffu
          if @rtl 
            ns = ns + sfill
            nu = nu + sfillu
          else
            ns = sfill + ns
            nu = sfillu + nu
          end
        end
        nu = UTF8ToUTF16BE(nu, false)
        temppage = temppage.gsub(alias_au, nu)
        if @is_unicode
          temppage = temppage.gsub(alias_bu, nu)
          temppage = temppage.gsub(alias_cu, nu)
          temppage = temppage.gsub(alias_b, ns)
          temppage = temppage.gsub(alias_c, ns)
        end
        temppage = temppage.gsub(alias_a, ns)
      end
      # save changes
      setPageBuffer(p, temppage)
    end
    # move pages
    Bookmark(toc_name, 0, 0, page_first)
    0.upto(numpages - 1) do |i|
      movePage(page_last, page)
    end
  end
end

Creates a new internal link and returns its identifier. An internal link is a clickable area which directs to another place within the document. The identifier can then be passed to Cell(), Write(), Image() or Link(). The destination is defined with SetLink().

@access public
@since 1.5
@see

Cell(), Write(), Image(), Link(), SetLink()



2904
2905
2906
2907
2908
2909
# File 'lib/rbpdf.rb', line 2904

def AddLink()
  #Create a new internal link
  n=@links.length+1;
  @links[n]=[0,0];
  return n;
end

#AddPage(orientation = '', format = '', keepmargins = false, tocpage = false) ⇒ Object Also known as: add_page

Adds a new page to the document. If a page is already present, the Footer() method is called first to output the footer (if enabled). Then the page is added, the current position set to the top-left corner according to the left and top margins (or top-right if in RTL mode), and Header() is called to display the header (if enabled). The origin of the coordinate system is at the top-left corner (or top-right for RTL) and increasing ordinates go downwards.

@param string :orientation

page orientation. Possible values are (case insensitive):

  • P or PORTRAIT (default)

  • L or LANDSCAPE

@param mixed :format

The format used for pages. It can be either: A string indicating the page format:

  • 4A0,2A0,A0,A1,A2,A3,A4 (default),A5,A6,A7,A8,A9,A10

  • B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10

  • C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10

  • RA0,RA1,RA2,RA3,RA4

  • SRA0,SRA1,SRA2,SRA3,SRA4

  • LETTER,LEGAL,EXECUTIVE,FOLIO

An array containing page measures and advanced options: see setPageFormat()

@param boolean :keepmargins

if true overwrites the default page margins with the current margin

@param boolean :tocpage

if true set the tocpage state to true (the added page will be used to display Table Of Content).

@access public
@since 1.0
@see

startPage, endPage(), addTOCPage(), endTOCPage()



1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
# File 'lib/rbpdf.rb', line 1643

def AddPage(orientation='', format='', keepmargins=false, tocpage=false)
  if @original_l_margin.nil? or keepmargins
    @original_l_margin = @l_margin
  end
  if @original_r_margin.nil? or keepmargins
    @original_r_margin = @r_margin
  end
  # terminate previous page
  endPage()
  # start new page
  startPage(orientation, format, tocpage)
end

#AddSpotColor(name, c, m, y, k) ⇒ Object Also known as: add_spot_color

Defines a new spot color. It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

@param int :c

Cyan color for CMYK. Value between 0 and 255

@param int :m

Magenta color for CMYK. Value between 0 and 255

@param int :y

Yellow color for CMYK. Value between 0 and 255

@param int :k

Key (Black) color for CMYK. Value between 0 and 255

@access public
@since 4.0.024 (2008-09-12)
@see

SetDrawSpotColor(), SetFillSpotColor(), SetTextSpotColor()



2159
2160
2161
2162
2163
2164
# File 'lib/rbpdf.rb', line 2159

def AddSpotColor(name, c, m, y, k)
  if @spot_colors[name].nil?
    i = 1 + @spot_colors.length
    @spot_colors[name] = {'i' => i, 'c' => c, 'm' => m, 'y' => y, 'k' => k}
  end
end

#addTOC(page = '', numbersfont = '', filler = '.', toc_name = 'TOC') ⇒ Object Also known as: add_toc

Output a Table of Content Index (TOC). Before calling this method you have to open the page using the addTOCPage() method. After calling this method you have to call endTOCPage() to close the TOC page. You can override this method to achieve different styles.

@param int :page

page number where this TOC should be inserted (leave empty for current page).

@param string :numbersfont

set the font for page numbers (please use monospaced font for better alignment).

@param string :filler

string used to fill the space between text and page number.

@param string :toc_name

name to use for TOC bookmark.

@access public
@author

Nicola Asuni

@since 4.5.000 (2009-01-02)
@see

addTOCPage(), endTOCPage(), addHTMLTOC()



14032
14033
14034
14035
14036
14037
14038
14039
14040
14041
14042
14043
14044
14045
14046
14047
14048
14049
14050
14051
14052
14053
14054
14055
14056
14057
14058
14059
14060
14061
14062
14063
14064
14065
14066
14067
14068
14069
14070
14071
14072
14073
14074
14075
14076
14077
14078
14079
14080
14081
14082
14083
14084
14085
14086
14087
14088
14089
14090
14091
14092
14093
14094
14095
14096
14097
14098
14099
14100
14101
14102
14103
14104
14105
14106
14107
14108
14109
14110
14111
14112
14113
14114
14115
14116
14117
14118
14119
14120
14121
14122
14123
14124
14125
14126
14127
14128
14129
14130
14131
14132
14133
14134
14135
14136
14137
14138
14139
14140
14141
14142
14143
14144
14145
14146
14147
14148
14149
14150
14151
14152
14153
14154
14155
14156
14157
14158
14159
14160
14161
14162
14163
14164
14165
14166
14167
# File 'lib/rbpdf.rb', line 14032

def addTOC(page='', numbersfont='', filler='.', toc_name='TOC')
  fontsize = @font_size_pt
  fontfamily = @font_family
  fontstyle = @font_style
  w = @w - @l_margin - @r_margin
  spacer = GetStringWidth(32.chr) * 4
  page_first = getPage()
  lmargin = @l_margin
  rmargin = @r_margin
  x_start = GetX()
  if empty_string(numbersfont)
    numbersfont = @default_monospaced_font
  end
  if empty_string(filler)
    filler = ' '
  end
  if empty_string(page)
    gap = ' '
  else
    gap = ''
  end
  @outlines.each_with_index do |outline, key|
    if @rtl
      aligntext = 'R'
      alignnum = 'L'
    else
      aligntext = 'L'
      alignnum = 'R'
    end
    if outline[:l] == 0
      SetFont(fontfamily, fontstyle + 'B', fontsize)
    else
      SetFont(fontfamily, fontstyle, fontsize - outline[:l])
    end
    indent = spacer * outline[:l]
    if @rtl
      @r_margin += indent
      @x -= indent
    else
      @l_margin += indent
      @x += indent
    end
    link = AddLink()
    SetLink(link, 0, outline[:p])
    # write the text
    Write(0, outline[:t], link, 0, aligntext, false, 0, false, false, 0)
    SetFont(numbersfont, fontstyle, fontsize)
    if empty_string(page)
      pagenum = outline[:p]
    else
      # placemark to be replaced with the correct number
      pagenum = '{#' + outline[:p].to_s + '}'
      if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
        pagenum = '{' + pagenum + '}'
      end
    end
    numwidth = GetStringWidth(pagenum)
    if @rtl
      tw = @x - @l_margin
    else
      tw = @w - @r_margin - @x
    end
    fw = tw - numwidth - GetStringWidth(32.chr)
    numfills = (fw / GetStringWidth(filler)).floor
    if numfills > 0
      rowfill = filler * numfills
    else
      rowfill = ''
    end
    if @rtl
      pagenum = pagenum + gap + rowfill + ' '
    else
      pagenum = ' ' + rowfill + gap + pagenum
    end
    # write the number
    Cell(tw, 0, pagenum, 0, 1, alignnum, 0, link, 0)
    SetX(x_start)
    @l_margin = lmargin
    @r_margin = rmargin
  end
  page_last = getPage()
  numpages = page_last - page_first + 1
  if !empty_string(page)
    page_first.upto(page_last) do |p|
      # get page data
      temppage = getPageBuffer(p)
      1.upto(@numpages) do |n|
        # update page numbers
        k = '{#' + n.to_s + '}'
        ku = '{' + k + '}'
        alias_a = escape(k)
        alias_au = escape('{' + k + '}')
        if @is_unicode
          alias_b = escape(UTF8ToLatin1(k))
          alias_bu = escape(UTF8ToLatin1(ku))
          alias_c = escape(utf8StrRev(k, false, @tmprtl))
          alias_cu = escape(utf8StrRev(ku, false, @tmprtl))
        end
        if n >= page
          np = n + numpages
        else
          np = n
        end
        ns = formatTOCPageNumber(np)
        nu = ns
        sdiff = k.length - ns.length - 1
        sdiffu = ku.length - ns.length - 1
        sfill = filler * sdiff
        sfillu = filler * sdiffu
        if @rtl
          ns = ns + ' ' + sfill
          nu = nu + ' ' + sfillu
        else
          ns = sfill + ' ' + ns
          nu = sfillu + ' ' + nu
        end
        nu = UTF8ToUTF16BE(nu, false)
        temppage = temppage.gsub(alias_au, nu)
        if @is_unicode
          temppage = temppage.gsub(alias_bu, nu)
          temppage = temppage.gsub(alias_cu, nu)
          temppage = temppage.gsub(alias_b, ns)
          temppage = temppage.gsub(alias_c, ns)
        end
        temppage = temppage.gsub(alias_a, ns)
      end
      # save changes
      setPageBuffer(p, temppage)
    end
    # move pages
    Bookmark(toc_name, 0, 0, page_first)
    0.upto(numpages - 1) do |i|
      movePage(page_last, page)
    end
  end
end

#addTOCPage(orientation = '', format = '', keepmargins = false) ⇒ Object Also known as: add_toc_page

Adds a new TOC (Table Of Content) page to the document.

@param string :orientation

page orientation.

@param boolean :keepmargins

if true overwrites the default page margins with the current margins

@access public
@since 5.0.001 (2010-05-06)
@see

AddPage(), startPage(), endPage(), endTOCPage()



1605
1606
1607
# File 'lib/rbpdf.rb', line 1605

def addTOCPage(orientation='', format='', keepmargins=false)
  AddPage(orientation, format, keepmargins, true)
end

#AliasNbPages(alias_nb = '{nb}') ⇒ Object Also known as: alias_nb_pages

Defines an alias for the total number of pages. It will be substituted as the document is closed.

@param string :alias

The alias.

@access public
@since 1.4
@see

getAliasNbPages(), PageNo(), Footer()



9707
9708
9709
# File 'lib/rbpdf.rb', line 9707

def AliasNbPages(alias_nb ='{nb}')
  @alias_nb_pages = alias_nb
end

#AliasNumPage(alias_num = '{pnb}') ⇒ Object Also known as: alias_num_page

Defines an alias for the page number. It will be substituted as the document is closed.

@param string :alias

The alias.

@access public
@since 4.5.000 (2009-01-02)
@see

getAliasNbPages(), PageNo(), Footer()



9736
9737
9738
9739
# File 'lib/rbpdf.rb', line 9736

def AliasNumPage(alias_num='{pnb}')
  # Define an alias for total number of pages
  @alias_num_page = alias_num
end

#Annotation(x, y, w, h, text, opt = {'Subtype'=>'Text'}, spaces = 0) ⇒ Object Also known as: annotation

Puts a markup annotation on a rectangular area of the page.

  • !!!!THE ANNOTATION SUPPORT IS NOT YET FULLY IMPLEMENTED !!!!

@param float :x

Abscissa of the upper-left corner of the rectangle

@param float :y

Ordinate of the upper-left corner of the rectangle

@param float :w

Width of the rectangle

@param float :h

Height of the rectangle

@param mixed :text

annotation text or alternate content

@param array :opt

array of options (see section 8.4 of PDF reference 1.7).

@param int :spaces

number of spaces on the text to link

@access public
@since 4.0.018 (2008-08-06)


2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
# File 'lib/rbpdf.rb', line 2963

def Annotation(x, y, w, h, text, opt={'Subtype'=>'Text'}, spaces=0)
  x = @x if x == ''
  y = @y if y == ''

  # recalculate coordinates to account for graphic transformations
  if !@transfmatrix.nil?
    @transfmatrix_key.downto(1) do |i|
      maxid = @transfmatrix[i].length - 1
      maxid.downto(0) do |j|
        ctm = @transfmatrix[i][j]
        if !ctm['a'].nil?
          x = x * @k
          y = (@h - y) * @k
          w = w * @k
          h = h * @k
          # top left
          xt = x
          yt = y
          x1 = (ctm['a'] * xt) + (ctm['c'] * yt) + ctm['e']
          y1 = (ctm['b'] * xt) + (ctm['d'] * yt) + ctm['f']
          # top right
          xt = x + w
          yt = y
          x2 = (ctm['a'] * xt) + (ctm['c'] * yt) + ctm['e']
          y2 = (ctm['b'] * xt) + (ctm['d'] * yt) + ctm['f']
          # bottom left
          xt = x
          yt = y - h
          x3 = (ctm['a'] * xt) + (ctm['c'] * yt) + ctm['e']
          y3 = (ctm['b'] * xt) + (ctm['d'] * yt) + ctm['f']
          # bottom right
          xt = x + w
          yt = y - h
          x4 = (ctm['a'] * xt) + (ctm['c'] * yt) + ctm['e']
          y4 = (ctm['b'] * xt) + (ctm['d'] * yt) + ctm['f']
          # new coordinates (rectangle area)
          x = [x1, x2, x3, x4].min
          y = [y1, y2, y3, y4].max
          w = ([x1, x2, x3, x4].max - x) / @k
          h = (y - [y1, y2, y3, y4].min) / @k
          x = x / @k
          y = @h - (y / @k)
        end
      end
    end
  end
  if @page <= 0
    page = 1
  else
    page = @page
  end
  @page_annots[page] ||= []
  @page_annots[page].push 'x' => x, 'y' => y, 'w' => w, 'h' => h, 'txt' => text, 'opt' => opt, 'numspaces' => spaces
  if ((opt['Subtype'] == 'FileAttachment') or (opt['Subtype'] == 'Sound')) and !empty_string(opt['FS']) and File.exist?(opt['FS']) and @embeddedfiles[File.basename(opt['FS'])].nil?
    @embeddedfiles[File.basename(opt['FS'])] = {'file' => opt['FS'], 'n' => (@embeddedfiles.length + @embedded_start_obj_id)}
  end
  # Add widgets annotation's icons
  if opt['mk'] and opt['mk']['i'] and File.exist?(opt['mk']['i'])
    Image(opt['mk']['i'], '', '', 10, 10, '', '', '', false, 300, '', false, false, 0, false, true)
  end
  if opt['mk'] and opt['mk']['ri'] and File.exist?(opt['mk']['ri'])
    Image(opt['mk']['ri'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true)
  end
  if opt['mk'] and opt['mk']['ix'] and File.exist?(opt['mk']['ix'])
    Image(opt['mk']['ix'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true)
  end
  @annot_obj_id += 1
end

#Arrow(x0, y0, x1, y1, head_style = 0, arm_size = 5, arm_angle = 15) ⇒ Object Also known as: arrow

Draws a grahic arrow.

@parameter float :x0

Abscissa of first point.

@parameter float :y0

Ordinate of first point.

@parameter float :x0

Abscissa of second point.

@parameter float :y1

Ordinate of second point.

@parameter int :head_style

(0 = draw only arrowhead arms, 1 = draw closed arrowhead, but no fill, 2 = closed and filled arrowhead, 3 = filled arrowhead)

@parameter float :arm_size

length of arrowhead arms

@parameter int :arm_angle

angle between an arm and the shaft

@author

Piotr Galecki, Nicola Asuni, Andy Meier

@access public
@since 4.6.018 (2009-07-10)


8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938
8939
8940
8941
8942
8943
8944
8945
8946
8947
8948
8949
8950
8951
8952
8953
8954
8955
8956
8957
8958
8959
8960
8961
8962
8963
8964
8965
8966
8967
8968
# File 'lib/rbpdf.rb', line 8927

def Arrow(x0, y0, x1, y1, head_style=0, arm_size=5, arm_angle=15)
  # getting arrow direction angle
  # 0 deg angle is when both arms go along X axis. angle grows clockwise.
  dir_angle = ::Math.atan2(y0 - y1, x0 - x1)
  if dir_angle < 0
    dir_angle += 2 * ::Math::PI
  end
  arm_angle = arm_angle * ::Math::PI / 180 # deg2rad
  sx1 = x1
  sy1 = y1
  if head_style > 0
    # calculate the stopping point for the arrow shaft
    sx1 = x1 + (arm_size - @line_width) * ::Math.cos(dir_angle)
    sy1 = y1 + (arm_size - @line_width) * ::Math.sin(dir_angle)
  end
  # main arrow line / shaft
  Line(x0, y0, sx1, sy1)
  # left arrowhead arm tip
  x2L = x1 + (arm_size * ::Math.cos(dir_angle + arm_angle))
  y2L = y1 + (arm_size * ::Math.sin(dir_angle + arm_angle))
  # right arrowhead arm tip
  x2R = x1 + (arm_size * ::Math.cos(dir_angle - arm_angle))
  y2R = y1 + (arm_size * ::Math.sin(dir_angle - arm_angle))
  mode = 'D'
  style = []
  case head_style
  when 0
    # draw only arrowhead arms
    mode = 'D'
    style = [1, 1, 0]
  when 1
    # draw closed arrowhead, but no fill
    mode = 'D'
  when 2
    # closed and filled arrowhead
    mode = 'DF'
  when 3
    # filled arrowhead
    mode = 'F'
  end
  Polygon([x2L, y2L, x1, y1, x2R, y2R], mode, style, nil)
end

#Bookmark(txt, level = 0, y = -1,, page = nil) ⇒ Object Also known as: bookmark

Adds a bookmark.

@param string :txt

bookmark description.

@param int :level

bookmark level.

@param float :y

Ordinate of the boorkmark position (default = -1 = current position).

@param int :page

target page number (leave empty for current page).

@access public
@author

Olivier Plathey, Nicola Asuni

@since 2.1.002 (2008-02-12)


9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
# File 'lib/rbpdf.rb', line 9593

def Bookmark(txt, level=0, y=-1, page=nil)
  if level < 0
    level = 0
  end
  if @outlines[0]
    lastoutline = @outlines[-1]
    maxlevel = lastoutline[:l] + 1
  else
    maxlevel = 0
  end
  if level > maxlevel
    level = maxlevel
  end
  if y == -1
    y = GetY()
  end
  if page.nil?
    page = PageNo()
  end
  @outlines.push :t => txt, :l => level, :y => y, :p => page
end

#BreakThePage?(h) ⇒ Boolean Also known as: break_the_page?

Returns:

  • (Boolean)


3208
3209
3210
3211
3212
3213
3214
3215
# File 'lib/rbpdf.rb', line 3208

def BreakThePage?(h)
  warn "[DEPRECATION] 'BreakThePage/break_the_page' is deprecated. Please don't Use."
  if ((@y + h) > @page_break_trigger and !@in_footer and AcceptPageBreak())
    true
  else
    false
  end
end

#Cell(w, h = 0, txt = '', border = 0, ln = 0, align = '', fill = 0, link = nil, stretch = 0, ignore_min_height = false, calign = 'T', valign = 'M') ⇒ Object Also known as: cell

Prints a cell (rectangular area) with optional borders, background color and character string. The upper-left corner of the cell corresponds to the current position. The text can be aligned or centered. After the call, the current position moves to the right or to the next line. It is possible to put a link on the text. If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.

@param float :w

Cell width. If 0, the cell extends up to the right margin.

@param float :h

Cell height. Default value: 0.

@param string :txt

String to print. Default value: empty string.

@param mixed :border

Indicates if borders must be drawn around the cell. The value can be either a number:

  • 0: no border (default)

  • 1: frame

or a string containing some or all of the following characters (in any order):

  • L: left

  • T: top

  • R: right

  • B: bottom

@param int :ln

Indicates where the current position should go after the call. Possible values are:

  • 0: to the right

  • 1: to the beginning of the next line

  • 2: below

Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.

@param string :align

Allows to center or align the text. Possible values are:

  • L or empty string: left align (default value)

  • C: center

  • R: right align

@param int :fill

Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.

@param mixed :link

URL or identifier returned by AddLink().

@param int :stretch

stretch carachter mode:

  • 0 = disabled

  • 1 = horizontal scaling only if necessary

  • 2 = forced horizontal scaling

  • 3 = character spacing only if necessary

  • 4 = forced character spacing

@param boolean :ignore_min_height

if true ignore automatic minimum height value.

@param string :calign

cell vertical alignment relative to the specified Y value. Possible values are:

  • T : cell top

  • C : center

  • B : cell bottom

  • A : font top

  • L : font baseline

  • D : font bottom

@param string :valign

text vertical alignment inside the cell. Possible values are:

  • T : top

  • M : middle

  • B : bottom

@access public
@since 1.0
@see

SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), AddLink(), Ln(), MultiCell(), Write(), SetAutoPageBreak()



3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
# File 'lib/rbpdf.rb', line 3271

def Cell(w, h=0, txt='', border=0, ln=0, align='', fill=0, link=nil, stretch=0, ignore_min_height=false, calign='T', valign='M')
  if !ignore_min_height
    min_cell_height = @font_size * @cell_height_ratio
    if h < min_cell_height
      h = min_cell_height
    end
  end
  checkPageBreak(h)
  out(getCellCode(w, h, txt, border, ln, align, fill, link, stretch, ignore_min_height, calign, valign))
end

#Circle(x0, y0, r, angstr = 0, angend = 360, style = '', line_style = nil, fill_color = nil, nc = 2) ⇒ Object Also known as: circle

Draws a circle. A circle is formed from n Bezier curves.

@param float :x0

Abscissa of center point.

@param float :y0

Ordinate of center point.

@param float :r

Radius.

@param float :angstr

Angle start of draw line. Default value: 0.

@param float :angend

Angle finish of draw line. Default value: 360.

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param array :line_style

Line style of circle. Array like for SetLineStyle SetLineStyle. Default value: default line style (empty array).

@param array :fill_color

Fill color. Format: array(red, green, blue). Default value: default color (empty array).

@param integer :nc

Number of curves used to draw a 90 degrees portion of circle.

@access public
@since 2.1.000 (2008-01-08)


8605
8606
8607
# File 'lib/rbpdf.rb', line 8605

def Circle(x0, y0, r, angstr=0, angend=360, style='', line_style=nil, fill_color=nil, nc=2)
  Ellipse(x0, y0, r, r, 0, angstr, angend, style, line_style, fill_color, nc)
end

#CloseObject

Terminates the PDF document. It is not necessary to call this method explicitly because Output() does it automatically. If the document contains no page, AddPage() is called to prevent from getting an invalid document.

@since 1.0
@see

Open(), Output()



1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
# File 'lib/rbpdf.rb', line 1481

def Close()
  #Terminate document
  if (@state==3)
    return;
  end
  if (@page==0)
    AddPage();
  end
  # close page
  endPage()
  lastPage()
  @state = 2
  SetAutoPageBreak(false)
  @y = @h - (1 / @k)
  @r_margin = 0
  out('q')
  setVisibility('screen')
  SetFont('helvetica', '', 1)
  SetTextColor(127,127,127)
  setAlpha(0)
  msg = "\x50\x6f\x77\x65\x72\x65\x64\x20\x62\x79\x20\x54\x43\x50\x44\x46\x20\x28\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29"
  lnk = "\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67"
  Cell(0, 0, msg, 0, 0, 'R', 0, lnk, 0, false, 'D', 'B')
  out('Q')
  setVisibility('all')
  @state = 1
  # close document
  enddoc();
end

#commitTransactionObject Also known as: commit_transaction

Delete the copy of the current RBPDF object used for undo operation.

@access public
@since 4.5.029 (2009-03-19)


14297
14298
14299
14300
14301
14302
14303
14304
14305
14306
14307
14308
14309
# File 'lib/rbpdf.rb', line 14297

def commitTransaction()
  if @objcopy
    if @objcopy.diskcache
      @prev_pages.compact.each do |file|
        File.delete(file.path)
      end
      @prev_pages = []
    end

    @objcopy.destroy(true, true)
    @objcopy = nil
  end
end

#convertHTMLColorToDec(color = "#FFFFFF") ⇒ Object Also known as: convert_html_color_to_dec

Returns an associative array (keys: R,G,B) from an html color name or a six-digit or three-digit hexadecimal color representation (i.e. #3FE5AA or #7FF).

@param string :color

html color

@return array

RGB color or empty array in case of error.

@access public


7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
# File 'lib/rbpdf.rb', line 7948

def convertHTMLColorToDec(color = "#FFFFFF")
  color = color.gsub(/[\s]*/, '') # remove extra spaces
  color = color.downcase
  if !(dotpos = color.index('.')).nil?
    # remove class parent (i.e.: color.red)
    color = color[(dotpos + 1)..-1]
  end
  if color.length == 0
    return []
  end
  returncolor = ActiveSupport::OrderedHash.new
  #  RGB ARRAY
  if color[0,3] == 'rgb' 
    codes = color.sub(/^rgb\(/, '')
    codes = codes.gsub(')', '')
    returncolor = codes.split(',', 3)
    returncolor[0] = returncolor[0].to_i
    returncolor[1] = returncolor[1].to_i
    returncolor[2] = returncolor[2].to_i
    return returncolor
  end
  # CMYK ARRAY
  if color[0,4] == 'cmyk' 
    codes = color.sub(/^cmyk\(/, '')
    codes = codes.gsub(')', '')
    returncolor[0] = returncolor[0].to_i
    returncolor[1] = returncolor[1].to_i
    returncolor[2] = returncolor[2].to_i
    returncolor[3] = returncolor[3].to_i
    return returncolor
  end
  # COLOR NAME
  if color[0].chr != "#"
    # decode color name
    if @@webcolor[color]
      color_code = @@webcolor[color]
    else
      return []
    end
  else
    color_code = color.sub(/^#/, "")
  end
  # RGB VALUE
  case color_code.length
  when 3
    # three-digit hexadecimal representation
    r = color_code[0]
    g = color_code[1]
    b = color_code[2]
    returncolor['R'] = (r + r).hex
    returncolor['G'] = (g + g).hex
    returncolor['B'] = (b + b).hex
  when 6
    # six-digit hexadecimal representation
    returncolor['R'] = color_code[0,2].hex
    returncolor['G'] = color_code[2,2].hex
    returncolor['B'] = color_code[4,2].hex
  else
    returncolor = []
  end
  return returncolor
end

#Curve(x0, y0, x1, y1, x2, y2, x3, y3, style = '', line_style = nil, fill_color = nil) ⇒ Object Also known as: curve

Draws a Bezier curve. The Bezier curve is a tangent to the line between the control points at either end of the curve.

@param float :x0

Abscissa of start point.

@param float :y0

Ordinate of start point.

@param float :x1

Abscissa of control point 1.

@param float :y1

Ordinate of control point 1.

@param float :x2

Abscissa of control point 2.

@param float :y2

Ordinate of control point 2.

@param float :x3

Abscissa of end point.

@param float :y3

Ordinate of end point.

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param array :line_style

Line style of curve. Array like for SetLineStyle SetLineStyle. Default value: default line style (empty array).

@param array :fill_color

Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array).

@access public
@see

SetLineStyle()

@since 2.1.000 (2008-01-08)


8439
8440
8441
8442
8443
8444
8445
8446
8447
8448
8449
8450
# File 'lib/rbpdf.rb', line 8439

def Curve(x0, y0, x1, y1, x2, y2, x3, y3, style='', line_style=nil, fill_color=nil)
  if style and (style.index('F') != nil) and fill_color
    SetFillColorArray(fill_color)
  end
  op = getPathPaintOperator(style)
  if line_style
    SetLineStyle(line_style)
  end
  outPoint(x0, y0)
  outCurve(x1, y1, x2, y2, x3, y3)
  out(op)
end

#deletePage(page) ⇒ Object Also known as: delete_page

Remove the specified page.

@param int :page

page to remove

@return

true in case of success, false in case of error.

@access public
@since 4.6.004 (2009-04-23)


13886
13887
13888
13889
13890
13891
13892
13893
13894
13895
13896
13897
13898
13899
13900
13901
13902
13903
13904
13905
13906
13907
13908
13909
13910
13911
13912
13913
13914
13915
13916
13917
13918
13919
13920
13921
13922
13923
13924
13925
13926
13927
13928
13929
13930
13931
13932
13933
13934
13935
13936
13937
13938
13939
13940
13941
13942
13943
13944
13945
13946
13947
13948
13949
13950
13951
13952
13953
13954
13955
13956
13957
13958
13959
13960
13961
13962
13963
13964
13965
13966
13967
13968
13969
13970
13971
13972
13973
13974
13975
13976
13977
13978
13979
13980
13981
13982
13983
13984
13985
13986
13987
13988
13989
13990
13991
13992
13993
13994
13995
13996
13997
13998
13999
14000
14001
14002
14003
14004
14005
14006
14007
14008
14009
14010
14011
14012
14013
14014
14015
# File 'lib/rbpdf.rb', line 13886

def deletePage(page)
  if page > @numpages
    return false
  end
  # delete current page
  @pages[page] = nil
  @pagedim[page] = nil
  @pagelen[page] = nil
  @intmrk[page] = nil
  if @footerpos[page]
    @footerpos[page] = nil
  end
  if @footerlen[page]
    @footerlen[page] = nil
  end
  if @transfmrk[page]
    @transfmrk[page] = nil
  end
  if @page_annots[page]
    @page_annots[page] = nil
  end
  if @newpagegroup[page]
    @newpagegroup[page] = nil
  end
  if @pageopen[page]
    @pageopen[page] = nil
  end
  # update remaining pages
  page.upto(@numpages - 1) do |i|
    j = i + 1
    # shift pages
    @pages[i] = @pages[j]
    @pagedim[i] = @pagedim[j]
    @pagelen[i] = @pagelen[j]
    @intmrk[i] = @intmrk[j]
    if @footerpos[j]
      @footerpos[i] = @footerpos[j]
    elsif @footerpos[i]
      @footerpos[i] = nil
    end
    if @footerlen[j]
      @footerlen[i] = @footerlen[j]
    elsif @footerlen[i]
      @footerlen[i] = nil
    end
    if @transfmrk[j]
      @transfmrk[i] = @transfmrk[j]
    elsif @transfmrk[i]
      @transfmrk[i] = nil
    end
    if @page_annots[j]
      @page_annots[i] = page_annots[j]
    elsif @page_annots[i]
      @page_annots[i] = nil
    end
    if @newpagegroup[j]
      @newpagegroup[i] = @newpagegroup[j]
    elsif @newpagegroup[i]
      @newpagegroup[i] = nil
    end
    if @pageopen[j]
      @pageopen[i] = @pageopen[j]
    elsif @pageopen[i]
      @pageopen[i] = nil
    end
  end
  # remove last page
  @pages[@numpages] = nil
  @pagedim[@numpages] = nil
  @pagelen[@numpages] = nil
  @intmrk[@numpages] = nil
  if @footerpos[@numpages]
    @footerpos[@numpages] = nil
  end
  if @footerlen[@numpages]
    @footerlen[@numpages] = nil
  end
  if @transfmrk[@numpages]
    @transfmrk[@numpages] = nil
  end
  if @page_annots[@numpages]
    @page_annots[@numpages] = nil
  end
  if @newpagegroup[@numpages]
    @newpagegroup[@numpages] = nil
  end
  if @pageopen[@numpages]
    @pageopen[@numpages] = nil
  end
  @numpages -= 1
  @page = @numpages
  # adjust outlines
  tmpoutlines = @outlines
  tmpoutlines.each_with_index do |outline, key|
    if outline[:p] > page
      @outlines[key][:p] = outline[:p] - 1
    elsif outline[:p] == page
      @outlines[key] = nil
    end
  end
  # adjust links
  tmplinks = @links
  tmplinks.each_with_index do |link, key|
    if link[0] > page
      @links[key][0] = link[0] - 1
    elsif link[0] == page
      @links[key] = nil
    end
  end

  #### PDF javascript code does not implement, yet. ###
  # adjust javascript
  #tmpjavascript = @javascript
  #jpage = page
  #tmpjavascript =~ /this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/
  #pagenum = $3.to_i + 1
  #if pagenum >= jpage
  #  newpage = pagenum - 1
  #elsif pagenum == jpage
  #  newpage = 1
  #else
  #  newpage = pagenum
  #end
  #newpage -= 1
  #@javascript = "this.addField(\'" + $1 + "\',\'" + $2 + "\'," + newpage + ""

  # return to last page
  lastPage(true)
  return true
end

#destroy(destroyall = false, preserve_objcopy = false) ⇒ Object

Unset all class variables except the following critical variables: internal_encoding, state, bufferlen, buffer and diskcache.

@param boolean :destroyall

if true destroys all class variables, otherwise preserves critical variables.

@param boolean :preserve_objcopy

if true preserves the objcopy variable

@access public


5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
# File 'lib/rbpdf.rb', line 5517

def destroy(destroyall=false, preserve_objcopy=false)
  if destroyall and @diskcache and !preserve_objcopy and !empty_string(@buffer.path)
    # remove buffer file from cache
    File.delete(@buffer.path)
  end
  self.instance_variables.each { |val|
    if destroyall or ((val != '@internal_encoding') and (val != '@state') and (val != '@bufferlen') and (val != '@buffer') and (val != '@diskcache') and (val != '@sign') and (val != '@signature_data') and (val != '@signature_max_length') and (val != '@byterange_string'))
      if (!preserve_objcopy or (val.to_s != '@objcopy')) and @val
        eval("#{val} = nil")
      end
    end
  }
end

#Ellipse(x0, y0, rx, ry = '', angle = 0, astart = 0, afinish = 360, style = '', line_style = nil, fill_color = nil, nc = 2) ⇒ Object Also known as: ellipse

Draws an ellipse. An ellipse is formed from n Bezier curves.

@param float :x0

Abscissa of center point.

@param float :y0

Ordinate of center point.

@param float :rx

Horizontal radius.

@param float :ry

Vertical radius (if ry = 0 then is a circle, see Circle Circle). Default value: 0.

@param float :angle

Angle oriented (anti-clockwise). Default value: 0.

@param float :astart

Angle start of draw line. Default value: 0.

@param float :afinish

Angle finish of draw line. Default value: 360.

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param array :line_style

Line style of ellipse. Array like for SetLineStyle SetLineStyle. Default value: default line style (empty array).

@param array :fill_color

Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array).

@param integer :nc

Number of curves used to draw a 90 degrees portion of ellipse.

@author

Nicola Asuni

@access public
@since 2.1.000 (2008-01-08)


8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
8486
8487
8488
8489
# File 'lib/rbpdf.rb', line 8471

def Ellipse(x0, y0, rx, ry='', angle=0, astart=0, afinish=360, style='', line_style=nil, fill_color=nil, nc=2)
  style = '' if style.nil?
  if empty_string(ry) or (ry == 0)
    ry = rx
  end
  if (nil != style.index('F')) and fill_color
    SetFillColorArray(fill_color)
  end
  op = getPathPaintOperator(style)
  if op == 'f'
    line_style = nil
  end

  if line_style and !line_style.empty?
    SetLineStyle(line_style)
  end
  outellipticalarc(x0, y0, rx, ry, angle, astart, afinish, false, nc)
  out(op)
end

#empty_string(str) ⇒ Object

Determine whether a string is empty.

@param string :str

string to be checked

@return boolean

true if string is empty

@access public
@since 4.5.044 (2009-04-16)


14374
14375
14376
# File 'lib/rbpdf.rb', line 14374

def empty_string(str)
  return (str.nil? or (str.is_a?(String) and (str.length == 0)))
end

#endPage(tocpage = false) ⇒ Object Also known as: end_page

Terminate the current page

@param boolean :tocpage

if true set the tocpage state to false (end the page used to display Table Of Content).

@access public
@since 4.2.010 (2008-11-14)
@see

AddPage(), startPage(), addTOCPage(), endTOCPage()



1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
# File 'lib/rbpdf.rb', line 1664

def endPage(tocpage=false)
  # check if page is already closed
  if (@page == 0) or (@numpages > @page) or !@pageopen[@page]
    return
  end
  @in_footer = true
  # print page footer
  setFooter()
  # close page
  endpage()
  # mark page as closed
  @pageopen[@page] = false
  @in_footer = false
  if tocpage
    @tocpage = false
  end
end

#endTOCPageObject Also known as: end_toc_page

Terminate the current TOC (Table Of Content) page

@access public
@since 5.0.001 (2010-05-06)
@see

AddPage(), startPage(), endPage(), addTOCPage()



1616
1617
1618
# File 'lib/rbpdf.rb', line 1616

def endTOCPage()
  endPage(true)
end

#Error(msg) ⇒ Object Also known as: error

This method is automatically called in case of fatal error; it simply outputs the message and halts the execution. An inherited class may override it to customize the error handling but should always halt the script, or the resulting document would probably be invalid.

  • 2004-06-11

    Nicola Asuni : changed bold tag with strong

@param string :msg

The error message

@access public
@since 1.0


1456
1457
1458
1459
1460
# File 'lib/rbpdf.rb', line 1456

def Error(msg)
  destroy(true)
  #Fatal error
  raise ("RBPDF error: #{msg}")
end

This method is used to render the page footer. It is automatically called by AddPage() and could be overwritten in your own inherited class.

@access public


1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
# File 'lib/rbpdf.rb', line 1975

def Footer()
  cur_y = GetY()
  ormargins = getOriginalMargins()
  SetTextColor(0, 0, 0)
  # set style for cell border
  line_width = 0.85 / getScaleFactor()
  SetLineStyle({'width' => line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => [0, 0, 0]})
  # print document barcode
  #barcode = getBarcode()
  #if !barcode.empty?
  #  Ln(line_width)
  #  barcode_width = ((getPageWidth() - ormargins['left'] - ormargins['right']) / 3).round
  #  write1DBarcode(barcode, 'C128B', GetX(), cur_y + line_width, barcode_width, ((getFooterMargin() / 3) - line_width), 0.3, '', '')
  #end
  w_page = (@l.nil? or @l['w_page'].nil?) ? '' : @l['w_page']
  if @pagegroups.empty?
    pagenumtxt = w_page + ' ' + getAliasNumPage() + ' / ' + getAliasNbPages()
  else
    pagenumtxt = w_page + ' ' + getPageNumGroupAlias() + ' / ' + getPageGroupAlias()
  end
  SetY(cur_y)
  # Print page number
  if getRTL()
    SetX(ormargins['right'])
    Cell(0, 0, pagenumtxt, 'T', 0, 'L')
  else
    SetX(ormargins['left'])
    Cell(0, 0, pagenumtxt, 'T', 0, 'R')
  end
end

#GetAbsXObject Also known as: get_abs_x

Returns the absolute X value of current position.

@return float
@access public
@since 1.2
@see

SetY(), GetX(), SetX()



5283
5284
5285
# File 'lib/rbpdf.rb', line 5283

def GetAbsX()
  return @x
end

#getAliasNbPagesObject Also known as: get_alias_nb_pages

Returns the string alias used for the total number of pages. If the current font is unicode type, the returned string is surrounded by additional curly braces.

@return string
@access public
@since 4.0.018 (2008-08-08)
@see

AliasNbPages(), PageNo(), Footer()



9720
9721
9722
9723
9724
9725
# File 'lib/rbpdf.rb', line 9720

def getAliasNbPages()
  if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
    return '{' + @alias_nb_pages + '}'
  end
  return @alias_nb_pages
end

#getAliasNumPageObject Also known as: get_alias_num_page

Returns the string alias used for the page number. If the current font is unicode type, the returned string is surrounded by additional curly braces.

@return string
@access public
@since 4.5.000 (2009-01-02)
@see

AliasNbPages(), PageNo(), Footer()



9750
9751
9752
9753
9754
9755
# File 'lib/rbpdf.rb', line 9750

def getAliasNumPage()
  if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
    return '{' + @alias_num_page + '}'
  end
  return @alias_num_page
end

#GetArrStringWidth(sa, fontname = '', fontstyle = '', fontsize = 0, getarray = false) ⇒ Object Also known as: get_arr_string_width

Returns the string length of an array of chars in user unit or an array of characters widths. A font must be selected.

@param string :sa

The array of chars whose total length is to be computed

@param string :fontname

Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained.

@param string :fontstyle

Font style. Possible values are (case insensitive):

  • empty string: regular

  • B: bold

  • I: italic

  • U: underline

  • D: line trough

  • O: overline

or any combination. The default value is regular.

@param float :fontsize

Font size in points. The default value is the current size.

@param boolean :getarray

if true returns an array of characters widths, if false returns the total length.

@return mixed int

total string length or array of characted widths

@author

Nicola Asuni

@access public
@since 2.4.000 (2008-03-06)


2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
# File 'lib/rbpdf.rb', line 2459

def GetArrStringWidth(sa, fontname='', fontstyle='', fontsize=0, getarray=false)
  # store current values
  if !empty_string(fontname)
    prev_FontFamily = @font_family
    prev_FontStyle = @font_style
    prev_FontSizePt = @font_size_pt
    SetFont(fontname, fontstyle, fontsize)
  end
  # convert UTF-8 array to Latin1 if required
  sa = UTF8ArrToLatin1(sa)
  w = 0 # total width
  wa = [] # array of characters widths
  sa.each do |char|
    # character width
    cw = GetCharWidth(char)
    wa.push cw
    w += cw
  end
  # restore previous values
  if !empty_string(fontname)
    SetFont(prev_FontFamily, prev_FontStyle, prev_FontSizePt)
  end
  if getarray
    return wa
  end
  return w
end

#getBreakMargin(pagenum = 0) ⇒ Object Also known as: get_break_margin

Returns the page break margin.

@param int :pagenum

page number (empty = current page)

@return int page

break margin.

@author

Nicola Asuni

[@access publi]c

@since 1.5.2
@see

getPageDimensions()



1165
1166
1167
1168
1169
1170
# File 'lib/rbpdf.rb', line 1165

def getBreakMargin(pagenum=0)
  if !pagenum.is_a? Integer or pagenum.zero?
    return @b_margin
  end
  return @pagedim[pagenum]['bm']
end

#GetBreakMargin(pagenum = 0) ⇒ Object



1173
1174
1175
1176
# File 'lib/rbpdf.rb', line 1173

def GetBreakMargin(pagenum=0)
  warn "[DEPRECATION] 'GetBreakMargin' is deprecated. Please use 'get_break_margin' instead."
  getBreakMargin(pagenum)
end

#getCellHeightRatioObject Also known as: get_cell_height_ratio

return the height of cell repect font height.

@access public
@since 4.0.012 (2008-07-24)


9996
9997
9998
# File 'lib/rbpdf.rb', line 9996

def getCellHeightRatio()
  return @cell_height_ratio
end

#GetCharWidth(char) ⇒ Object Also known as: get_char_width

Returns the length of the char in user unit for the current font.

@param int :char

The char code whose length is to be returned

@return int

char width

@author

Nicola Asuni

@access public
@since 2.4.000 (2008-03-06)


2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
# File 'lib/rbpdf.rb', line 2496

def GetCharWidth(char)
  if char == 173
    # SHY character will not be printed
    return 0
  end
  cw = @current_font['cw']
  if !cw[char].nil?
    w = cw[char]
  elsif !@current_font['dw'].nil?
    # default width
    w = @current_font['dw']
  elsif !cw[32].nil?
    # default width
    w = cw[32]
  else
    w = 600
  end
  return (w * @font_size / 1000.0)
end

#getFontAscent(font, style = '', size = 0) ⇒ Object Also known as: get_font_ascent

Return the font ascent value

@param string :font

font name

@param string :style

font style

@param float :size

The size (in points)

@return int

font ascent

@access public
@since 4.9.003 (2010-03-30)


2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
# File 'lib/rbpdf.rb', line 2872

def getFontAscent(font, style='', size=0)
  # Set font size in points
  sizek = size / @k
  fontdata = AddFont(font, style)
  font = getFontBuffer(fontdata['fontkey'])
  if font['desc'] and font['desc']['Ascent'] and (font['desc']['Ascent'] > 0)
    ascent = font['desc']['Ascent'] * sizek / 1000
  else
    ascent = 0.85 * sizek
  end
  return ascent
end

#getFontDescent(font, style = '', size = 0) ⇒ Object Also known as: get_font_descent

Return the font descent value

@param string :font

font name

@param string :style

font style

@param float :size

The size (in points)

@return int

font descent

@access public
@since 4.9.003 (2010-03-30)


2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
# File 'lib/rbpdf.rb', line 2849

def getFontDescent(font, style='', size=0)
  # Set font size in points
  sizek = size / @k
  fontdata = AddFont(font, style)
  font = getFontBuffer(fontdata['fontkey'])
  if font['desc'] and font['desc']['Descent'] and (font['desc']['Descent'] <= 0)
    descent = - font['desc']['Descent'] * sizek / 1000
  else
    descent = 0.15 * sizek
  end
  return descent
end

#getFontFamilyObject Also known as: get_font_family

Returns the current font family name.

@return string

current font family name

@access public
@since 4.3.008 (2008-12-05)


10297
10298
10299
# File 'lib/rbpdf.rb', line 10297

def getFontFamily()
  return @font_family
end

#getFontSizeObject Also known as: get_font_size

Returns the current font size.

@return

current font size

@access public
@since 3.2.000 (2008-06-23)


10275
10276
10277
# File 'lib/rbpdf.rb', line 10275

def getFontSize()
  return @font_size
end

#getFontSizePtObject Also known as: get_font_size_pt

Returns the current font size in points unit.

@return

current font size in points unit

@access public
@since 3.2.000 (2008-06-23)


10286
10287
10288
# File 'lib/rbpdf.rb', line 10286

def getFontSizePt()
  return @font_size_pt
end

#getFontStyleObject Also known as: get_font_style

Returns the current font style.

@return string

current font style

@access public
@since 4.3.008 (2008-12-05)


10308
10309
10310
# File 'lib/rbpdf.rb', line 10308

def getFontStyle()
  return @font_style
end

#getFooterFont(font) ⇒ Object Also known as: get_footer_font

Get Footer font.

@return array
@access public
@since 4.0.012 (2008-07-24)


7860
7861
7862
# File 'lib/rbpdf.rb', line 7860

def getFooterFont(font)
  return @footer_font
end

#getFooterMarginObject Also known as: get_footer_margin

Returns footer margin in user units.

@return float
@since 4.0.012 (2008-07-24)
@access public


1864
1865
1866
# File 'lib/rbpdf.rb', line 1864

def getFooterMargin()
  return @footer_margin
end

#getGroupPageNoObject Also known as: get_group_page_no

Return the current page in the group.

@return

current page in the group

@access public
@since 3.0.000 (2008-03-27)


9764
9765
9766
# File 'lib/rbpdf.rb', line 9764

def getGroupPageNo()
  return @pagegroups[@currpagegroup]
end

#getGroupPageNoFormattedObject Also known as: get_group_page_no_formatted

Returns the current group page number formatted as a string.

@access public
@since 4.3.003 (2008-11-18)
@see

PaneNo(), formatPageNumber()



9775
9776
9777
# File 'lib/rbpdf.rb', line 9775

def getGroupPageNoFormatted()
  return formatPageNumber(getGroupPageNo())
end

#getHeaderDataObject Also known as: get_header_data

Returns header data:

ret['logo'] = logo image
ret['logo_width'] = width of the image logo in user units
ret['title'] = header title
ret['string'] = header description string
@return hash
@access public
@since 4.0.012 (2008-07-24)


1805
1806
1807
1808
1809
1810
1811
1812
# File 'lib/rbpdf.rb', line 1805

def getHeaderData()
  ret = {}
  ret['logo'] = @header_logo
  ret['logo_width'] = @header_logo_width
  ret['title'] = @header_title
  ret['string'] = @header_string
  return ret
end

#getHeaderFontObject Also known as: get_header_font

Get header font.

@return array
@access public
@since 4.0.012 (2008-07-24)


7833
7834
7835
# File 'lib/rbpdf.rb', line 7833

def getHeaderFont()
  return @header_font
end

#getHeaderMarginObject Also known as: get_header_margin

Returns header margin in user units.

@return float
@since 4.0.012 (2008-07-24)
@access public


1837
1838
1839
# File 'lib/rbpdf.rb', line 1837

def getHeaderMargin()
  return @header_margin
end

#getHTMLUnitToUnits(htmlval, refsize = 1, defaultunit = 'px', points = false) ⇒ Object Also known as: get_html_unit_to_units

convert HTML string containing value and unit of measure to user’s units or points.

@param string :htmlval

string containing values and unit

@param string :refsize

reference value in points

@param string :defaultunit

default unit (can be one of the following: %, em, ex, px, in, mm, pc, pt).

@param boolean :point

if true returns points, otherwise returns value in user’s units

@return float

value in user’s unit or point if :points=true

@access public
@since 4.4.004 (2008-12-10)


13185
13186
13187
13188
13189
13190
13191
13192
13193
13194
13195
13196
13197
13198
13199
13200
13201
13202
13203
13204
13205
13206
13207
13208
13209
13210
13211
13212
13213
13214
13215
13216
13217
13218
13219
13220
13221
13222
13223
13224
13225
13226
13227
13228
13229
13230
13231
13232
# File 'lib/rbpdf.rb', line 13185

def getHTMLUnitToUnits(htmlval, refsize=1, defaultunit='px', points=false)
  supportedunits = ['%', 'em', 'ex', 'px', 'in', 'cm', 'mm', 'pc', 'pt']
  retval = 0
  value = 0
  unit = 'px'
  k = @k
  if points
    k = 1
  end
  if supportedunits.include?(defaultunit)
    unit = defaultunit
  end
  if htmlval.is_a?(Numeric)
    value = htmlval.to_f
  else
    mnum = htmlval.scan(/[0-9\.\-\+]+/)
    unless mnum.empty?
      value = mnum[0].to_f
      munit = htmlval.scan(/[a-z%]+/)
      unless munit.empty?
        if supportedunits.include?(munit[0])
          unit = munit[0]
        end
      end
    end
  end
  case unit
  when '%' # percentage
    retval = (value * refsize) / 100
  when 'em' # relative-size
    retval = value * refsize
  when 'ex' # height of lower case 'x' (about half the font-size)
    retval = value * (refsize / 2)
  when 'in' # absolute-size
    retval = (value * @dpi) / k
  when 'cm' # centimeters
    retval = (value / 2.54 * @dpi) / k
  when 'mm' # millimeters
    retval = (value / 25.4 * @dpi) / k
  when 'pc' # one pica is 12 points
    retval = (value * 12) / k
  when 'pt' # points
    retval = value / k
  when 'px' # pixels
    retval = pixelsToUnits(value)
  end
  return retval
end

#getImageFileType(imgfile, iminfo = {}) ⇒ Object Also known as: get_image_file_type

Return the image type given the file name or array returned by getimagesize() function.

@param string :imgfile

image file name

@param hash :iminfo

array of image information returned by getimagesize() function.

@return string

image type

@access public
@since 4.8.017 (2009-11-27)


4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
# File 'lib/rbpdf.rb', line 4652

def getImageFileType(imgfile, iminfo={})
  if iminfo.is_a? Hash and iminfo['mime'] and !iminfo['mime'].empty?
    mime = iminfo['mime'].split('/')
    if (mime.length > 1) and (mime[0] == 'image') and !mime[1].empty?
      return mime[1].strip
    end
  end
  type = ''
  return type if imgfile.nil?

  fileinfo = File::extname(imgfile)
  type = fileinfo.sub(/^\./, '').downcase if fileinfo != ''
  if type == 'jpg'
    type = 'jpeg'
  end
  return type
end

#getImageRBXObject Also known as: get_image_rbx

Return the right-bottom (or left-bottom for RTL) corner X coordinate of last inserted image

@return float
@access public


1904
1905
1906
# File 'lib/rbpdf.rb', line 1904

def getImageRBX()
  return @img_rb_x
end

#getImageRBYObject Also known as: get_image_rby

Return the right-bottom (or left-bottom for RTL) corner Y coordinate of last inserted image

@return float
@access public


1914
1915
1916
# File 'lib/rbpdf.rb', line 1914

def getImageRBY()
  return @img_rb_y
end

#GetImageScaleObject



1053
1054
1055
1056
# File 'lib/rbpdf.rb', line 1053

def GetImageScale()
  warn "[DEPRECATION] 'GetImageScale' is deprecated. Please use 'get_image_scale' instead."
  getImageScale()
end

#getImageScaleObject Also known as: get_image_scale

Returns the adjusting factor to convert pixels to user units.

@return float

adjusting factor to convert pixels to user units.

@author

Nicola Asuni

@access public
@since 1.5.2


1048
1049
1050
# File 'lib/rbpdf.rb', line 1048

def getImageScale()
  return @img_scale;
end

#getLastHObject Also known as: get_last_h

Get the last cell height.

@return

last cell height

@access public
@since 4.0.017 (2008-08-05)


1019
1020
1021
# File 'lib/rbpdf.rb', line 1019

def getLastH()
  return @lasth
end

#GetLineWidthObject Also known as: get_line_width

Returns the current the line width.

@return int

Line width

@access public
@since 2.1.000 (2008-01-07)
@see

Line(), SetLineWidth()



8185
8186
8187
# File 'lib/rbpdf.rb', line 8185

def GetLineWidth()
  return @line_width
end

#getMarginsObject Also known as: get_margins

Returns an array containing current margins:

* ret['left'] = left  margin
* ret['right'] = right margin
* ret['top'] = top margin
* ret['bottom'] = bottom margin
* ret['header'] = header margin
* ret['footer'] = footer margin
* ret['cell'] = cell margin
@return array

containing all margins measures

@access public
@since 3.2.000 (2008-06-23)


10241
10242
10243
10244
10245
10246
10247
10248
10249
10250
10251
10252
# File 'lib/rbpdf.rb', line 10241

def getMargins()
  ret = {
      'left' => @l_margin,
      'right' => @r_margin,
      'top' => @t_margin,
      'bottom' => @b_margin,
      'header' => @header_margin,
      'footer' => @footer_margin,
      'cell' => @c_margin,
  }
  return ret
end

#GetNumChars(s) ⇒ Object Also known as: get_num_chars

Returns the numbero of characters in a string.

@param string :s

The input string.

@return int

number of characters

@access public
@since 2.0.0001 (2008-01-07)


2524
2525
2526
2527
2528
2529
# File 'lib/rbpdf.rb', line 2524

def GetNumChars(s)
  if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
    return UTF8StringToArray(s).length
  end 
  return s.length
end

#getNumLines(txt, w = 0, reseth = false, autopadding = true, cellMargin = '', lineWidth = '') ⇒ Object Also known as: get_num_lines

This method return the estimated number of lines for print a simple text string in Multicell() method.

@param string :txt

String for calculating his height

@param float :w

Width of cells. If 0, they extend up to the right margin of the page.

@param boolean :reseth

if true reset the last cell height (default false).

@param boolean :autopadding

if true, uses internal padding and automatically adjust it to account for line width (default true).

@param float :cellMargin

Internal cell margin, if empty or <= 0, extended up to current pdf cell margin (default ”).

@param float :lineWidth

Line width, if empty or <= 0, extended up to current pdf line width (default ”).

@return float

Return the minimal height needed for multicell method for printing the :txt param.

@author

Alexander Escalona Fernendez, Nicola Asuni

@access public
@since 4.5.011


4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
# File 'lib/rbpdf.rb', line 4054

def getNumLines(txt, w=0, reseth=false, autopadding=true, cellMargin='', lineWidth='')
  if empty_string(w) or (w <= 0)
    if @rtl
      w = @x - @l_margin
    else
      w = @w - @r_margin - @x
    end
  end
  if empty_string(cellMargin) or (cellMargin <= 0)
    cellMargin = @c_margin
  end
  if empty_string(lineWidth) or (lineWidth <= 0)
    lineWidth = @line_width
  end
  if autopadding
    # adjust internal padding
    if cellMargin < (lineWidth / 2)
      cellMargin = lineWidth / 2
    end
  end
  wmax = w - (2 * cellMargin)
  if reseth
    @lasth = @font_size * @cell_height_ratio
  end
  lines = 1
  sum = 0
  chars = UTF8StringToArray(txt)
  chars = utf8Bidi(chars, txt, @tmprtl)
  charsWidth = GetArrStringWidth(chars, '', '', 0, true)
  if @rtl
    charsWidth.reverse!
    chars.reverse!
  end
  length = chars.length
  lastSeparator = -1

  i = 0
  while i < length
    charWidth = charsWidth[i]
    if unichr(chars[i]) =~ /\s/
      lastSeparator = i
    end
    if (sum + charWidth >= wmax) or (chars[i] == 10) # 10 = "\n" = new line
      lines += 1
      if lastSeparator != -1
        i = lastSeparator
        lastSeparator = -1
        sum = 0
      else
        sum = charWidth
      end
    else
      sum += charWidth
    end
    i += 1
  end
  return lines
end

#getNumPagesObject Also known as: get_num_pages

Get the total number of insered pages.

@return int

number of pages

@access public
@since 2.1.000 (2008-01-07)
@see

setPage(), getPage(), lastPage()



1592
1593
1594
# File 'lib/rbpdf.rb', line 1592

def getNumPages()
  return @numpages
end

#getOriginalMarginsObject Also known as: get_original_margins

Returns an array containing original margins:

ret['left'] = left  margin
ret['right'] = right margin
@return array

containing all margins measures

@access public
@since 4.0.012 (2008-07-24)


10263
10264
10265
10266
# File 'lib/rbpdf.rb', line 10263

def getOriginalMargins()
  ret = { 'left' => @original_l_margin, 'right' => @original_r_margin }
  return ret
end

#getPageObject Also known as: get_page

Get current document page number.

@return int

page number

@access public
@since 2.1.000 (2008-01-07)
@see

setPage(), lastPage(), getNumPages()



1580
1581
1582
# File 'lib/rbpdf.rb', line 1580

def getPage()
  return @page
end

#getPageDimensions(pagenum = 0) ⇒ Object Also known as: get_page_dimensions

Returns an array of page dimensions:

@pagedim[@page]['w'] = page width in points
@pagedim[@page]['h'] = height in points
@pagedim[@page]['wk'] = page width in user units
@pagedim[@page]['hk'] = page height in user units
@pagedim[@page]['tm'] = top margin
@pagedim[@page]['bm'] = bottom margin
@pagedim[@page]['lm'] = left margin
@pagedim[@page]['rm'] = right margin
@pagedim[@page]['pb'] = auto page break
@pagedim[@page]['or'] = page orientation
@pagedim[@page]['olm'] = original left margin
@pagedim[@page]['orm'] = original right margin
@pagedim[@page]['Rotate'] = The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.
@pagedim[@page]['PZ'] = The page's preferred zoom (magnification) factor.
@pagedim[@page]['trans'] : the style and duration of the visual transition to use when moving from another page to the given page during a presentation
  @pagedim[@page]['trans']['Dur'] = The page's display duration (also called its advance timing): the maximum length of time, in seconds, that the page shall be displayed during presentations before the viewer application shall automatically advance to the next page.
  @pagedim[@page]['trans']['S'] = transition style : Split, Blinds, Box, Wipe, Dissolve, Glitter, R, Fly, Push, Cover, Uncover, Fade
  @pagedim[@page]['trans']['D'] = The duration of the transition effect, in seconds.
  @pagedim[@page]['trans']['Dm'] = (Split and Blinds transition styles only) The dimension in which the specified transition effect shall occur: H = Horizontal, V = Vertical. Default value: H.
  @pagedim[@page]['trans']['M'] = (Split, Box and Fly transition styles only) The direction of motion for the specified transition effect: I = Inward from the edges of the page, O = Outward from the center of the pageDefault value: I.
  @pagedim[@page]['trans']['Di'] = (Wipe, Glitter, Fly, Cover, Uncover and Push transition styles only) The direction in which the specified transition effect shall moves, expressed in degrees counterclockwise starting from a left-to-right direction. If the value is a number, it shall be one of: 0 = Left to right, 90 = Bottom to top (Wipe only), 180 = Right to left (Wipe only), 270 = Top to bottom, 315 = Top-left to bottom-right (Glitter only). If the value is a name, it shall be None, which is relevant only for the Fly transition when the value of SS is not 1.0. Default value: 0.
  @pagedim[@page]['trans']['SS'] = (Fly transition style only) The starting or ending scale at which the changes shall be drawn. If M specifies an inward transition, the scale of the changes drawn shall progress from SS to 1.0 over the course of the transition. If M specifies an outward transition, the scale of the changes drawn shall progress from 1.0 to SS over the course of the transition. Default: 1.0. 
  @pagedim[@page]['trans']['B'] = (Fly transition style only) If true, the area that shall be flown in is rectangular and opaque. Default: false.
@pagedim[@page]['MediaBox'] : the boundaries of the physical medium on which the page shall be displayed or printed
  @pagedim[@page]['MediaBox']['llx'] = lower-left x coordinate in points
  @pagedim[@page]['MediaBox']['lly'] = lower-left y coordinate in points
  @pagedim[@page]['MediaBox']['urx'] = upper-right x coordinate in points
  @pagedim[@page]['MediaBox']['ury'] = upper-right y coordinate in points
@pagedim[@page]['CropBox'] : the visible region of default user space
  @pagedim[@page]['CropBox']['llx'] = lower-left x coordinate in points
  @pagedim[@page]['CropBox']['lly'] = lower-left y coordinate in points
  @pagedim[@page]['CropBox']['urx'] = upper-right x coordinate in points
  @pagedim[@page]['CropBox']['ury'] = upper-right y coordinate in points
@pagedim[@page]['BleedBox'] : the region to which the contents of the page shall be clipped when output in a production environment
  @pagedim[@page]['BleedBox']['llx'] = lower-left x coordinate in points
  @pagedim[@page]['BleedBox']['lly'] = lower-left y coordinate in points
  @pagedim[@page]['BleedBox']['urx'] = upper-right x coordinate in points
  @pagedim[@page]['BleedBox']['ury'] = upper-right y coordinate in points
@pagedim[@page]['TrimBox'] : the intended dimensions of the finished page after trimming
  @pagedim[@page]['TrimBox']['llx'] = lower-left x coordinate in points
  @pagedim[@page]['TrimBox']['lly'] = lower-left y coordinate in points
  @pagedim[@page]['TrimBox']['urx'] = upper-right x coordinate in points
  @pagedim[@page]['TrimBox']['ury'] = upper-right y coordinate in points
@pagedim[@page]['ArtBox'] : the extent of the page's meaningful content
  @pagedim[@page]['ArtBox']['llx'] = lower-left x coordinate in points
  @pagedim[@page]['ArtBox']['lly'] = lower-left y coordinate in points
  @pagedim[@page]['ArtBox']['urx'] = upper-right x coordinate in points
  @pagedim[@page]['ArtBox']['ury'] = upper-right y coordinate in points
@param int :pagenum

page number (empty = current page)

@return

array of page dimensions.

@author

Nicola Asuni

@access public
@since 4.5.027 (2009-03-16)


1114
1115
1116
1117
1118
1119
# File 'lib/rbpdf.rb', line 1114

def getPageDimensions(pagenum=0)
  if !pagenum.is_a? Integer or pagenum.zero?
    pagenum = @page
  end
  return @pagedim[pagenum]
end

#getPageGroupAliasObject Also known as: get_page_group_alias

Return the alias of the current page group If the current font is unicode type, the returned string is surrounded by additional curly braces. (will be replaced by the total number of pages in this group).

@return

alias of the current page group

@access public
@since 3.0.000 (2008-03-27)


9788
9789
9790
9791
9792
9793
# File 'lib/rbpdf.rb', line 9788

def getPageGroupAlias()
  if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont1')
    return '{' + @currpagegroup + '}'
  end
  return @currpagegroup
end

#GetPageHeightObject



1151
1152
1153
1154
# File 'lib/rbpdf.rb', line 1151

def GetPageHeight()
  warn "[DEPRECATION] 'GetPageHeight' is deprecated. Please use 'get_page_height' instead."
  getPageHeight()
end

#getPageHeightObject Also known as: get_page_height

Returns the page height in units.

@return int

page height.

@author

Nicola Asuni

@access public
@since 1.5.2


1146
1147
1148
# File 'lib/rbpdf.rb', line 1146

def getPageHeight()
  return @h;
end

#getPageNumGroupAliasObject Also known as: get_page_num_group_alias

Return the alias for the page number on the current page group If the current font is unicode type, the returned string is surrounded by additional curly braces. (will be replaced by the total number of pages in this group).

@return

alias of the current page group

@access public
@since 4.5.000 (2009-01-02)


9804
9805
9806
9807
9808
9809
# File 'lib/rbpdf.rb', line 9804

def getPageNumGroupAlias()
  if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
    return '{' + @currpagegroup.gsub('{nb', '{pnb') +'}'
  end
  return @currpagegroup.gsub('{nb', '{pnb')
end

#getPageSizeFromFormat(format) ⇒ Object Also known as: get_page_size_from_format

Get page dimensions from fromat name.

@param mixed :format

The format name. It can be:

  • 4A0,2A0,A0,A1,A2,A3,A4 (default),A5,A6,A7,A8,A9,A10

  • B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10

  • C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10

  • RA0,RA1,RA2,RA3,RA4

  • SRA0,SRA1,SRA2,SRA3,SRA4

  • LETTER,LEGAL,EXECUTIVE,FOLIO

@return array

containing page width and height in points

@access public
@since 5.0.010 (2010-05-17)


562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
# File 'lib/rbpdf.rb', line 562

def getPageSizeFromFormat(format)
  # Page formats (45 standard ISO paper formats and 4 american common formats).
  # Paper cordinates are calculated in this way: (inches * 72) where (1 inch = 2.54 cm)
  case format.upcase
  when '4A0'; pf = [4767.87,6740.79]
  when '2A0'; pf = [3370.39,4767.87]
  when 'A0'; pf = [2383.94,3370.39]
  when 'A1'; pf = [1683.78,2383.94]
  when 'A2'; pf = [1190.55,1683.78]
  when 'A3'; pf = [841.89,1190.55]
  when 'A4'; pf = [595.28,841.89]
  when 'A5'; pf = [419.53,595.28]
  when 'A6'; pf = [297.64,419.53]
  when 'A7'; pf = [209.76,297.64]
  when 'A8'; pf = [147.40,209.76]
  when 'A9'; pf = [104.88,147.40]
  when 'A10'; pf = [73.70,104.88]
  when 'B0'; pf = [2834.65,4008.19]
  when 'B1'; pf = [2004.09,2834.65]
  when 'B2'; pf = [1417.32,2004.09]
  when 'B3'; pf = [1000.63,1417.32]
  when 'B4'; pf = [708.66,1000.63]
  when 'B5'; pf = [498.90,708.66]
  when 'B6'; pf = [354.33,498.90]
  when 'B7'; pf = [249.45,354.33]
  when 'B8'; pf = [175.75,249.45]
  when 'B9'; pf = [124.72,175.75]
  when 'B10'; pf = [87.87,124.72]
  when 'C0'; pf = [2599.37,3676.54]
  when 'C1'; pf = [1836.85,2599.37]
  when 'C2'; pf = [1298.27,1836.85]
  when 'C3'; pf = [918.43,1298.27]
  when 'C4'; pf = [649.13,918.43]
  when 'C5'; pf = [459.21,649.13]
  when 'C6'; pf = [323.15,459.21]
  when 'C7'; pf = [229.61,323.15]
  when 'C8'; pf = [161.57,229.61]
  when 'C9'; pf = [113.39,161.57]
  when 'C10'; pf = [79.37,113.39]
  when 'RA0'; pf = [2437.80,3458.27]
  when 'RA1'; pf = [1729.13,2437.80]
  when 'RA2'; pf = [1218.90,1729.13]
  when 'RA3'; pf = [864.57,1218.90]
  when 'RA4'; pf = [609.45,864.57]
  when 'SRA0'; pf = [2551.18,3628.35]
  when 'SRA1'; pf = [1814.17,2551.18]
  when 'SRA2'; pf = [1275.59,1814.17]
  when 'SRA3'; pf = [907.09,1275.59]
  when 'SRA4'; pf = [637.80,907.09]
  when 'LETTER'; pf = [612.00,792.00]
  when 'LEGAL'; pf = [612.00,1008.00]
  when 'EXECUTIVE'; pf = [521.86,756.00]
  when 'FOLIO'; pf = [612.00,936.00]
  else
    pf = [595.28,841.89] # DEFAULT A4
  end
  return pf
end

#GetPageWidthObject



1134
1135
1136
1137
# File 'lib/rbpdf.rb', line 1134

def GetPageWidth()
  warn "[DEPRECATION] 'GetPageWidth' is deprecated. Please use 'get_page_width' instead."
  getPageWidth()
end

#getPageWidthObject Also known as: get_page_width

Returns the page width in units.

@return int

page width.

@author

Nicola Asuni

@access public
@since 1.5.2


1129
1130
1131
# File 'lib/rbpdf.rb', line 1129

def getPageWidth()
  return @w;
end

#GetPDFDataObject



7897
7898
7899
7900
# File 'lib/rbpdf.rb', line 7897

def GetPDFData()
  warn "[DEPRECATION] 'GetPDFData' is deprecated. Please use 'get_pdf_data' instead."
  getPDFData()
end

#getPDFDataObject Also known as: get_pdf_data

Returns the PDF data.

@access public


7889
7890
7891
7892
7893
7894
# File 'lib/rbpdf.rb', line 7889

def getPDFData()
  if (@state < 3)
    Close();
  end
  return @buffer;
end

#getRTLObject Also known as: get_rtl

Return the RTL status

@return boolean
@access public
@since 4.0.012 (2008-07-24)


967
968
969
# File 'lib/rbpdf.rb', line 967

def getRTL()
  return @rtl
end

#getScaleFactorObject Also known as: get_scale_factor

Returns the scale factor (number of points in user unit).

@return int

scale factor.

@author

Nicola Asuni

@access public
@since 1.5.2


1185
1186
1187
# File 'lib/rbpdf.rb', line 1185

def getScaleFactor()
  return @k;
end

#GetScaleFactorObject



1190
1191
1192
1193
# File 'lib/rbpdf.rb', line 1190

def GetScaleFactor()
  warn "[DEPRECATION] 'GetScaleFactor' is deprecated. Please use 'get_scale_factor' instead."
  getScaleFactor()
end

#getStringHeight(w, txt, reseth = false, autopadding = true, cellMargin = '', lineWidth = '') ⇒ Object Also known as: get_string_height

This method return the estimated needed height for print a simple text string in Multicell() method. Generally, if you want to know the exact height for a block of content you can use the following technique:

# store current object
pdf.start_transaction()
# store starting values
start_y = pdf.get_y()
start_page = pdf.get_page()
# call your printing functions with your parameters
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
pdf.multi_cell(w=0, h=0, txt, border=1, align='L', fill=0, ln=1, x='', y='', reseth=true, stretch=0, ishtml=false, autopadding=true, maxh=0)
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# get the new Y
end_y = pdf.get_y()
end_page = pdf.get_page()
# calculate height
height = 0
if end_page == start_page
  height = end_y - start_y
else
  start_page.upto(end_page) do |page|
    pdf.set_page(page)
    if page == start_page
      # first page
      height = @h - start_y - @b_margin
    elsif page == end_page
      # last page
      height = end_y - @t_margin
    else
      height = @h - @t_margin - @b_margin
    end
  end
end
# restore previous object
pdf = pdf.rollbackTransaction()
@param float :w

Width of cells. If 0, they extend up to the right margin of the page.

@param string :txt

String for calculating his height

@param boolean :reseth

if true reset the last cell height (default false).

@param boolean :autopadding

if true, uses internal padding and automatically adjust it to account for line width (default true).

@param float :cellMargin

Internal cell margin, if empty or <= 0, extended up to current pdf cell margin (default ”).

@param float :lineWidth

Line width, if empty or <= 0, extended up to current pdf line width (default ”).

@return float

Return the minimal height needed for multicell method for printing the :txt param.

@author

Nicola Asuni, Alexander Escalona Fern<E1>ndez

@access public


4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
# File 'lib/rbpdf.rb', line 4161

def getStringHeight(w, txt, reseth=false, autopadding=true, cellMargin='', lineWidth='')
  lines = getNumLines(txt, w, reseth, autopadding, cellMargin, lineWidth)
  height = lines * (@font_size * @cell_height_ratio)
  if autopadding
    if empty_string(cellMargin) or (cellMargin <= 0)
      cellMargin = @c_margin
    end
    if empty_string(lineWidth) or (lineWidth <= 0)
      lineWidth = @line_width
    end
    # adjust internal padding
    if cellMargin < (lineWidth / 2)
      cellMargin = lineWidth / 2
    end
    # add top and bottom space if needed
    if (@lasth - @font_size) < lineWidth
      height += lineWidth
    end
    # add top and bottom padding
    height += 2 * cellMargin
  end
  return height
end

#GetStringWidth(s, fontname = '', fontstyle = '', fontsize = 0, getarray = false) ⇒ Object Also known as: get_string_width

Returns the length of a string in user unit. A font must be selected.

@param string :s

The string whose length is to be computed

@param string :fontname

Family font. It can be either a name defined by AddFont() or one of the standard families. It is also possible to pass an empty string, in that case, the current family is retained.

@param string :fontstyle

Font style. Possible values are (case insensitive):

  • empty string: regular

  • B: bold

  • I: italic

  • U: underline

  • D: line trough

  • O: overline

or any combination. The default value is regular.

@param float :fontsize

Font size in points. The default value is the current size.

@param boolean :getarray

if true returns an array of characters widths, if false returns the total length.

@return mixed int

total string length or array of characted widths

@author

Nicola Asuni

@access public
@since 1.2


2434
2435
2436
# File 'lib/rbpdf.rb', line 2434

def GetStringWidth(s, fontname='', fontstyle='', fontsize=0, getarray=false)
  return GetArrStringWidth(utf8Bidi(UTF8StringToArray(s), s, @tmprtl), fontname, fontstyle, fontsize, getarray)
end

#GetXObject Also known as: get_x

Returns the relative X value of current position. The value is relative to the left border for LTR languages and to the right border for RTL languages.

@return float
@access public
@since 1.2
@see

SetX(), GetY(), SetY()



5267
5268
5269
5270
5271
5272
5273
# File 'lib/rbpdf.rb', line 5267

def GetX()
  if @rtl
    return @w - @x
  else
    return @x
  end
end

#GetYObject Also known as: get_y

Returns the ordinate of the current position.

@return float
@access public
@since 1.0
@see

SetY(), GetX(), SetX()



5295
5296
5297
# File 'lib/rbpdf.rb', line 5295

def GetY()
  return @y;
end

#HeaderObject Also known as: header

This method is used to render the page header. It is automatically called by AddPage() and could be overwritten in your own inherited class.

@access public


1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
# File 'lib/rbpdf.rb', line 1924

def Header()
  ormargins = getOriginalMargins()
  headerfont = getHeaderFont()
  headerdata = getHeaderData()
  if headerdata['logo'] and (headerdata['logo'] != @@k_blank_image)
    result_img = Image(@@k_path_images + headerdata['logo'], '', '', headerdata['logo_width'])
    if result_img != false
      imgy = getImageRBY()
    else
      Write(@lasth, File.basename(headerdata['logo']), '', false, '', false, 0, false)
      imgy = GetY()
    end
  else
    imgy = GetY()
  end
  cell_height = ((getCellHeightRatio() * headerfont[2]) / getScaleFactor()).round(2)

  # set starting margin for text data cell
  if getRTL()
    header_x = ormargins['right'] + (headerdata['logo_width'] * 1.1)
  else
    header_x = ormargins['left'] + (headerdata['logo_width'] * 1.1)
  end
  SetTextColor(0, 0, 0)
  # header title
  SetFont(headerfont[0], 'B', headerfont[2] + 1)
  SetX(header_x)
  Cell(0, cell_height, headerdata['title'], 0, 1, '', 0, '', 0)
  # header string
  SetFont(headerfont[0], headerfont[1], headerfont[2])
  SetX(header_x)
  MultiCell(0, cell_height, headerdata['string'], 0, '', 0, 1, '', '', true, 0, false)

  # print an ending header line
  SetLineStyle({'width' => 0.85 / getScaleFactor(), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => [0, 0, 0]})
  SetY((2.835 / getScaleFactor()) + (imgy > GetY() ? imgy : GetY()))

  if getRTL()
    SetX(ormargins['right'])
  else
    SetX(ormargins['left'])
  end
  Cell(0, 0, '', 'T', 0, 'C')
end

#Image(file, x = '', y = '', w = 0, h = 0, type = '', link = nil, align = '', resize = false, dpi = 300, palign = '', ismask = false, imgmask = false, border = 0, fitbox = false, hidden = false, fitonpage = false) ⇒ Object Also known as: image

Puts an image in the page. The upper-left corner must be given. The dimensions can be specified in different ways:

  • explicit width and height (expressed in user unit)

  • one explicit dimension, the other being calculated automatically in order to keep the original proportions

  • no explicit dimension, in which case the image is put at 72 dpi

Supported formats are PNG images whitout RMagick library and JPEG and GIF images supported by RMagick. For JPEG, all flavors are allowed:

  • gray scales

  • true colors (24 bits)

  • CMYK (32 bits)

For PNG, are allowed:

  • gray scales on at most 8 bits (256 levels)

  • indexed colors

  • true colors (24 bits)

If a transparent color is defined, it will be taken into account (but will be only interpreted by Acrobat 4 and above). The format can be specified explicitly or inferred from the file extension. It is possible to put a link on the image.

  • Remark: if an image is used several times, only one copy will be embedded in the file.

@param string :file

Name of the file containing the image.

@param float :x

Abscissa of the upper-left corner.

@param float :y

Ordinate of the upper-left corner.

@param float :w

Width of the image in the page. If not specified or equal to zero, it is automatically calculated.

@param float :h

Height of the image in the page. If not specified or equal to zero, it is automatically calculated.

@param string :type

Image format. Possible values are (case insensitive): JPG, JPEG, PNG. If not specified, the type is inferred from the file extension.

@param mixed :link

URL or identifier returned by AddLink().

@param string :align

Indicates the alignment of the pointer next to image insertion relative to image height. The value can be:

  • T: top-right for LTR or top-left for RTL

  • M: middle-right for LTR or middle-left for RTL

  • B: bottom-right for LTR or bottom-left for RTL

  • N: next line

@param mixed :resize

If true resize (reduce) the image to fit :w and :h (requires RMagick library); if false do not resize; if 2 force resize in all cases (upscaling and downscaling).

@param int :dpi

dot-per-inch resolution used on resize

@param string :palign

Allows to center or align the image on the current line. Possible values are:

  • L : left align

  • C : center

  • R : right align

  • ” : empty string : left for LTR or right for RTL

@param boolean :ismask

true if this image is a mask, false otherwise

@param mixed :imgmask

image object returned by this function or false

@param mixed :border

Indicates if borders must be drawn around the image. The value can be either a number:

  • 0: no border (default)

  • 1: frame

or a string containing some or all of the following characters (in any order):

  • L: left

  • T: top

  • R: right

  • B: bottom

@param boolean :fitbox

If true scale image dimensions proportionally to fit within the (:w, :h) box.

@param boolean :hidden

if true do not display the image.

@param boolean :fitonpage

if true the image is resized to not exceed page dimensions.

@return

image information

@access public
@since 1.1


4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
# File 'lib/rbpdf.rb', line 4730

def Image(file, x='', y='', w=0, h=0, type='', link=nil, align='', resize=false, dpi=300, palign='', ismask=false, imgmask=false, border=0, fitbox=false, hidden=false, fitonpage=false)
  w = 0 if w == ''
  h = 0 if h == ''

  x = @x if x == ''
  y = @y if y == ''

  # set bottomcoordinates
  @img_rb_y = y + h
  Error('Image filename is empty.') if file.nil? or file.length == 0

  # get image dimensions
  imsize = getimagesize(file)
  if imsize.nil? or imsize == false
    # encode spaces on filename
    file = file.gsub(' ', '%20')
    imsize = getimagesize(file)

    if imsize.nil?
      Error('Missing image file: ' + file)
    elsif imsize == false
      if (w > 0) and (h > 0)
        pw = getHTMLUnitToUnits(w, 0, @pdfunit, true) * @img_scale * @k
        ph = getHTMLUnitToUnits(h, 0, @pdfunit, true) * @img_scale * @k
        imsize = [pw, ph]
      else
        Error('[Image] Unable to get image width and height: ' + file)
      end
    end
  end
  # get original image width and height in pixels
  pixw = imsize[0]
  pixh = imsize[1]

  # calculate image width and height on document
  if (w <= 0) and (h <= 0)
    # convert image size to document unit
    w = pixelsToUnits(pixw)
    h = pixelsToUnits(pixh)
  elsif w <= 0
    w = h * pixw / pixh
  elsif h <= 0
    h = w * pixh / pixw
  elsif fitbox and (w > 0) and (h > 0)
    # scale image dimensions proportionally to fit within the (:w, :h) box
    if ((w * pixh) / (h * pixw)) < 1
      h = w * pixh / pixw
    else
      w = h * pixw / pixh
    end
  end

  # resize image to be contained on a single page          # fix at page break case.
  if fitonpage
    ratio_wh = w / h
    if (@t_margin + h) > @page_break_trigger
      h = @page_break_trigger - @t_margin
      w = h * ratio_wh
    end
    if !@rtl and ((x + w) > (@w - @r_margin))
      w = @w - @r_margin - x
      h = w / ratio_wh
    elsif @rtl and ((x - w) < @l_margin)
      w = x - @l_margin
      h = w / ratio_wh
    end
  end

  # Check whether we need a new page first as this does not fit
  prev_x = @x
  if checkPageBreak(h, y)
    y = @y
    if @rtl
      x += prev_x - @x
    else
      x += @x - prev_x
    end
  end
  # resize image to be contained on a single page
  if fitonpage
    ratio_wh = w / h
    if (y + h) > @page_break_trigger
      h = @page_break_trigger - y
      w = h * ratio_wh
    end
    if !@rtl and ((x + w) > (@w - @r_margin))
      w = @w - @r_margin - x
      h = w / ratio_wh
    elsif @rtl and ((x - w) < @l_margin)
      w = x - @l_margin
      h = w / ratio_wh
    end
  end
  # calculate new minimum dimensions in pixels
  neww = (w * @k * dpi / @dpi).round
  newh = (h * @k * dpi / @dpi).round
  # check if resize is necessary (resize is used only to reduce the image)
  newsize = neww * newh
  pixsize = pixw * pixh
  if resize == 2
    resize = true
  elsif newsize >= pixsize
    resize = false
  end

  # check if image has been already added on document
  newimage = true
  if @imagekeys.include?(file)
    newimage = false;
    # get existing image data
    info = getImageBuffer(file)
    # check if the newer image is larger
    oldsize = info['w'] * info['h']
    if ((oldsize < newsize) and resize) or ((oldsize < pixsize) and !resize)
      newimage = true
    end
  end
  if newimage
    #First use of image, get info
    if (type == '')
      type = getImageFileType(file, imsize)
    else
      type = type.downcase
      type = 'jpeg' if type == 'jpg'
    end

    info = false
    if !resize
      if (type == 'jpeg')
        info=parsejpeg(file)
      elsif (type == 'png')
        info=parsepng(file);
      elsif (type == 'gif')
        tmpFile = imageToPNG(file)
        if tmpFile != false
          info=parsepng(tmpFile.path)
          tmpFile.delete
        end
      else
        #Allow for additional formats
        mtd='parse' + type;
        unless self.respond_to?(mtd, true)
          Error('Unsupported image type: ' + type);
        end
        info=send(mtd, file);
      end
      if info == 'pngalpha' and ismask == false and Object.const_defined?(:Magick)
        info = ImagePngAlpha(file, x, y, w, h, 'PNG', link, align, resize, dpi, palign)
        if false != info
          return
        end
      end
    end
    if !info
      if Object.const_defined?(:Magick)
        # RMagick library

        ### T.B.D ### TCPDF 5.0.000 ###
        # if type == 'SVG'
        # else
          img = Magick::ImageList.new(file)
        # end
        if resize
          img.resize(neww,newh)
        end
        img.format = 'JPEG'
        tmpname = Tempfile.new(File::basename(file), @@k_path_cache)
        tmpname.binmode
        jpeg_quality = @jpeg_quality
        tmpname.print img.to_blob { self.quality = jpeg_quality }
        tmpname.close

        info = parsejpeg(tmpname.path)
        tmpname.delete
      else
        return false
      end
    end

    if info == false
      # If false, we cannot process image
      return false
    end
    if ismask
      # force grayscale
      info['cs'] = 'DeviceGray'
    end
    info['i'] = @numimages
    if !@imagekeys.include?(file)
      info['i'] += 1
    end
    if imgmask != false
      info['masked'] = imgmask
    end
    # add image to document
    setImageBuffer(file, info)
  end

  # set alignment
  @img_rb_y = y + h
  # set alignment
  if @rtl
    if palign == 'L'
      ximg = @l_margin
    elsif palign == 'C'
      ximg = (@w + @l_margin - @r_margin - w) / 2
    elsif palign == 'R'
      ximg = @w - @r_margin - w
    else
      ximg = x - w
    end
    @img_rb_x = ximg
  else
    if palign == 'L'
      ximg = @l_margin
    elsif palign == 'C'
      ximg = (@w + @l_margin - @r_margin - w) / 2
    elsif palign == 'R'
      ximg = @w - @r_margin - w
    else
      ximg = x
    end
    @img_rb_x = ximg + w
  end
  if ismask or hidden
    # image is not displayed
    return info['i']
  end
  xkimg = ximg * @k
  out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q', w * @k, h * @k, xkimg, (@h -(y + h)) * @k, info['i']))

  if border != 0
    bx = x
    by = y
    @x = ximg
    if @rtl
      @x += w
    end
    @y = y
    Cell(w, h, '', border, 0, '', 0, '', 0)
    @x = bx
    @y = by
  end

  if link and !link.empty?
    Link(ximg, y, w, h, link)
  end

  # set pointer to align the successive text/objects
  case align
  when 'T'
    @y = y
    @x = @img_rb_x
  when 'M'
    @y = y + (h/2).round
    @x = @img_rb_x
  when 'B'
    @y = @img_rb_y
    @x = @img_rb_x
  when 'N'
    SetY(@img_rb_y)
  end
  @endlinex = @img_rb_x
  return info['i']
end

#image_alpha_mask(file) ⇒ Object



5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
# File 'lib/rbpdf.rb', line 5046

def image_alpha_mask(file)
  img = Magick::ImageList.new(file)

  img2 = img.separate(Magick::OpacityChannel)
  img = img2.negate(true)

  #use a temporary file....
  tmpFile = Tempfile.new(['msk_', '.png'], @@k_path_cache)
  tmpFile.binmode
  tmpFile.print img.to_blob
  tmpFile
ensure
  tmpFile.close unless tmpFile.nil?
end

#intToRoman(number) ⇒ Object Also known as: int_to_roman

Returns the Roman representation of an integer number

@param int :number

to convert

@return string

roman representation of the specified number

@access public
@since 4.4.004 (2008-12-10)


13242
13243
13244
13245
13246
13247
13248
13249
13250
13251
13252
13253
13254
13255
13256
13257
13258
13259
13260
13261
13262
13263
13264
13265
13266
13267
13268
13269
13270
13271
13272
13273
13274
13275
13276
13277
13278
13279
13280
13281
13282
13283
13284
13285
13286
13287
13288
13289
13290
13291
13292
13293
13294
13295
13296
13297
# File 'lib/rbpdf.rb', line 13242

def intToRoman(number)
  roman = ''
  while number >= 1000
    roman << 'M'
    number -= 1000
  end
  while number >= 900
    roman << 'CM'
    number -= 900
  end
  while number >= 500
    roman << 'D'
    number -= 500
  end
  while number >= 400
    roman << 'CD'
    number -= 400
  end
  while number >= 100
    roman << 'C'
    number -= 100
  end
  while number >= 90
    roman << 'XC'
    number -= 90
  end
  while number >= 50
    roman << 'L'
    number -= 50
  end
  while number >= 40
    roman << 'XL'
    number -= 40
  end
  while number >= 10
    roman << 'X'
    number -= 10
  end
  while number >= 9
    roman << 'IX'
    number -= 9
  end
  while number >= 5
    roman << 'V'
    number -= 5
  end
  while number >= 4
    roman << 'IV'
    number -= 4
  end
  while number >= 1
    roman << 'I'
    number -= 1
  end
  return roman
end

#isRTLTextDirObject Also known as: is_rtl_text_dir

Return the current temporary RTL status

@return boolean
@access public
@since 4.8.014 (2009-11-04)


996
997
998
# File 'lib/rbpdf.rb', line 996

def isRTLTextDir()
  return (@rtl or (@tmprtl == 'R'))
end

#lastPage(resetmargins = false) ⇒ Object Also known as: last_page

Reset pointer to the last document page.

@param boolean :resetmargins

if true reset left, right, top margins and Y position.

@access public
@since 2.0.000 (2008-01-04)
@see

setPage(), getPage(), getNumPages()



1568
1569
1570
# File 'lib/rbpdf.rb', line 1568

def lastPage(resetmargins=false)
  setPage(getNumPages(), resetmargins)
end

#Line(x1, y1, x2, y2, style = nil) ⇒ Object Also known as: line

Draws a line between two points.

@param float :x1

Abscissa of first point

@param float :y1

Ordinate of first point

@param float :x2

Abscissa of second point

@param float :y2]

Ordinate of second point

@param hash :style

Line style. Array like for SetLineStyle SetLineStyle. Default value: default line style (empty array).

@access public
@since 1.0
@see

SetLineWidth(), SetDrawColor(), SetLineStyle()



8355
8356
8357
8358
8359
8360
8361
8362
# File 'lib/rbpdf.rb', line 8355

def Line(x1, y1, x2, y2, style=nil)
  if style.is_a? Hash
    SetLineStyle(style)
  end
  outPoint(x1, y1)
  outLine(x2, y2)
  out('S')
end

Puts a link on a rectangular area of the page. Text or image links are generally put via Cell(), Write() or Image(), but this method can be useful for instance to define a clickable area inside an image.

@param float :x

Abscissa of the upper-left corner of the rectangle

@param float :y

Ordinate of the upper-left corner of the rectangle

@param float :w

Width of the rectangle

@param float :h

Height of the rectangle

@param mixed :link

URL or identifier returned by AddLink()

@param int :spaces

number of spaces on the text to link

@access public
@since 1.5
@see

AddLink(), Annotation(), Cell(), Write(), Image()



2945
2946
2947
# File 'lib/rbpdf.rb', line 2945

def Link(x, y, w, h, link, spaces=0)
  Annotation(x, y, w, h, link, {'Subtype'=>'Link'}, spaces)
end

#Ln(h = '', cell = false) ⇒ Object Also known as: ln

Performs a line break. The current abscissa goes back to the left margin and the ordinate increases by the amount passed in parameter.

@param float :h

The height of the break. By default, the value equals the height of the last printed cell.

@param boolean :cell

if true add a c_margin to the x coordinate

@access public
@since 1.0
@see

Cell()



5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
# File 'lib/rbpdf.rb', line 5235

def Ln(h='', cell=false)
  if (@num_columns > 0) and (@y == @columns[@current_column]['y']) and @columns[@current_column]['x'] and (@x == @columns[@current_column]['x'])
    # revove vertical space from the top of the column
    return
  end
  if cell
    cellmargin = @c_margin
  else
    cellmargin = 0
  end
  if @rtl
    @x = @w - @r_margin - cellmargin
  else
    @x = @l_margin + cellmargin
  end
  if h.is_a?(String)
    @y += @lasth
  else
    @y += h
  end
  @newline = true
end

#loggerObject



105
106
107
# File 'lib/rbpdf.rb', line 105

def logger
  Rails.logger
end

#movePage(frompage, topage) ⇒ Object Also known as: move_page

Move a page to a previous position.

@param int :frompage

number of the source page

@param int :topage

number of the destination page (must be less than :frompage)

@return

true in case of success, false in case of error.

@access public
@since 4.5.000 (2009-01-02)


13745
13746
13747
13748
13749
13750
13751
13752
13753
13754
13755
13756
13757
13758
13759
13760
13761
13762
13763
13764
13765
13766
13767
13768
13769
13770
13771
13772
13773
13774
13775
13776
13777
13778
13779
13780
13781
13782
13783
13784
13785
13786
13787
13788
13789
13790
13791
13792
13793
13794
13795
13796
13797
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810
13811
13812
13813
13814
13815
13816
13817
13818
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
13829
13830
13831
13832
13833
13834
13835
13836
13837
13838
13839
13840
13841
13842
13843
13844
13845
13846
13847
13848
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858
13859
13860
13861
13862
13863
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874
13875
13876
# File 'lib/rbpdf.rb', line 13745

def movePage(frompage, topage)
  if (frompage > @numpages) or (frompage <= topage)
    return false
  end
  if frompage == @page
    # close the page before moving it
    endPage()
  end
  # move all page-related states
  tmppage = @pages[frompage]
  tmppagedim = @pagedim[frompage]
  tmppagelen = @pagelen[frompage]
  tmpintmrk = @intmrk[frompage]
  if @footerpos[frompage]
    tmpfooterpos = @footerpos[frompage]
  end
  if @footerlen[frompage]
    tmpfooterlen = @footerlen[frompage]
  end
  if @transfmrk[frompage]
    tmptransfmrk = @transfmrk[frompage]
  end
  if @page_annots[frompage]
    tmpannots = @page_annots[frompage]
  end
  if @newpagegroup[frompage]
    tmpnewpagegroup = @newpagegroup[frompage]
  end
  frompage.downto(topage + 1) do |i|
    j = i - 1
    # shift pages down
    @pages[i] = @pages[j]
    @pagedim[i] = @pagedim[j]
    @pagelen[i] = @pagelen[j]
    @intmrk[i] = @intmrk[j]
    if @footerpos[j]
      @footerpos[i] = @footerpos[j]
    elsif footerpos[i]
      @footerpos[i] = nil
    end
    if @footerlen[j]
      @footerlen[i] = @footerlen[j]
    elsif @footerlen[i]
      @footerlen[i] = nil
    end
    if @transfmrk[j]
      @transfmrk[i] = @transfmrk[j]
    elsif @transfmrk[i]
      @transfmrk[i] = nil
    end
    if @page_annots[j]
      @page_annots[i] = @page_annots[j]
    elsif @page_annots[i]
      @page_annots[i] = nil
    end
    if @newpagegroup[j]
      @newpagegroup[i] = @newpagegroup[j]
    elsif @newpagegroup[i]
      @newpagegroup[i] = nil
    end
  end
  @pages[topage] = tmppage
  @pagedim[topage] = tmppagedim
  @pagelen[topage] = tmppagelen
  @intmrk[topage] = tmpintmrk
  if tmpfooterpos
    @footerpos[topage] = tmpfooterpos
  elsif @footerpos[topage]
    @footerpos[topage] = nil
  end
  if tmpfooterlen
    @footerlen[topage] = tmpfooterlen
  elsif @footerlen[topage]
    @footerlen[topage] = nil
  end
  if tmptransfmrk
    @transfmrk[topage] = tmptransfmrk
  elsif @transfmrk[topage]
    @transfmrk[topage] = nil
  end
  if tmpannots
    @page_annots[topage] = tmpannots
  elsif @page_annots[topage]
    @page_annots[topage] = nil
  end
  if tmpnewpagegroup
    @newpagegroup[topage] = tmpnewpagegroup
  elsif @newpagegroup[topage]
    @newpagegroup[topage] = nil
  end
  # adjust outlines
  tmpoutlines = @outlines
  tmpoutlines.each_with_index do |outline, key|
    if (outline[:p] >= topage) and (outline[:p] < frompage)
      @outlines[key][:p] = outline[:p] + 1
    elsif outline[:p] == frompage
      @outlines[key][:p] = topage
    end
  end
  # adjust links
  tmplinks = @links
  tmplinks.each_with_index do |link, key|
    next if link.nil?
    if (link[0] >= topage) and (link[0] < frompage)
      @links[key][0] = link[0] + 1
    elsif link[0] == frompage
      @links[key][0] = topage
    end
  end
  ### T.B.D ### TCPDF 5.0.001 ###
  # adjust javascript
  #tmpjavascript = @javascript
  #global jfrompage, jtopage
  #jfrompage = frompage
  #jtopage = topage
  #@javascript = preg_replace_callback('/this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/',
  #create_function('$matches', 'global $jfrompage, $jtopage;
  #  pagenum = matches[3].to_i + 1
  #  if (pagenum >= jtopage) and (pagenum < jfrompage)
  #    newpage = pagenum + 1
  #  elsif pagenum == jfrompage
  #    newpage = jtopage
  #  else
  #    newpage = pagenum
  #  end
  #  newpage -= 1
  #  return "this.addField(\'".$matches[1]."\',\'".$matches[2]."\',".$newpage."";'), $tmpjavascript);

  # return to last page
  lastPage(true)
  return true
end

#MultiCell(w, h, txt, border = 0, align = 'J', fill = 0, ln = 1, x = '', y = '', reseth = true, stretch = 0, ishtml = false, autopadding = true, maxh = 0) ⇒ Object Also known as: multi_cell

This method allows printing text with line breaks. They can be automatic (as soon as the text reaches the right border of the cell) or explicit (via the n character). As many cells as necessary are output, one below the other. Text can be aligned, centered or justified. The cell block can be framed and the background painted.

@param float :w

Width of cells. If 0, they extend up to the right margin of the page.

@param float :h

Cell minimum height. The cell extends automatically if needed.

@param string :txt

String to print

@param mixed :border

Indicates if borders must be drawn around the cell block. The value can be either a number:

  • 0: no border (default)

  • 1: frame

or a string containing some or all of the following characters (in any order):

  • L: left

  • T: top

  • R: right

  • B: bottom

@param string :align

Allows to center or align the text. Possible values are:

  • L or empty string: left align

  • C: center

  • R: right align

  • J: justification (default value when :ishtml=false)

@param int :fill

Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.

@param int :ln

Indicates where the current position should go after the call. Possible values are:

  • 0: to the right

  • 1: to the beginning of the next line [DEFAULT]

  • 2: below

@param float :x

x position in user units

@param float :y

y position in user units

@param boolean :reseth

if true reset the last cell height (default true).

@param int :stretch

stretch carachter mode:

  • 0 = disabled

  • 1 = horizontal scaling only if necessary

  • 2 = forced horizontal scaling

  • 3 = character spacing only if necessary

  • 4 = forced character spacing

@param boolean :ishtml

set to true if :txt is HTML content (default = false).

@param boolean :autopadding

if true, uses internal padding and automatically adjust it to account for line width.

@param float :maxh

maximum height. It should be >= :h and less then remaining space to the bottom of the page, or 0 for disable this feature. This feature works only when :ishtml=false.

@return int

Rerurn the number of cells or 1 for html mode.

@access public
@since 1.3
@see

SetFont(), SetDrawColor(), SetFillColor(), SetTextColor(), SetLineWidth(), Cell(), Write(), SetAutoPageBreak()



3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
# File 'lib/rbpdf.rb', line 3766

def MultiCell(w, h, txt, border=0, align='J', fill=0, ln=1, x='', y='', reseth=true, stretch=0, ishtml=false, autopadding=true, maxh=0)
  w = 0 unless w.is_a?(Numeric)
  h = 0 unless h.is_a?(Numeric)

  if empty_string(@lasth) or reseth
    # set row height
    @lasth = @font_size * @cell_height_ratio
  end
   
  if !empty_string(y)
    SetY(y)
  else
    y = GetY()
  end
  resth = 0
  if !@in_footer and (y + h > @page_break_trigger)
    # spit cell in two pages
    newh = @page_break_trigger - y
    resth = h - newh # cell to be printed on the next page
    h = newh
  end
  # get current page number
  startpage = @page

  if !empty_string(x)
    SetX(x)
  else
    x = GetX()
  end

  if empty_string(w) or (w <= 0)
    if @rtl
      w = @x - @l_margin
    else
      w = @w - @r_margin - @x
    end
  end

  # store original margin values
  l_margin = @l_margin
  r_margin = @r_margin

  if @rtl
    SetRightMargin(@w - @x)
    SetLeftMargin(@x - w)
  else
    SetLeftMargin(@x)
    SetRightMargin(@w - @x - w)
  end

  starty = @y
  if autopadding
    # Adjust internal padding
    if @c_margin < (@line_width / 2)
      @c_margin = @line_width / 2
    end
    # Add top space if needed
    if (@lasth - @font_size) < @line_width
      @y += @line_width / 2
    end
    # add top padding
    @y += @c_margin
  end

  if ishtml
    # ******* Write HTML text
    writeHTML(txt, true, false, reseth, true, align)
    nl = 1
  else
    # ******* Write text
    nl = Write(@lasth, txt, '', 0, align, true, stretch, false, true, maxh)
  end

  if autopadding
    # add bottom padding
    @y += @c_margin
    # Add bottom space if needed
    if (@lasth - @font_size) < @line_width
      @y += @line_width / 2
    end
  end

  # Get end-of-text Y position
  currentY = @y
  # get latest page number
  end_page = @page
  if resth > 0
    skip = end_page - startpage
    tmpresth = resth
    while tmpresth > 0
      if skip <= 0
        # add a page (or trig AcceptPageBreak() for multicolumn mode)
        checkPageBreak(@page_break_trigger + 1)
      end
      tmpresth -= (@h - @t_margin - @b_margin)
      skip -= 1
    end
    currentY = @y
    end_page = @page
  end

  # check if a new page has been created
  if end_page > startpage
    # design borders around HTML cells.
    for page in startpage..end_page
      setPage(page)
      if page == startpage
        # first page
        @y = starty # put cursor at the beginning of cell on the first page
        h = @h - starty - @b_margin
        cborder = getBorderMode(border, position='start')
      elsif page == end_page
        # last page
        @y = @t_margin # put cursor at the beginning of last page
        h = currentY - @t_margin
        if resth > h
          h = resth
        end
        cborder = getBorderMode(border, position='end')
      else
        @y = @t_margin # put cursor at the beginning of the current page
        h = @h - @t_margin - @b_margin
        resth -= h
        cborder = getBorderMode(border, position='middle')
      end
      nx = x
      # account for margin changes
      if page > startpage
        if @rtl and (@pagedim[page]['orm'] != @pagedim[startpage]['orm'])
          nx = x + (@pagedim[page]['orm'] - @pagedim[startpage]['orm'])
        elsif !@rtl and (@pagedim[page]['olm'] != @pagedim[startpage]['olm'])
          nx = x + (@pagedim[page]['olm'] - @pagedim[startpage]['olm'])
        end
      end
      SetX(nx)
      ccode = getCellCode(w, h, '', cborder, 1, '', fill, '', 0, false)
      if (cborder != 0) or (fill == 1)
        pagebuff = getPageBuffer(@page)
        pstart = pagebuff[0, @intmrk[@page]]
        pend = pagebuff[@intmrk[@page]..-1]
        setPageBuffer(@page, pstart + ccode + "\n" + pend)
        @intmrk[@page] += (ccode + "\n").length
      end
    end
  else
    h = [h, currentY - y].max
    # put cursor at the beginning of text
    SetY(y)
    SetX(x)
    # design a cell around the text
    ccode = getCellCode(w, h, '', border, 1, '', fill, '', 0, true)
    if (border != 0) or (fill == 1)
      if !@transfmrk[@page].nil?
        pagemark = @transfmrk[@page]
        @transfmrk[@page] += (ccode + "\n").length
      elsif @in_footer
        pagemark = @footerpos[@page]
        @footerpos[@page] += (ccode + "\n").length
      else
        pagemark = @intmrk[@page]
        @intmrk[@page] += (ccode + "\n").length
      end
      pagebuff = getPageBuffer(@page)
      pstart = pagebuff[0, pagemark]
      pend = pagebuff[pagemark..-1].to_s
      setPageBuffer(@page, pstart + ccode + "\n" + pend)
    end
  end
  
  # Get end-of-cell Y position
  currentY = GetY()

  # restore original margin values
  SetLeftMargin(l_margin)
  SetRightMargin(r_margin)

  if ln > 0
    # Go to the beginning of the next line
    SetY(currentY)
    if ln == 2
      SetX(x + w)
    end
  else
    # go left or right by case
    setPage(startpage)
    @y = y
    SetX(x + w)
  end

  setContentMark()
  return nl
end

#objclone(object) ⇒ Object

Creates a copy of a class object

@param object :object

class object to be cloned

@return

cloned object

@access public
@since 4.5.029 (2009-03-19)


14352
14353
14354
14355
14356
14357
14358
14359
14360
14361
14362
# File 'lib/rbpdf.rb', line 14352

def objclone(object)
  if @diskcache
    newobj = object.dup
    newobj.cache_file_length = object.cache_file_length.dup
    newobj.prev_pages = object.prev_pages.dup
    newobj.pages = object.pages.dup
    return newobj
  else
    return Marshal.load(Marshal.dump(object))
  end
end

#OpenObject

This method begins the generation of the PDF document. It is not necessary to call it explicitly because AddPage() does it automatically.

  • Note: no page is created by this method

@access public
@since 1.0
@see

AddPage(), Close()



1470
1471
1472
1473
# File 'lib/rbpdf.rb', line 1470

def Open()
  #Begin document
  @state = 1
end

#Output(name = '', dest = '') ⇒ Object Also known as: output

Send the document to a given destination: string, local file or browser. In the last case, the plug-in may be used (if present) or a download (“Save as” dialog box) may be forced. The method first calls Close() if necessary to terminate the document.

@param string :name

The name of the file when saved. Note that special characters are removed and blanks characters are replaced with the underscore character.

@param string :dest

Destination where to send the document. It can take one of the following values:

  • I: send the file inline to the browser (default). The plug-in is used if available. The name given by name is used when one selects the “Save as” option on the link generating the PDF.

  • D: send to the browser and force a file download with the name given by name.

  • F: save to a local server file with the name given by name.

  • S: return the document as a string. name is ignored.

  • FI: equivalent to F + I option

  • FD: equivalent to F + D option

@access public
@since 1.0
@see

Close()



5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
# File 'lib/rbpdf.rb', line 5393

def Output(name='', dest='')
  #Output PDF to some destination
  #Finish document if necessary
  lastPage()
  if (@state < 3)
    Close();
  end
  #Normalize parameters
  # Boolean no longer supported
  # if (dest.is_a?(Boolean))
  #   dest = dest ? 'D' : 'F';
  # end
  dest = dest.upcase
  if (dest=='')
    if (name=='')
      name='doc.pdf';
      dest='I';
    else
      dest='F';
    end
  end
  case (dest)
  when 'I'
      # This is PHP specific code
      ##Send to standard output
      # if (ob_get_contents())
      #   Error('Some data has already been output, can\'t send PDF file');
      # end
      # if (php_sapi_name()!='cli')
      #   #We send to a browser
      #   header('Content-Type: application/pdf');
      #   if (headers_sent())
      #     Error('Some data has already been output to browser, can\'t send PDF file');
      #   end
      #   header('Content-Length: ' + @buffer.length);
      #   header('Content-disposition: inline; filename="' + name + '"');
      # end
    return getBuffer
  when 'D'
      # PHP specific
      #Download file
      # if (ob_get_contents())
      #   Error('Some data has already been output, can\'t send PDF file');
      # end
      # if (!_SERVER['HTTP_USER_AGENT'].nil? && SERVER['HTTP_USER_AGENT'].include?('MSIE'))
      #   header('Content-Type: application/force-download');
      # else
      #   header('Content-Type: application/octet-stream');
      # end
      # if (headers_sent())
      #   Error('Some data has already been output to browser, can\'t send PDF file');
      # end
      # header('Content-Length: '+ @buffer.length);
      # header('Content-disposition: attachment; filename="' + name + '"');
    return getBuffer
  when 'F', 'FI', 'FD'
    # Save PDF to a local file
    if @diskcache
      FileUtils.copy(@buffer.path, name)
    else
      open(name,'wb') do |f|
        f.write(@buffer)
      end
    end
    if dest == 'FI'
    # This is PHP specific code
    #  # send headers to browser
    #  header('Content-Type: application/pdf')
    #  header('Cache-Control: public, must-revalidate, max-age=0') # HTTP/1.1
    #  header('Pragma: public')
    #  header('Expires: Sat, 26 Jul 1997 05:00:00 GMT') # Date in the past
    #  header('Last-Modified: ' + gmdate('D, d M Y H:i:s') + ' GMT')
    #  header('Content-Length: ' + filesize(name))
    #  header('Content-Disposition: inline; filename="' + File.basename(name) + '";')
      # send document to the browser
      data = ''
      open(name) do |f| data<< f.read ;end
      return data
    elsif dest == 'FD'
    # This is PHP specific code
    #  # send headers to browser
    #  if ob_get_contents()
    #    Error('Some data has already been output, can\'t send PDF file')
    #  end
    #  header('Content-Description: File Transfer')
    #  if headers_sent())
    #    Error('Some data has already been output to browser, can\'t send PDF file')
    #  end
    #  header('Cache-Control: public, must-revalidate, max-age=0') # HTTP/1.1
    #  header('Pragma: public')
    #  header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); # Date in the past
    #  header('Last-Modified: ' + gmdate('D, d M Y H:i:s') + ' GMT')
    #  # force download dialog
    #  header('Content-Type: application/force-download')
    #  header('Content-Type: application/octet-stream', false)
    #  header('Content-Type: application/download', false)
    #  header('Content-Type: application/pdf', false)
    #  # use the Content-Disposition header to supply a recommended filename
    #  header('Content-Disposition: attachment; filename="' + File.basename(name) + '";')
    #  header('Content-Transfer-Encoding: binary')
    #  header('Content-Length: ' + filesize(name))
      # send document to the browser
      data = ''
      open(name) do |f| data<< f.read ;end
      return data
    end
  when 'S'
    # Returns PDF as a string
    return getBuffer
  else
    Error('Incorrect output destination: ' + dest);
  end
  return '';
ensure
  destroy(true)
end

#PageNoObject Also known as: page_no

Returns the current page number.

@return int

page number

@access public
@since 1.0
@see

alias_nb_pages()



2141
2142
2143
2144
# File 'lib/rbpdf.rb', line 2141

def PageNo()
  #Get current page number
  return @page;
end

#PageNoFormattedObject Also known as: page_no_formatted

Returns the current page number formatted as a string.

@access public
@since 4.2.005 (2008-11-06)
@see

PaneNo(), formatPageNumber()



9843
9844
9845
# File 'lib/rbpdf.rb', line 9843

def PageNoFormatted()
  return formatPageNumber(PageNo())
end

#PieSector(xc, yc, r, a, b, style = 'FD', cw = true, o = 90) ⇒ Object Also known as: pie_sector

Draw the sector of a circle. It can be used for instance to render pie charts.

@param float :xc

abscissa of the center.

@param float :yc

ordinate of the center.

@param float :r

radius.

@param float :a

start angle (in degrees).

@param float :b

end angle (in degrees).

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param float :cw

indicates whether to go clockwise (default: true).

@param float :o

origin of angles (0 for 3 o’clock, 90 for noon, 180 for 9 o’clock, 270 for 6 o’clock). Default: 90.

@author

Maxime Delorme, Nicola Asuni

@since 3.1.000 (2008-06-09)
@access public


10087
10088
10089
# File 'lib/rbpdf.rb', line 10087

def PieSector(xc, yc, r, a, b, style='FD', cw=true, o=90)
  PieSectorXY(xc, yc, r, r, a, b, style, cw, o)
end

#PieSectorXY(xc, yc, rx, ry, a, b, style = 'FD', cw = false, o = 0, nc = 2) ⇒ Object Also known as: pie_sector_xy

Draw the sector of an ellipse. It can be used for instance to render pie charts.

@param float :xc

abscissa of the center.

@param float :yc

ordinate of the center.

@param float :rx

the x-axis radius.

@param float :ry

the y-axis radius.

@param float :a

start angle (in degrees).

@param float :b

end angle (in degrees).

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param float :cw

indicates whether to go clockwise.

@param float :o

origin of angles (0 for 3 o’clock, 90 for noon, 180 for 9 o’clock, 270 for 6 o’clock).

@param integer :nc

Number of curves used to draw a 90 degrees portion of arc.

@author

Maxime Delorme, Nicola Asuni

@since 3.1.000 (2008-06-09)
@access public


10109
10110
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122
10123
10124
10125
10126
10127
10128
# File 'lib/rbpdf.rb', line 10109

def PieSectorXY(xc, yc, rx, ry, a, b, style='FD', cw=false, o=0, nc=2)
  if @rtl
    xc = @w - xc
  end
  op = getPathPaintOperator(style)
  ### not use ###
  #if op == 'f'
  #  line_style = nil
  #end
  if cw
    d = b
    b = 360 - a + o
    a = 360 - d + o
  else
    b += o
    a += o
  end
  outellipticalarc(xc, yc, rx, ry, 0, a, b, true, nc)
  out(op)
end

#pixelsToUnits(px) ⇒ Object Also known as: pixels_to_units

Converts pixels to Units.

@param int

:px pixels

@return float

millimeters

@access public
@see

setImageScale(), getImageScale()



8019
8020
8021
# File 'lib/rbpdf.rb', line 8019

def pixelsToUnits(px)
  return (px.to_f / (@img_scale * @k))
end

#Polygon(p, style = '', line_style = nil, fill_color = nil, closed = true) ⇒ Object Also known as: polygon

Draws a polygon.

@param array :p

Points 0 to (np - 1). Array with values (x0, y0, x1, y1,…, x(np-1), y(np - 1))

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param array :line_style

Line style of polygon. Array with keys among the following:

  • all: Line style of all lines. Array like for SetLineStyle SetLineStyle.

  • 0 to (:np - 1): Line style of each line. Array like for SetLineStyle SetLineStyle.

If a key is not present or is null, not draws the line. Default value is default line style (empty array).

@param array :fill_color

Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array).

@param boolean :closed

if true the polygon is closes, otherwise will remain open

@access public
@since 2.1.000 (2008-01-08)


8643
8644
8645
8646
8647
8648
8649
8650
8651
8652
8653
8654
8655
8656
8657
8658
8659
8660
8661
8662
8663
8664
8665
8666
8667
8668
8669
8670
8671
8672
8673
8674
8675
8676
8677
8678
8679
8680
8681
8682
8683
8684
8685
8686
8687
8688
8689
8690
8691
8692
8693
8694
8695
8696
8697
8698
8699
8700
8701
8702
8703
8704
8705
8706
8707
8708
8709
8710
8711
8712
8713
8714
8715
# File 'lib/rbpdf.rb', line 8643

def Polygon(p, style='', line_style=nil, fill_color=nil, closed=true)
  style = '' if style.nil?
  nc = p.length # number of coordinates
  np = nc / 2 # number of points
  if closed
    # close polygon by adding the first 2 points at the end (one line)
    0.upto(3) do |i|
      p[nc + i] = p[i]
    end
    # copy style for the last added line
    if line_style
      if line_style.is_a? Array and line_style[0]
        line_style[np] = line_style[0]
      elsif line_style.is_a? Hash and line_style['all']
        line_style[np] = line_style['all']
      end
    end
    nc += 4
  end
  if (nil != style.index('F')) and fill_color
    SetFillColorArray(fill_color)
  end
  op = getPathPaintOperator(style)
  if op == 'f'
    line_style = []
  end
  draw = true
  if line_style
    if line_style.is_a? Hash and line_style['all']
      SetLineStyle(line_style['all'])
    else
      draw = false
      if op == 'B'
        # draw fill
        op = 'f'
        outPoint(p[0], p[1])
        2.step(nc - 1, 2) do |i|
          outLine(p[i], p[i + 1])
        end
        out(op)
      end
      # draw outline
      outPoint(p[0], p[1])
      2.step(nc - 1, 2) do |i|
        line_num = i / 2 - 1
        if line_style[line_num]
          if line_style[line_num] != 0
            if line_style[line_num].is_a? Hash
              out('S')
              SetLineStyle(line_style[line_num])
              outPoint(p[i - 2], p[i - 1])
              outLine(p[i], p[i + 1])
              out('S')
              outPoint(p[i], p[i + 1])
            else
              outLine(p[i], p[i + 1])
            end
          end
        else
          outLine(p[i], p[i + 1])
        end
      end
      out(op)
    end
  end
  if draw
    outPoint(p[0], p[1])
    2.step(nc - 1, 2) do |i|
      outLine(p[i], p[i + 1])
    end
    out(op)
  end
end

#PolyLine(p, style = '', line_style = nil, fill_color = nil) ⇒ Object Also known as: poly_line

Draws a polygonal line

@param array :p

Points 0 to (:np - 1). Array with values (x0, y0, x1, y1,…, x(np-1), y(np - 1))

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param array :line_style

Line style of polygon. Array with keys among the following:

  • all: Line style of all lines. Array like for SetLineStyle SetLineStyle.

  • 0 to (:np - 1): Line style of each line. Array like for SetLineStyle SetLineStyle.

If a key is not present or is null, not draws the line. Default value is default line style (empty array).

[@param array :fill_color Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array). [@param boolean :closed if true the polygon is closes, otherwise will remain open

@access public
@since 4.8.003 (2009-09-15)


8624
8625
8626
# File 'lib/rbpdf.rb', line 8624

def PolyLine(p, style='', line_style=nil, fill_color=nil)
  Polygon(p, style, line_style, fill_color, false)
end

#Rect(x, y, w, h, style = '', border_style = {}, fill_color = {}) ⇒ Object Also known as: rect

Draws a rectangle.

@param float :x

Abscissa of upper-left corner (or upper-right corner for RTL language).

@param float :y

Ordinate of upper-left corner (or upper-right corner for RTL language).

@param float :w

Width.

@param float :h

Height.

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

  • all: Line style of all borders. Array like for SetLineStyle SetLineStyle.

  • L, T, R, B or combinations: Line style of left, top, right or bottom border. Array like for SetLineStyle SetLineStyle.

If a key is not present or is null, not draws the border. Default value: default line style (empty array).

@param array :border_style

Border style of rectangle. Array like for SetLineStyle SetLineStyle. Default value: default line style (empty array).

@param array :fill_color

Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array).

@access public
@since 1.0
@see

SetLineStyle()



8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
# File 'lib/rbpdf.rb', line 8382

def Rect(x, y, w, h, style='', border_style={}, fill_color={})
  if style.index('F') != nil and !fill_color.empty?
    SetFillColorArray(fill_color)
  end
  op = getPathPaintOperator(style)
  if !border_style or !border_style['all'].nil?
    if !border_style['all'].nil? and border_style['all']
      SetLineStyle(border_style['all'])
      border_style = {}
    end
  end
  outRect(x, y, w, h, op)

  if border_style
    border_style2 = {}
    border_style.each { |line, value|
      length = line.length
      0.upto(length - 1) do |i|
        border_style2[line[i]] = value
      end
    }
    border_style = border_style2
    if !border_style['L'].nil? and border_style['L']
      Line(x, y, x, y + h, border_style['L'])
    end
    if !border_style['T'].nil? and border_style['T']
      Line(x, y, x + w, y, border_style['T'])
    end
    if !border_style['R'].nil? and border_style['R']
      Line(x + w, y, x + w, y + h, border_style['R'])
    end
    if !border_style['B'].nil? and border_style['B']
      Line(x, y + h, x + w, y + h, border_style['B'])
    end
  end
end

#RegularPolygon(x0, y0, r, ns, angle = 0, draw_circle = false, style = '', line_style = nil, fill_color = nil, circle_style = '', circle_outLine_style = nil, circle_fill_color = nil) ⇒ Object Also known as: regular_polygon

Draws a regular polygon.

@param float :x0

Abscissa of center point.

@param float :y0

Ordinate of center point.

@param float :r

Radius of inscribed circle.

@param integer :ns

Number of sides.

@param float :angle

Angle oriented (anti-clockwise). Default value: 0.

@param boolean :draw_circle

Draw inscribed circle or not. Default value: false.

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param array :line_style

Line style of polygon sides. Array with keys among the following:

  • all: Line style of all sides. Array like for SetLineStyle SetLineStyle.

  • 0 to (:ns - 1): Line style of each side. Array like for SetLineStyle SetLineStyle.

If a key is not present or is null, not draws the side. Default value is default line style (empty array).

@param array :fill_color

Fill color. Format: array(red, green, blue). Default value: default color (empty array).

@param string :circle_style

Style of rendering of inscribed circle (if draws). Possible values are:

  • D or empty string: Draw (default).

  • F: Fill.

  • DF or FD: Draw and fill.

  • CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).

  • CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).

@param array :circle_outLine_style

Line style of inscribed circle (if draws). Array like for SetLineStyle SetLineStyle. Default value: default line style (empty array).

@param array :circle_fill_color

Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array).

@access public
@since 2.1.000 (2008-01-08)


8745
8746
8747
8748
8749
8750
8751
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761
# File 'lib/rbpdf.rb', line 8745

def RegularPolygon(x0, y0, r, ns, angle=0, draw_circle=false, style='', line_style=nil, fill_color=nil, circle_style='', circle_outLine_style=nil, circle_fill_color=nil)
  draw_circle = false if draw_circle == 0
  if 3 > ns
    ns = 3
  end
  if draw_circle
    Circle(x0, y0, r, 0, 360, circle_style, circle_outLine_style, circle_fill_color)
  end
  p = []
  0.upto(ns -1) do |i|
    a = angle + i * 360 / ns
    a_rad = a * ::Math::PI / 180 # deg2rad
    p.push x0 + (r * ::Math.sin(a_rad))
    p.push y0 + (r * ::Math.cos(a_rad))
  end
  Polygon(p, style, line_style, fill_color)
end

#removeSHY(txt = '') ⇒ Object Also known as: remove_shy

Removes SHY characters from text.

@param string :txt

input string

@return string

without SHY characters.

@access public
@since (4.5.019) 2009-02-28


3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
# File 'lib/rbpdf.rb', line 3290

def removeSHY(txt='')
  txt = txt.dup
  # Unicode Data
  # Name : SOFT HYPHEN, commonly abbreviated as SHY
  # HTML Entity (decimal): &#173;
  # HTML Entity (hex): &#xad;
  # HTML Entity (named): &shy;
  # How to type in Microsoft Windows: [Alt +00AD] or [Alt 0173]
  # UTF-8 (hex): 0xC2 0xAD (c2ad)
  # UTF-8 character: chr(194).chr(173)

  txt.force_encoding('ASCII-8BIT') if txt.respond_to?(:force_encoding)
  txt.gsub!(/([\xc2]{1}[\xad]{1})/, '')
  if !@is_unicode
    txt.gsub!(/([\xad]{1})/, '')
    return txt
  end
  txt.force_encoding('UTF-8') if txt.respond_to?(:force_encoding)
  return txt
end

#revstrpos(haystack, needle, offset = 0) ⇒ Object

Find position of last occurrence of a substring in a string

@param string :haystack

The string to search in.

@param string :needle

substring to search.

@param int :offset

May be specified to begin searching an arbitrary number of characters into the string.

@return

Returns the position where the needle exists. Returns FALSE if the needle was not found.

@access public
@since 4.8.038 (2010-03-13)


14387
14388
14389
14390
14391
14392
14393
# File 'lib/rbpdf.rb', line 14387

def revstrpos(haystack, needle, offset = 0)
  length = haystack.length
  offset = (offset > 0) ? (length - offset) : offset.abs
  pos = haystack.reverse.index(needle.reverse, offset)

  return (pos.nil? ? nil : length - pos - needle.length)
end

#rollbackTransaction(this_self = false) ⇒ Object Also known as: rollback_transaction

This method allows to undo the latest transaction by returning the latest saved RBPDF object with startTransaction().

@param boolean :this_self

if true restores current class object to previous state without the need of reassignment via the returned value.

@return

RBPDF object.

@access public
@since 4.5.029 (2009-03-19)


14319
14320
14321
14322
14323
14324
14325
14326
14327
14328
14329
14330
14331
14332
14333
14334
14335
14336
14337
14338
14339
14340
14341
14342
# File 'lib/rbpdf.rb', line 14319

def rollbackTransaction(this_self=false)
  if @objcopy
    if @objcopy.diskcache
      # truncate files to previous values
      @objcopy.cache_file_length.each { |file, length|
        File.truncate(file, length) if File.exist?(file)
      }
      @pages.each_with_index do |file, i|
        if @prev_pages[i] and File.exist?(@prev_pages[i].path)
          File.delete(file.path)
        end
      end
    end
    destroy(true, true)
    if this_self
      objvars = @objcopy.instance_variables
      objvars.each {|key|
        eval("#{key} = @objcopy.instance_variable_get(key)") if key.to_s != '@objcopy'
      }
    end
    return @objcopy
  end
  return self
end

#Rotate(angle, x = "", y = "") ⇒ Object Also known as: rotate

Rotate object.

@param float :angle

angle in degrees for counter-clockwise rotation

@param int :x

abscissa of the rotation center. Default is current x position

@param int :y

ordinate of the rotation center. Default is current y position

@access public
@since 2.1.000 (2008-01-07)
@see

StartTransform(), StopTransform()



8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
# File 'lib/rbpdf.rb', line 8112

def Rotate(angle, x="", y="")
  if (x == '')
    x = @x
  end
  
  if (y == '')
    y = @y
  end
  
  y = (@h - y) * @k
  x *= @k

  # calculate elements of transformation matrix
  tm = []
  tm[0] = ::Math::cos(angle * ::Math::PI / 180) # deg2rad
  tm[1] = ::Math::sin(angle * ::Math::PI / 180) # deg2rad
  tm[2] = -tm[1]
  tm[3] = tm[0]
  tm[4] = x + tm[1] * y - tm[0] * x
  tm[5] = y - tm[0] * y - tm[1] * x

  # generate the transformation matrix
  Transform(tm)
end

#RoundedRect(x, y, w, h, r, round_corner = '1111', style = '', border_style = nil, fill_color = nil) ⇒ Object Also known as: rounded_rect

Draws a rounded rectangle.

@param float :x

Abscissa of upper-left corner.

@param float :y

Ordinate of upper-left corner.

@param float :w

Width.

@param float :h

Height.

@param float :r

the radius of the circle used to round off the corners of the rectangle.

@param string :round_corner

Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top left, top right, bottom right and bottom left. Default value: all rounded corner (“1111”).

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param array :border_style

Border style of rectangle. Array like for SetLineStyle SetLineStyle. Default value: default line style (empty array).

@param array :fill_color

Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array).

@access public
@since 2.1.000 (2008-01-08)


8837
8838
8839
# File 'lib/rbpdf.rb', line 8837

def RoundedRect(x, y, w, h, r, round_corner='1111', style='', border_style=nil, fill_color=nil)
  RoundedRectXY(x, y, w, h, r, r, round_corner, style, border_style, fill_color)
end

#RoundedRectXY(x, y, w, h, rx, ry, round_corner = '1111', style = '', border_style = nil, fill_color = nil) ⇒ Object Also known as: rounded_rect_xy

Draws a rounded rectangle.

@param float :x

Abscissa of upper-left corner.

@param float :y

Ordinate of upper-left corner.

@param float :w

Width.

@param float :h

Height.

@param float :rx

the x-axis radius of the ellipse used to round off the corners of the rectangle.

@param float :ry

the y-axis radius of the ellipse used to round off the corners of the rectangle.

@param string :round_corner

Draws rounded corner or not. String with a 0 (not rounded i-corner) or 1 (rounded i-corner) in i-position. Positions are, in order and begin to 0: top left, top right, bottom right and bottom left. Default value: all rounded corner (“1111”).

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param array :border_style

Border style of rectangle. Array like for SetLineStyle SetLineStyle. Default value: default line style (empty array).

@param array :fill_color

Fill color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K). Default value: default color (empty array).

@access public
@since 4.9.019 (2010-04-22)


8857
8858
8859
8860
8861
8862
8863
8864
8865
8866
8867
8868
8869
8870
8871
8872
8873
8874
8875
8876
8877
8878
8879
8880
8881
8882
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
8899
8900
8901
8902
8903
8904
8905
8906
8907
8908
8909
8910
8911
# File 'lib/rbpdf.rb', line 8857

def RoundedRectXY(x, y, w, h, rx, ry, round_corner='1111', style='', border_style=nil, fill_color=nil)
  style = '' if style.nil?
  if (round_corner == '0000') or ((rx == ry) and (rx == 0))
    # Not rounded
    Rect(x, y, w, h, style, border_style, fill_color)
    return
  end
  # Rounded
  if (nil != style.index('F')) and fill_color
    SetFillColorArray(fill_color)
  end
  op = getPathPaintOperator(style)
  if op == 'f'
    border_style = []
  end
  if border_style
    SetLineStyle(border_style)
  end
  myArc = 4 / 3 * (::Math.sqrt(2) - 1)
  outPoint(x + rx, y)
  xc = x + w - rx
  yc = y + ry
  outLine(xc, y)
  if round_corner[0,1] == '1'
    outCurve(xc + (rx * myArc), yc - ry, xc + rx, yc - (ry * myArc), xc + rx, yc)
  else
    outLine(x + w, y)
  end
  xc = x + w - rx
  yc = y + h - ry
  outLine(x + w, yc)
  if round_corner[1,1] == '1'
    outCurve(xc + rx, yc + (ry * myArc), xc + (rx * myArc), yc + ry, xc, yc + ry)
  else
    outLine(x + w, y + h)
  end
  xc = x + rx
  yc = y + h - ry
  outLine(xc, y + h)
  if round_corner[2,1] == '1'
    outCurve(xc - (rx * myArc), yc + ry, xc - rx, yc + (ry * myArc), xc - rx, yc)
  else
    outLine(x, y + h)
  end
  xc = x + rx
  yc = y + ry
  outLine(x, yc)
  if round_corner[3,1] == '1'
    outCurve(xc - rx, yc - (ry * myArc), xc - (rx * myArc), yc - ry, xc, yc - ry)
  else
    outLine(x, y)
    outLine(x + rx, y)
  end
  out(op)
end

#setAlpha(alpha, bm = 'Normal') ⇒ Object Also known as: set_alpha

Set alpha for stroking (CA) and non-stroking (ca) operations.

@param float :alpha

real value from 0 (transparent) to 1 (opaque)

@param string :bm

blend mode, one of the following: Normal, Multiply, Screen, Overlay, Darken, Lighten, ColorDodge, ColorBurn, HardLight, SoftLight, Difference, Exclusion, Hue, Saturation, Color, Luminosity

@access public
@since 3.0.000 (2008-03-27)


9960
9961
9962
9963
# File 'lib/rbpdf.rb', line 9960

def setAlpha(alpha, bm='Normal')
  gs = addExtGState({'ca' => alpha, 'CA' => alpha, 'BM' => '/' + bm, 'AIS' => 'false'})
  setExtGState(gs)
end

#SetAuthor(author) ⇒ Object Also known as: set_author

Defines the author of the document.

@param string :author

The name of the author.

@access public
@since 1.2
@see

SetCreator(), SetKeywords(), SetSubject(), SetTitle()



1417
1418
1419
1420
# File 'lib/rbpdf.rb', line 1417

def SetAuthor(author)
  #Author of document
  @author = author
end

#SetAutoPageBreak(auto, margin = 0) ⇒ Object Also known as: set_auto_page_break

Enables or disables the automatic page breaking mode. When enabling, the second parameter is the distance from the bottom of the page that defines the triggering limit. By default, the mode is on and the margin is 2 cm.

@param boolean :auto

Boolean indicating if mode should be on or off.

@param float :margin

Distance from the bottom of the page.

@access public
@since 1.0
@see

Cell(), MultiCell(), AcceptPageBreak()



1288
1289
1290
1291
1292
1293
# File 'lib/rbpdf.rb', line 1288

def SetAutoPageBreak(auto, margin=0)
  #Set auto page break mode and triggering margin
  @auto_page_break = auto
  @b_margin = margin
  @page_break_trigger = @h - margin
end

#SetBooklet(booklet = true, inner = -1,, outer = -1)) ⇒ Object Also known as: set_booklet

Set the booklet mode for double-sided pages.

@param boolean :booklet

true set the booklet mode on, fals eotherwise.

@param float :inner

Inner page margin.

@param float :outer

Outer page margin.

@access public
@since 4.2.000 (2008-10-29)


13128
13129
13130
13131
13132
13133
13134
13135
13136
# File 'lib/rbpdf.rb', line 13128

def SetBooklet(booklet=true, inner=-1, outer=-1)
  @booklet = booklet
  if inner >= 0
    @l_margin = inner
  end
  if outer >= 0
    @r_margin = outer
  end
end

#setCellHeightRatio(h) ⇒ Object Also known as: set_cell_height_ratio

Set the height of cell repect font height.

@param int :h

cell proportion respect font height (typical value = 1.25).

@access public
@since 3.0.014 (2008-06-04)


9986
9987
9988
# File 'lib/rbpdf.rb', line 9986

def setCellHeightRatio(h) 
  @cell_height_ratio = h 
end

#SetCellPadding(pad) ⇒ Object Also known as: set_cell_padding

Set the internal Cell padding.

@param float :pad

internal padding.

@access public
@since 2.1.000 (2008-01-09)
@see

Cell(), SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()



1275
1276
1277
# File 'lib/rbpdf.rb', line 1275

def SetCellPadding(pad)
  @c_margin = pad
end

#SetCompression(compress) ⇒ Object Also known as: set_compression

Activates or deactivates page compression. When activated, the internal representation of each page is compressed, which leads to a compression ratio of about 2 for the resulting document. Compression is on by default.

  • Note: the Zlib extension is required for this feature. If not present, compression will be turned off.

@param boolean :compress

Boolean indicating if compression must be enabled.

@access public
@since 1.4


1374
1375
1376
1377
1378
1379
1380
1381
# File 'lib/rbpdf.rb', line 1374

def SetCompression(compress)
  #Set page compression
  if Object.const_defined?(:Zlib)
    @compress = compress
  else
    @compress = false
  end
end

#SetCreator(creator) ⇒ Object Also known as: set_creator

Defines the creator of the document. This is typically the name of the application that generates the PDF.

@param string :creator

The name of the creator.

@access public
@since 1.2
@see

SetAuthor(), SetKeywords(), SetSubject(), SetTitle()



1443
1444
1445
1446
# File 'lib/rbpdf.rb', line 1443

def SetCreator(creator)
  #Creator of document
  @creator = creator
end

#SetDefaultMonospacedFont(font) ⇒ Object Also known as: set_default_monospaced_font

Defines the default monospaced font.

@param string :font

Font name.

@access public
@since 4.5.025


2892
2893
2894
# File 'lib/rbpdf.rb', line 2892

def SetDefaultMonospacedFont(font)
  @default_monospaced_font = font
end

#SetDisplayMode(zoom, layout = 'SinglePage', mode = 'UseNone') ⇒ Object Also known as: set_display_mode

Defines the way the document is to be displayed by the viewer.

@param mixed :zoom

The zoom to use. It can be one of the following string values or a number indicating the zooming factor to use.

  • fullpage: displays the entire page on screen

  • fullwidth: uses maximum width of window

  • real: uses real size (equivalent to 100% zoom)

  • default: uses viewer default mode

@param string :layout

The page layout. Possible values are:

  • SinglePage Display one page at a time

  • OneColumn Display the pages in one column

  • TwoColumnLeft Display the pages in two columns, with odd-numbered pages on the left

  • TwoColumnRight Display the pages in two columns, with odd-numbered pages on the right

  • TwoPageLeft (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the left

  • TwoPageRight (PDF 1.5) Display the pages two at a time, with odd-numbered pages on the right

@param string :mode

A name object specifying how the document should be displayed when opened:

  • UseNone Neither document outline nor thumbnail images visible

  • UseOutlines Document outline visible

  • UseThumbs Thumbnail images visible

  • FullScreen Full-screen mode, with no menu bar, window controls, or any other window visible

  • UseOC (PDF 1.5) Optional content group panel visible

  • UseAttachments (PDF 1.6) Attachments panel visible

@access public
@since 1.2


1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
# File 'lib/rbpdf.rb', line 1323

def SetDisplayMode(zoom, layout='SinglePage', mode='UseNone')
  #Set display mode in viewer
  if (zoom == 'fullpage' or zoom == 'fullwidth' or zoom == 'real' or zoom == 'default' or !zoom.is_a?(String))
    @zoom_mode = zoom
  else
    Error('Incorrect zoom display mode: ' + zoom)
  end

  case layout
  when 'default', 'single', 'SinglePage'
    @layout_mode = 'SinglePage'
  when 'continuous', 'OneColumn'
    @layout_mode = 'OneColumn'
  when 'two', 'TwoColumnLeft'
    @layout_mode = 'TwoColumnLeft'
  when 'TwoColumnRight'
    @layout_mode = 'TwoColumnRight'
  when 'TwoPageLeft'
    @layout_mode = 'TwoPageLeft'
  when 'TwoPageRight'
    @layout_mode = 'TwoPageRight'
  else
    @layout_mode = 'SinglePage'
  end

  case mode
  when 'UseNone'
    @page_mode = 'UseNone'
  when 'UseOutlines'
    @page_mode = 'UseOutlines'
  when 'UseThumbs'
    @page_mode = 'UseThumbs'
  when 'FullScreen'
    @page_mode = 'FullScreen'
  when 'UseOC'
    @page_mode = 'UseOC'
  when ''
    @page_mode = 'UseAttachments'
  else
    @page_mode = 'UseNone'
  end
end

#SetDrawColor(col1 = 0, col2 = -1,, col3 = -1,, col4 = -1)) ⇒ Object Also known as: set_draw_color

Defines the color used for all drawing operations (lines, rectangles and cell borders). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

@param int :col1

Gray level for single color, or Red color for RGB, or Cyan color for CMYK. Value between 0 and 255

@param int :col2

Green color for RGB, or Magenta color for CMYK. Value between 0 and 255

@param int :col3

Blue color for RGB, or Yellow color for CMYK. Value between 0 and 255

@param int :col4

Key (Black) color for CMYK. Value between 0 and 255

@access public
@since 1.3
@see

SetFillColor(), SetTextColor(), Line(), Rect(), Cell(), MultiCell()



2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
# File 'lib/rbpdf.rb', line 2200

def SetDrawColor(col1=0, col2=-1, col3=-1, col4=-1)
  # set default values
  unless col1.is_a?(Numeric)
    col1 = 0
  end
  unless col2.is_a?(Numeric)
    col2 = 0
  end
  unless col3.is_a?(Numeric)
    col3 = 0
  end
  unless col4.is_a?(Numeric)
    col4 = 0
  end
  #Set color for all stroking operations
  if (col2 == -1) and (col3 == -1) and (col4 == -1)
    # Grey scale
    @draw_color = sprintf('%.3f G', col1 / 255.0)
    @strokecolor['G'] = col1
  elsif col4 == -1
    # RGB
    @draw_color = sprintf('%.3f %.3f %.3f RG', col1 / 255.0, col2 / 255.0, col3 / 255.0)
    @strokecolor['R'] = col1
    @strokecolor['G'] = col2
    @strokecolor['B'] = col3
  else
    # CMYK
    @draw_color = sprintf('%.3f %.3f %.3f %.3f K', col1 / 100.0, col2 / 100.0, col3 / 100.0, col4 / 100.0)
    @strokecolor['C'] = col1
    @strokecolor['M'] = col2
    @strokecolor['Y'] = col3
    @strokecolor['K'] = col4
  end
  if (@page>0)
    out(@draw_color + ' ')
  end
end

#SetDrawColorArray(color) ⇒ Object Also known as: set_draw_color_array

Defines the color used for all drawing operations (lines, rectangles and cell borders). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

@param array or ordered hash :color

array(or ordered hash) of colors

@access public
@since 3.1.000 (2008-6-11)
@see

SetDrawColor()



2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
# File 'lib/rbpdf.rb', line 2176

def SetDrawColorArray(color)
  if !color.nil?
    color = color.values if color.is_a? Hash
    r = !color[0].nil? ? color[0] : -1
    g = !color[1].nil? ? color[1] : -1
    b = !color[2].nil? ? color[2] : -1
    k = !color[3].nil? ? color[3] : -1
    if r >= 0
      SetDrawColor(r, g, b, k)
    end
  end
end

#SetFillColor(col1 = 0, col2 = -1,, col3 = -1,, col4 = -1)) ⇒ Object Also known as: set_fill_color

Defines the color used for all filling operations (filled rectangles and cell backgrounds). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

@param int :col1

Gray level for single color, or Red color for RGB, or Cyan color for CMYK. Value between 0 and 255

@param int :col2

Green color for RGB, or Magenta color for CMYK. Value between 0 and 255

@param int :col3

Blue color for RGB, or Yellow color for CMYK. Value between 0 and 255

@param int :col4

Key (Black) color for CMYK. Value between 0 and 255

@access public
@since 1.3
@see

SetDrawColor(), SetTextColor(), Rect(), Cell(), MultiCell()



2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
# File 'lib/rbpdf.rb', line 2272

def SetFillColor(col1=0, col2=-1, col3=-1, col4=-1)
  # set default values
  unless col1.is_a?(Numeric)
    col1 = 0
  end
  unless col2.is_a?(Numeric)
    col2 = -1
  end
  unless col3.is_a?(Numeric)
    col3 = -1
  end
  unless col4.is_a?(Numeric)
    col4 = -1
  end

  # Set color for all filling operations
  if (col2 == -1) and (col3 == -1) and (col4 == -1)
    # Grey scale
    @fill_color = sprintf('%.3f g', col1 / 255.0)
    @bgcolor['G'] = col1
  elsif col4 == -1
    # RGB
    @fill_color = sprintf('%.3f %.3f %.3f rg', col1 / 255.0, col2 / 255.0, col3 / 255.0)
    @bgcolor['R'] = col1
    @bgcolor['G'] = col2
    @bgcolor['B'] = col3
  else
    # CMYK
    @fill_color = sprintf('%.3f %.3f %.3f %.3f k', col1 / 100.0, col2 / 100.0, col3 / 100.0, col4 / 100.0)
    @bgcolor['C'] = col1
    @bgcolor['M'] = col2
    @bgcolor['Y'] = col3
    @bgcolor['K'] = col4
  end

  @color_flag = (@fill_color != @text_color)
  if @page > 0
    out(@fill_color)
  end
end

#SetFillColorArray(color) ⇒ Object Also known as: set_fill_color_array

Defines the color used for all filling operations (filled rectangles and cell backgrounds). It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

@param array or ordered hash :color

array(or ordered hash) of colors

@access public
@since 3.1.000 (2008-6-11)
@see

SetFillColor()



2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
# File 'lib/rbpdf.rb', line 2248

def SetFillColorArray(color)
  if !color.nil?
    color = color.values if color.is_a? Hash
    r = !color[0].nil? ? color[0] : -1
    g = !color[1].nil? ? color[1] : -1
    b = !color[2].nil? ? color[2] : -1
    k = !color[3].nil? ? color[3] : -1
    if r >= 0
      SetFillColor(r, g, b, k)
    end
  end
end

#SetFont(family, style = '', size = 0, fontfile = '') ⇒ Object Also known as: set_font

Sets the font used to print character strings. The font can be either a standard one or a font added via the AddFont() method. Standard fonts use Windows encoding cp1252 (Western Europe). The method can be called before the first page is created and the font is retained from page to page. If you just wish to change the current font size, it is simpler to call SetFontSize().

  • Note: for the standard fonts, the font metric files must be accessible. There are three possibilities for this:

    • They are in the current directory (the one where the running script lies)

    • They are in one of the directories defined by the include_path parameter

    • They are in the directory defined by the FPDF_FONTPATH constant

@param string :family

Family font. It can be either a name defined by AddFont() or one of the standard Type1 families (case insensitive):

  • times (Times-Roman)

  • timesb (Times-Bold)

  • timesi (Times-Italic)

  • timesbi (Times-BoldItalic)

  • helvetica (Helvetica)

  • helveticab (Helvetica-Bold)

  • helveticai (Helvetica-Oblique)

  • helveticabi (Helvetica-BoldOblique)

  • courier (Courier)

  • courierb (Courier-Bold)

  • courieri (Courier-Oblique)

  • courierbi (Courier-BoldOblique)

  • symbol (Symbol)

  • zapfdingbats (ZapfDingbats)

It is also possible to pass an empty string. In that case, the current family is retained.

@param string :style

Font style. Possible values are (case insensitive):

  • empty string: regular

  • B: bold

  • I: italic

  • U: underline

  • D: line trough

  • O: overline

or any combination. The default value is regular. Bold and italic styles do not apply to Symbol and ZapfDingbats basic fonts or other fonts when not defined.

@param float :size

Font size in points. The default value is the current size. If no size has been specified since the beginning of the document, the value taken is 12

@param string :fontfile

The font definition file. By default, the name is built from the family and style, in lower case with no spaces.

@access public
@since 1.0
@see

AddFont(), SetFontSize()



2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
# File 'lib/rbpdf.rb', line 2799

def SetFont(family, style='', size=0, fontfile='')
  # Select a font; size given in points
  if size == 0
    size = @font_size_pt
  end
  # try to add font (if not already added)
  fontdata =  AddFont(family, style, fontfile)
  @font_family = fontdata['family']
  @font_style = fontdata['style']
  @current_font = getFontBuffer(fontdata['fontkey'])
  SetFontSize(size)
end

#SetFontSize(size) ⇒ Object Also known as: set_font_size

Defines the size of the current font.

@param float :size

The size (in points)

@access public
@since 1.0
@see

SetFont()



2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
# File 'lib/rbpdf.rb', line 2820

def SetFontSize(size)
  #Set font size in points
  @font_size_pt = size;
  @font_size = size.to_f / @k;
  if !@current_font['desc'].nil? and !@current_font['desc']['Ascent'].nil? and (@current_font['desc']['Ascent'] > 0)
    @font_ascent = @current_font['desc']['Ascent'] * @font_size / 1000
  else
    @font_ascent = 0.85 * @font_size
  end
  if !@current_font['desc'].nil? and !@current_font['desc']['Descent'].nil? and (@current_font['desc']['Descent'] <= 0)
    @font_descent = - @current_font['desc']['Descent'] * @font_size / 1000
  else
    @font_descent = 0.15 * @font_size
  end
  if (@page > 0) and !@current_font['i'].nil?
    out(sprintf('BT /F%d %.2f Tf ET ', @current_font['i'], @font_size_pt));
  end
end

#setFooterFont(font) ⇒ Object Also known as: set_footer_font

Set footer font.

@param array :font

font

@access public
@since 1.1


7844
7845
7846
# File 'lib/rbpdf.rb', line 7844

def setFooterFont(font)
  @footer_font = font;
end

#SetFooterFont(font) ⇒ Object



7849
7850
7851
7852
# File 'lib/rbpdf.rb', line 7849

def SetFooterFont(font)
  warn "[DEPRECATION] 'SetFooterFont' is deprecated. Please use 'set_footer_font' instead."
  setFooterFont(font)
end

#setFooterMargin(fm = 10) ⇒ Object Also known as: set_footer_margin

Set footer margin. (minimum distance between footer and bottom page margin)

@param int :fm

distance in millimeters

@access public


1848
1849
1850
# File 'lib/rbpdf.rb', line 1848

def setFooterMargin(fm=10)
  @footer_margin = fm;
end

#SetFooterMargin(fm = 10) ⇒ Object



1853
1854
1855
1856
# File 'lib/rbpdf.rb', line 1853

def SetFooterMargin(fm=10)
  warn "[DEPRECATION] 'SetFooterMargin' is deprecated. Please use 'set_footer_margin' instead."
  setFooterMargin(fm)
end

#setHeaderData(ln = "", lw = 0, ht = "", hs = "") ⇒ Object Also known as: set_header_data

Set header data.

@param string :ln

header image logo

@param string :lw

header image logo width in mm

@param string :ht

string to print as title on document header

@param string :hs

string to print on document header

@access public


1782
1783
1784
1785
1786
1787
# File 'lib/rbpdf.rb', line 1782

def setHeaderData(ln="", lw=0, ht="", hs="")
  @header_logo = ln || ""
  @header_logo_width = lw || 0
  @header_title = ht || ""
  @header_string = hs || ""
end

#SetHeaderData(ln = "", lw = 0, ht = "", hs = "") ⇒ Object



1790
1791
1792
1793
# File 'lib/rbpdf.rb', line 1790

def SetHeaderData(ln="", lw=0, ht="", hs="")
  warn "[DEPRECATION] 'SetHeaderData' is deprecated. Please use 'set_header_data' instead."
  setHeaderData(ln, lw, ht, hs)
end

#setHeaderFont(font) ⇒ Object Also known as: set_header_font

Set header font.

@param array :font

font

@access public
@since 1.1


7817
7818
7819
# File 'lib/rbpdf.rb', line 7817

def setHeaderFont(font)
  @header_font = font;
end

#SetHeaderFont(font) ⇒ Object



7822
7823
7824
7825
# File 'lib/rbpdf.rb', line 7822

def SetHeaderFont(font)
  warn "[DEPRECATION] 'SetHeaderFont' is deprecated. Please use 'set_header_font' instead."
  setHeaderFont(font)
end

#setHeaderMargin(hm = 10) ⇒ Object Also known as: set_header_margin

Set header margin. (minimum distance between header and top page margin)

@param int :hm

distance in user units

@access public


1821
1822
1823
# File 'lib/rbpdf.rb', line 1821

def setHeaderMargin(hm=10)
  @header_margin = hm;
end

#SetHeaderMargin(hm = 10) ⇒ Object



1826
1827
1828
1829
# File 'lib/rbpdf.rb', line 1826

def SetHeaderMargin(hm=10)
  warn "[DEPRECATION] 'SetHeaderMargin' is deprecated. Please use 'set_header_margin' instead."
  setHeaderMargin(hm)
end

#setHtmlVSpace(tagvs) ⇒ Object Also known as: set_html_v_space

Set the vertical spaces for HTML tags. The array must have the following structure (example):

:tagvs = {'h1' => [{'h' => '', 'n' => 2}, {'h' => 1.3, 'n' => 1}]}

The first array level contains the tag names, the second level contains 0 for opening tags or 1 for closing tags, the third level contains the vertical space unit (h) and the number spaces to add (n). If the h parameter is not specified, default values are used.

@param array :tagvs

array of tags and relative vertical spaces.

@access public
@since 4.2.001 (2008-10-30)


13170
13171
13172
# File 'lib/rbpdf.rb', line 13170

def setHtmlVSpace(tagvs)
  @tagvspaces = tagvs
end

#setImageScale(scale) ⇒ Object Also known as: set_image_scale

Set the adjusting factor to convert pixels to user units.

@param float :scale

adjusting factor to convert pixels to user units.

@author

Nicola Asuni

@access public
@since 1.5.2


1031
1032
1033
# File 'lib/rbpdf.rb', line 1031

def setImageScale(scale)
  @img_scale = scale;
end

#SetImageScale(scale) ⇒ Object



1036
1037
1038
1039
# File 'lib/rbpdf.rb', line 1036

def SetImageScale(scale)
  warn "[DEPRECATION] 'SetImageScale' is deprecated. Please use 'set_image_scale' instead."
  setImageScale(scale)
end

#setJPEGQuality(quality) ⇒ Object Also known as: set_jpeg_quality

Set the default JPEG compression quality (1-100)

@param int :quality

JPEG quality, integer between 1 and 100

@access public
@since 3.0.000 (2008-03-27)


9972
9973
9974
9975
9976
9977
# File 'lib/rbpdf.rb', line 9972

def setJPEGQuality(quality)
  if (quality < 1) or (quality > 100)
    quality = 75
  end
  @jpeg_quality = quality
end

#SetKeywords(keywords) ⇒ Object Also known as: set_keywords

Associates keywords with the document, generally in the form ‘keyword1 keyword2 …’.

@param string :keywords

The list of keywords.

@access public
@since 1.2
@see

SetAuthor(), SetCreator(), SetSubject(), SetTitle()



1430
1431
1432
1433
# File 'lib/rbpdf.rb', line 1430

def SetKeywords(keywords)
  #Keywords of document
  @keywords = keywords
end

#setLanguageArray(language) ⇒ Object Also known as: set_language_array

Set language array.

@param array :language
@since 1.1


7870
7871
7872
7873
7874
7875
7876
7877
# File 'lib/rbpdf.rb', line 7870

def setLanguageArray(language)
  @l = language;
  if @l['a_meta_dir']
    @rtl = (@l['a_meta_dir'] == 'rtl') ? true : false
  else
    @rtl = false
  end
end

#SetLanguageArray(language) ⇒ Object



7880
7881
7882
7883
# File 'lib/rbpdf.rb', line 7880

def SetLanguageArray(language)
  warn "[DEPRECATION] 'SetLanguageArray' is deprecated. Please use 'set_language_array' instead."
  setLanguageArray(language)
end

#setLastH(h) ⇒ Object Also known as: set_last_h

Set the last cell height.

@param float :h

cell height.

@author

Nicola Asuni

@access public
@since 1.53.0.TC034


1008
1009
1010
# File 'lib/rbpdf.rb', line 1008

def setLastH(h)
  @lasth = h
end

#SetLeftMargin(margin) ⇒ Object Also known as: set_left_margin

Defines the left margin. The method can be called before creating the first page. If the current abscissa gets out of page, it is brought back to the margin.

@param float :margin

The margin.

@access public
@since 1.4
@see

SetTopMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()



1228
1229
1230
1231
1232
1233
1234
# File 'lib/rbpdf.rb', line 1228

def SetLeftMargin(margin)
  #Set left margin
  @l_margin = margin
  if (@page > 0) and (@x < margin)
    @x = margin
  end
end

#SetLineStyle(style) ⇒ Object Also known as: set_line_style

Set line style.

@param hash :style

Line style. Array with keys among the following:

  • width (float): Width of the line in user units.

  • cap (string): Type of cap to put on the line. Possible values are: butt, round, square. The difference between “square” and “butt” is that “square” projects a flat end past the end of the line.

  • join (string): Type of join. Possible values are: miter, round, bevel.

  • dash (mixed): Dash pattern. Is 0 (without dash) or string with series of length values, which are the lengths of the on and off dashes. For example: “2” represents 2 on, 2 off, 2 on, 2 off, …; “2,1” is 2 on, 1 off, 2 on, 1 off, …

  • phase (integer): Modifier on the dash pattern which is used to shift the point at which the pattern starts.

  • color (array): Draw color. Format: array(GREY) or array(R,G,B) or array(C,M,Y,K).

@access public
@since 2.1.000 (2008-01-08)


8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
# File 'lib/rbpdf.rb', line 8203

def SetLineStyle(style)
  unless style.is_a? Hash
    return
  end
  if !style['width'].nil?
    width = style['width']
    width_prev = @line_width
    SetLineWidth(width)
    @line_width = width_prev
  end
  if !style['cap'].nil?
    cap = style['cap']
    ca = {'butt' => 0, 'round'=> 1, 'square' => 2}
    if !ca[cap].nil?
      @linestyle_cap = ca[cap].to_s + ' J'
      out(@linestyle_cap)
    end
  end
  if !style['join'].nil?
    join = style['join']
    ja = {'miter' => 0, 'round' => 1, 'bevel' => 2}
    if !ja[join].nil?
      @linestyle_join = ja[join].to_s + ' j'
      out(@linestyle_join);
    end
  end
  if !style['dash'].nil?
    dash = style['dash']
    dash_string = ''
    if dash != 0 and dash != ''
      if dash =~ /^.+,/
        tab = dash.split(',')
      else
        tab = [dash]
      end
      dash_string = ''
      tab.each_with_index { |v, i|
        if i != 0
          dash_string << ' '
        end
        dash_string << sprintf("%.2f", v.to_f)
      }
    end
    phase = 0
    @linestyle_dash = sprintf("[%s] %.2f d", dash_string, phase)
    out(@linestyle_dash)
  end
  if !style['color'].nil?
    color = style['color']
    SetDrawColorArray(color)
  end
end

#SetLineWidth(width) ⇒ Object Also known as: set_line_width

Defines the line width. By default, the value equals 0.2 mm. The method can be called before the first page is created and the value is retained from page to page.

@param float :width

The width.

@access public
@since 1.0
@see

Line(), Rect(), Cell(), MultiCell()



8168
8169
8170
8171
8172
8173
8174
8175
# File 'lib/rbpdf.rb', line 8168

def SetLineWidth(width)
  #Set line width
  @line_width = width;
  @linestyle_width = sprintf('%.2f w', width * @k)
  if (@page>0)
    out(@linestyle_width)
  end
end

Defines the page and position a link points to

@param int :link

The link identifier returned by AddLink()

@param float :y

Ordinate of target position; -1 indicates the current position. The default value is 0 (top of page)

@param int :page

Number of target page; -1 indicates the current page. This is the default value

@since 1.5
@see

AddLink()



2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
# File 'lib/rbpdf.rb', line 2920

def SetLink(link, y=0, page=-1)
  #Set destination of internal link
  if (y==-1)
    y=@y;
  end
  if (page==-1)
    page=@page;
  end
  @links[link] = [page, y]
end

#SetMargins(left, top, right = -1,, keepmargins = false) ⇒ Object Also known as: set_margins

Defines the left, top and right margins.

@param float :left

Left margin.

@param float :top

Top margin.

@param float :right

Right margin. Default value is the left one.

@param boolean :keepmargins

if true overwrites the default page margins

@access public
@since 1.0
@see

SetLeftMargin(), SetTopMargin(), SetRightMargin(), SetAutoPageBreak()



1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
# File 'lib/rbpdf.rb', line 1205

def SetMargins(left, top, right=-1, keepmargins=false)
  #Set left, top and right margins
  @l_margin = left
  @t_margin = top
  if (right == -1)
    right = left
  end
  @r_margin = right
  if keepmargins
    # overwrite original values
    @original_l_margin = @l_margin
    @original_r_margin = @r_margin
  end
end

#setPage(pnum, resetmargins = false) ⇒ Object Also known as: set_page

Move pointer at the specified document page and update page dimensions.

@param int :pnum

page number (1 … numpages)

@param boolean :resetmargins

if true reset left, right, top margins and Y position.

@access public
@since 2.1.000 (2008-01-07)
@see

getPage(), lastPage(), getNumPages()



1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
# File 'lib/rbpdf.rb', line 1520

def setPage(pnum, resetmargins=false)
  if pnum == @page
    return
  end
  if (pnum > 0) and (pnum <= @numpages)
    @state = 2
    # save current graphic settings
    # gvars = getGraphicVars()
    oldpage = @page
    @page = pnum
    @w_pt = @pagedim[@page]['w']
    @h_pt = @pagedim[@page]['h']
    @w = @pagedim[@page]['wk']
    @h = @pagedim[@page]['hk']
    @t_margin = @pagedim[@page]['tm']
    @b_margin = @pagedim[@page]['bm']
    @original_l_margin = @pagedim[@page]['olm']
    @original_r_margin = @pagedim[@page]['orm']
    @auto_page_break = @pagedim[@page]['pb']
    @cur_orientation = @pagedim[@page]['or']
    SetAutoPageBreak(@auto_page_break, @b_margin)
    # restore graphic settings
    # setGraphicVars(gvars)
    if resetmargins
      @l_margin = @pagedim[@page]['olm']
      @r_margin = @pagedim[@page]['orm']
      SetY(@t_margin)
    else
      # account for booklet mode
      if @pagedim[@page]['olm'] != @pagedim[oldpage]['olm']
        deltam = @pagedim[@page]['olm'] - @pagedim[@page]['orm']
        @l_margin += deltam
        @r_margin -= deltam
      end
    end
  else
    Error('Wrong page number on setPage() function.')
  end
end

#setPageBoxes(page, type, llx, lly, urx, ury) ⇒ Object Also known as: set_page_boxes

Set page boundaries.

@param int :page

page number

@param string :type

valid values are:

  • ‘MediaBox’ : the boundaries of the physical medium on which the page shall be displayed or printed

  • ‘CropBox’ : the visible region of default user space

  • ‘BleedBox’ : the region to which the contents of the page shall be clipped when output in a production environment

  • ‘TrimBox’ : the intended dimensions of the finished page after trimming

  • ‘ArtBox’ : the page’s meaningful content (including potential white space).

@param float :llx

lower-left x coordinate in user units

@param float :lly

lower-left y coordinate in user units

@param float :urx

upper-right x coordinate in user units

@param float :ury

upper-right y coordinate in user units

@access public
@since 5.0.010 (2010-05-17)


805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
# File 'lib/rbpdf.rb', line 805

def setPageBoxes(page, type, llx, lly, urx, ury)
  if @pagedim[@page].nil?
    # initialize array
    @pagedim[@page] = {}
  end
  pageboxes = ['MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox']
  unless pageboxes.include?(type)
    return
  end
  @pagedim[page][type] = {}
  @pagedim[page][type]['llx'] = llx * @k
  @pagedim[page][type]['lly'] = lly * @k
  @pagedim[page][type]['urx'] = urx * @k
  @pagedim[page][type]['ury'] = ury * @k
end

#setPageMarkObject Also known as: set_page_mark

Set start-writing mark on current page stream used to put borders and fills. Borders and fills are always created after content and inserted on the position marked by this method. This function must be called after calling Image() function for a background image. Background images must be always inserted before calling Multicell() or WriteHTMLCell() or WriteHTML() functions.

@access public
@since 4.0.016 (2008-07-30)


1749
1750
1751
1752
# File 'lib/rbpdf.rb', line 1749

def setPageMark()
  @intmrk[@page] = @pagelen[@page]
  setContentMark()
end

#setPageOrientation(orientation, autopagebreak = '', bottommargin = '') ⇒ Object Also known as: set_page_orientation

Set page orientation.

@param string :orientation

page orientation. Possible values are (case insensitive):

  • P or PORTRAIT (default)

  • L or LANDSCAPE

@param boolean :autopagebreak

Boolean indicating if auto-page-break mode should be on or off.

@param float :bottommargin

bottom margin of the page.

@access public
@since 3.0.015 (2008-06-06)


855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
# File 'lib/rbpdf.rb', line 855

def setPageOrientation(orientation, autopagebreak='', bottommargin='')
  if @pagedim[@page].nil? or @pagedim[@page]['MediaBox'].nil?
    # the boundaries of the physical medium on which the page shall be displayed or printed
    setPageBoxes(@page, 'MediaBox', 0, 0, (@fw_pt / @k), (@fh_pt / @k))
  end
  if @pagedim[@page]['CropBox'].nil?
    # the visible region of default user space
    setPageBoxes(@page, 'CropBox', @pagedim[@page]['MediaBox']['llx'], @pagedim[@page]['MediaBox']['lly'], @pagedim[@page]['MediaBox']['urx'], @pagedim[@page]['MediaBox']['ury'])
  end
  if @pagedim[@page]['BleedBox'].nil?
    # the region to which the contents of the page shall be clipped when output in a production environment
    setPageBoxes(@page, 'BleedBox', @pagedim[@page]['CropBox']['llx'], @pagedim[@page]['CropBox']['lly'], @pagedim[@page]['CropBox']['urx'], @pagedim[@page]['CropBox']['ury'])
  end
  if @pagedim[@page]['TrimBox'].nil?
    # the intended dimensions of the finished page after trimming
    setPageBoxes(@page, 'TrimBox', @pagedim[@page]['CropBox']['llx'], @pagedim[@page]['CropBox']['lly'], @pagedim[@page]['CropBox']['urx'], @pagedim[@page]['CropBox']['ury'])
  end
  if @pagedim[@page]['ArtBox'].nil?
    # the page's meaningful content (including potential white space)
    setPageBoxes(@page, 'ArtBox', @pagedim[@page]['CropBox']['llx'], @pagedim[@page]['CropBox']['lly'], @pagedim[@page]['CropBox']['urx'], @pagedim[@page]['CropBox']['ury'])
  end
  if @pagedim[@page]['Rotate'].nil?
    # The number of degrees by which the page shall be rotated clockwise when displayed or printed. The value shall be a multiple of 90.
    @pagedim[@page]['Rotate'] = 0
  end
  if @pagedim[@page]['PZ'].nil?
    # The page's preferred zoom (magnification) factor
    @pagedim[@page]['PZ'] = 1
  end
  if @fw_pt > @fh_pt
    # landscape
    default_orientation = 'L'
  else
    # portrait
    default_orientation = 'P'
  end
  valid_orientations = ['P', 'L']
  if orientation.empty?
    orientation = default_orientation
  else
    orientation = orientation[0, 1].upcase
  end
  if valid_orientations.include?(orientation) and (orientation != default_orientation)
    @cur_orientation = orientation
    @w_pt = @fh_pt
    @h_pt = @fw_pt
  else
    @cur_orientation = default_orientation
    @w_pt = @fw_pt
    @h_pt = @fh_pt
  end
  if ((@pagedim[@page]['MediaBox']['urx'] - @h_pt).abs < @feps) and ((@pagedim[@page]['MediaBox']['ury'] - @w_pt).abs < @feps)
    # swap X and Y coordinates (change page orientatio
    swapPageBoxCoordinates(@page)
  end
  @w = @w_pt / @k
  @h = @h_pt / @k
  if empty_string(autopagebreak)
    unless @auto_page_break.nil?
      autopagebreak = @auto_page_break
    else
      autopagebreak = true
    end
  end
  if empty_string(bottommargin)
    unless @b_margin.nil?
      bottommargin = @b_margin
    else
      # default value = 2 cm
      bottommargin = 2 * 28.35 / @k
    end
  end
  SetAutoPageBreak(autopagebreak, bottommargin)
  # store page dimensions
  @pagedim[@page]['w'] = @w_pt
  @pagedim[@page]['h'] = @h_pt
  @pagedim[@page]['wk'] = @w
  @pagedim[@page]['hk'] = @h
  @pagedim[@page]['tm'] = @t_margin
  @pagedim[@page]['bm'] = bottommargin
  @pagedim[@page]['lm'] = @l_margin
  @pagedim[@page]['rm'] = @r_margin
  @pagedim[@page]['pb'] = autopagebreak
  @pagedim[@page]['or'] = @cur_orientation
  @pagedim[@page]['olm'] = @original_l_margin
  @pagedim[@page]['orm'] = @original_r_margin
  @pagedim[@page]
end

#setPageUnit(unit) ⇒ Object Also known as: set_page_unit

Set the units of measure for the document.

@param string :unit

User measure unit. Possible values are:

  • pt: point

  • mm: millimeter (default)

  • cm: centimeter

  • in: inch

A point equals 1/72 of inch, that is to say about 0.35 mm (an inch being 2.54 cm). This is a very common unit in typography; font sizes are expressed in that unit.

@access public
@since 3.0.015 (2008-06-06)


530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
# File 'lib/rbpdf.rb', line 530

def setPageUnit(unit)
  unit = unit.downcase
  # Set scale factor
  case unit
  when 'px', 'pt'; @k=1.0     # points
  when 'mm'; @k = @dpi / 25.4 # millimeters
  when 'cm'; @k = @dpi / 2.54 # centimeters
  when 'in'; @k = @dpi        # inches
  # unsupported unit
  else Error("Incorrect unit: #{unit}")
  end
  @pdfunit = unit
  unless @cur_orientation.nil?
    setPageOrientation(@cur_orientation)
  end
end

#setPDFVersion(version = '1.7') ⇒ Object Also known as: set_pdf_version

Set the PDF version (check PDF reference for valid values). Default value is 1.t

@access public
@since 3.1.000 (2008-06-09)


10007
10008
10009
# File 'lib/rbpdf.rb', line 10007

def setPDFVersion(version='1.7')
  @pdf_version = version
end

#setPrintFooter(val = true) ⇒ Object Also known as: set_print_footer

Set a flag to print page footer.

@param boolean :value

set to true to print the page footer (default), false otherwise.

@access public


1889
1890
1891
# File 'lib/rbpdf.rb', line 1889

def setPrintFooter(val=true)
  @print_footer = val;
end

#SetPrintFooter(val = true) ⇒ Object



1894
1895
1896
1897
# File 'lib/rbpdf.rb', line 1894

def SetPrintFooter(val=true)
  warn "[DEPRECATION] 'SetPrintFooter' is deprecated. Please use 'set_print_footer' instead."
  setPrintFooter(val)
end

#SetPrintHeader(val = true) ⇒ Object



1879
1880
1881
1882
# File 'lib/rbpdf.rb', line 1879

def SetPrintHeader(val=true)
  warn "[DEPRECATION] 'SetPrintHeader' is deprecated. Please use 'set_print_header' instead."
  setPrintHeader(val)
end

#setPrintHeader(val = true) ⇒ Object Also known as: set_print_header

Set a flag to print page header.

@param boolean :val

set to true to print the page header (default), false otherwise.

@access public


1874
1875
1876
# File 'lib/rbpdf.rb', line 1874

def setPrintHeader(val=true)
  @print_header = val;
end

#SetRightMargin(margin) ⇒ Object Also known as: set_right_margin

Defines the right margin. The method can be called before creating the first page.

@param float :margin

The margin.

@access public
@since 1.5
@see

SetLeftMargin(), SetTopMargin(), SetAutoPageBreak(), SetMargins()



1260
1261
1262
1263
1264
1265
# File 'lib/rbpdf.rb', line 1260

def SetRightMargin(margin)
  @r_margin = margin
  if (@page > 0) and (@x > (@w - margin))
    @x = @w - margin
  end
end

#setRTL(enable, resetx = true) ⇒ Object Also known as: set_rtl

Enable or disable Right-To-Left language mode

@param Boolean :enable

if true enable Right-To-Left language mode.

@param Boolean :resetx

if true reset the X position on direction change.

@access public
@since 2.0.000 (2008-01-03)


952
953
954
955
956
957
958
# File 'lib/rbpdf.rb', line 952

def setRTL(enable, resetx=true)
  enable = enable ? true : false
  resetx = resetx and (enable != @rtl)
  @rtl = enable
  @tmprtl = false
  Ln(0) if resetx
end

#SetSubject(subject) ⇒ Object Also known as: set_subject

Defines the subject of the document.

@param string :subject

The subject.

@access public
@since 1.2
@see

SetAuthor(), SetCreator(), SetKeywords(), SetTitle()



1404
1405
1406
1407
# File 'lib/rbpdf.rb', line 1404

def SetSubject(subject)
  #Subject of document
  @subject = subject
end

#setTempRTL(mode) ⇒ Object Also known as: set_temp_rtl

Force temporary RTL language direction

@param mixed :mode

can be false, ‘L’ for LTR or ‘R’ for RTL

@access public
@since 2.1.000 (2008-01-09)


978
979
980
981
982
983
984
985
986
987
# File 'lib/rbpdf.rb', line 978

def setTempRTL(mode)
  newmode = false
  case mode
  when 'ltr', 'LTR', 'L'
    newmode = 'L' if @rtl
  when 'rtl', 'RTL', 'R'
    newmode = 'R' if !@rtl
  end
  @tmprtl = newmode
end

#SetTextColor(col1 = 0, col2 = -1,, col3 = -1,, col4 = -1)) ⇒ Object Also known as: set_text_color

Defines the color used for text. It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

@param int :col1

Gray level for single color, or Red color for RGB, or Cyan color for CMYK. Value between 0 and 255

@param int :col2

Green color for RGB, or Magenta color for CMYK. Value between 0 and 255

@param int :col3

Blue color for RGB, or Yellow color for CMYK. Value between 0 and 255

@param int :col4

Key (Black) color for CMYK. Value between 0 and 255

@access public
@since 1.3
@see

SetDrawColor(), SetFillColor(), Text(), Cell(), MultiCell()



2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
# File 'lib/rbpdf.rb', line 2362

def SetTextColor(col1=0, col2=-1, col3=-1, col4=-1)
  # set default values
  unless col1.is_a?(Numeric)
    col1 = 0
  end
  unless col2.is_a?(Numeric)
    col2 = -1
  end
  unless col3.is_a?(Numeric)
    col3 = -1
  end
  unless col4.is_a?(Numeric)
    col4 = -1
  end

  # Set color for text
  if (col2 == -1) and (col3 == -1) and (col4 == -1)
    # Grey scale
    @text_color = sprintf('%.3f g', col1 / 255.0)
    @fgcolor['G'] = col1
  elsif col4 == -1
    # RGB
    @text_color = sprintf('%.3f %.3f %.3f rg', col1 / 255.0, col2 / 255.0, col3 / 255.0)
    @fgcolor['R'] = col1
    @fgcolor['G'] = col2
    @fgcolor['B'] = col3
  else
    # CMYK
    @text_color = sprintf('%.3f %.3f %.3f %.3f k', col1 / 100.0, col2 / 100.0, col3 / 100.0, col4 / 100.0)
    @fgcolor['C'] = col1
    @fgcolor['M'] = col2
    @fgcolor['Y'] = col3
    @fgcolor['K'] = col4
  end
  @color_flag = (@fill_color != @text_color)
end

#SetTextColorArray(color) ⇒ Object Also known as: set_text_color_array

Defines the color used for text. It can be expressed in RGB components or gray scale. The method can be called before the first page is created and the value is retained from page to page.

@param array or ordered hash :color

array(or ordered hash) of colors

@access public
@since 3.1.000 (2008-6-11)
@see

SetFillColor()



2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
# File 'lib/rbpdf.rb', line 2338

def SetTextColorArray(color)
  unless color.nil?
    color = color.values if color.is_a? Hash
    r = !color[0].nil? ? color[0] : -1
    g = !color[1].nil? ? color[1] : -1
    b = !color[2].nil? ? color[2] : -1
    k = !color[3].nil? ? color[3] : -1
    if r >= 0
      SetTextColor(r, g, b, k)
    end
  end
end

#setTextRenderingMode(stroke = 0, fill = true, clip = false) ⇒ Object Also known as: set_text_rendering_mode

Set Text rendering mode.

@param int :stroke

outline size in user units (0 = disable).

@param boolean :fill

if true fills the text (default).

@param boolean :clip

if true activate clipping mode

@access public
@since 4.9.008 (2009-04-02)


14405
14406
14407
14408
14409
14410
14411
14412
14413
14414
14415
14416
14417
14418
14419
14420
14421
14422
14423
14424
14425
14426
14427
14428
14429
14430
14431
14432
14433
14434
14435
14436
14437
14438
14439
14440
14441
14442
14443
14444
14445
14446
14447
14448
14449
14450
14451
14452
# File 'lib/rbpdf.rb', line 14405

def setTextRenderingMode(stroke=0, fill=true, clip=false)
  # Ref.: PDF 32000-1:2008 - 9.3.6 Text Rendering Mode
  # convert text rendering parameters
  if stroke < 0
    stroke = 0
  end
  if fill == true
    if stroke > 0
      if clip == true
        # Fill, then stroke text and add to path for clipping
        textrendermode = 6
      else
        # Fill, then stroke text
        textrendermode = 2
      end
      textstrokewidth = stroke
    else
      if clip == true
        # Fill text and add to path for clipping
        textrendermode = 4
      else
        # Fill text
        textrendermode = 0
      end
    end
  else
    if stroke > 0
      if clip == true
        # Stroke text and add to path for clipping
        textrendermode = 5
      else
        # Stroke text
        textrendermode = 1
      end
      textstrokewidth = stroke
    else
      if clip == true
        # Add text to path for clipping
        textrendermode = 7
      else
        # Neither fill nor stroke text (invisible)
        textrendermode = 3
      end
    end
  end
  @textrendermode = textrendermode
  @textstrokewidth = stroke * @k
end

#SetTitle(title) ⇒ Object Also known as: set_title

Defines the title of the document.

@param string :title

The title.

[@access public$

@since 1.2
@see

SetAuthor(), SetCreator(), SetKeywords(), SetSubject()



1391
1392
1393
1394
# File 'lib/rbpdf.rb', line 1391

def SetTitle(title)
  #Title of document
  @title = title
end

#SetTopMargin(margin) ⇒ Object Also known as: set_top_margin

Defines the top margin. The method can be called before creating the first page.

@param float :margin

The margin.

@access public
@since 1.5
@see

SetLeftMargin(), SetRightMargin(), SetAutoPageBreak(), SetMargins()



1244
1245
1246
1247
1248
1249
1250
# File 'lib/rbpdf.rb', line 1244

def SetTopMargin(margin)
  #Set top margin
  @t_margin = margin
  if (@page > 0) and (@y < margin)
    @y = margin
  end
end

#setViewerPreferences(preferences) ⇒ Object Also known as: set_viewer_preferences

Set the viewer preferences dictionary controlling the way the document is to be presented on the screen or in print. (see Section 8.1 of PDF reference, “Viewer Preferences”).

  • HideToolbar boolean (Optional) A flag specifying whether to hide the viewer application’s tool bars when the document is active. Default value: false.

  • HideMenubar boolean (Optional) A flag specifying whether to hide the viewer application’s menu bar when the document is active. Default value: false.

  • HideWindowUI boolean (Optional) A flag specifying whether to hide user interface elements in the document’s window (such as scroll bars and navigation controls), leaving only the document’s contents displayed. Default value: false.

  • FitWindow boolean (Optional) A flag specifying whether to resize the document’s window to fit the size of the first displayed page. Default value: false.

  • CenterWindow boolean (Optional) A flag specifying whether to position the document’s window in the center of the screen. Default value: false.

  • DisplayDocTitle boolean (Optional; PDF 1.4) A flag specifying whether the window’s title bar should display the document title taken from the Title entry of the document information dictionary (see Section 10.2.1, “Document Information Dictionary”). If false, the title bar should instead display the name of the PDF file containing the document. Default value: false.

  • NonFullScreenPageMode name (Optional) The document’s page mode, specifying how to display the document on exiting full-screen mode:

    • UseNone Neither document outline nor thumbnail images visible

    • UseOutlines Document outline visible

    • UseThumbs Thumbnail images visible

    • UseOC Optional content group panel visible

    This entry is meaningful only if the value of the PageMode entry in the catalog dictionary (see Section 3.6.1, “Document Catalog”) is FullScreen; it is ignored otherwise. Default value: UseNone.

  • ViewArea name (Optional; PDF 1.4) The name of the page boundary representing the area of a page to be displayed when viewing the document on the screen. Valid values are (see Section 10.10.1, “Page Boundaries”).:

    • MediaBox

    • CropBox (default)

    • BleedBox

    • TrimBox

    • ArtBox

  • ViewClip name (Optional; PDF 1.4) The name of the page boundary to which the contents of a page are to be clipped when viewing the document on the screen. Valid values are (see Section 10.10.1, “Page Boundaries”).:

    • MediaBox

    • CropBox (default)

    • BleedBox

    • TrimBox

    • ArtBox

  • PrintArea name (Optional; PDF 1.4) The name of the page boundary representing the area of a page to be rendered when printing the document. Valid values are (see Section 10.10.1, “Page Boundaries”).:

    • MediaBox

    • CropBox (default)

    • BleedBox

    • TrimBox

    • ArtBox

  • PrintClip name (Optional; PDF 1.4) The name of the page boundary to which the contents of a page are to be clipped when printing the document. Valid values are (see Section 10.10.1, “Page Boundaries”).:

    • MediaBox

    • CropBox (default)

    • BleedBox

    • TrimBox

    • ArtBox

  • PrintScaling name (Optional; PDF 1.6) The page scaling option to be selected when a print dialog is displayed for this document. Valid values are:

    • None, which indicates that the print dialog should reflect no page scaling

    • AppDefault (default), which indicates that applications should use the current print scaling

  • Duplex name (Optional; PDF 1.7) The paper handling option to use when printing the file from the print dialog. The following values are valid:

    • Simplex - Print single-sided

    • DuplexFlipShortEdge - Duplex and flip on the short edge of the sheet

    • DuplexFlipLongEdge - Duplex and flip on the long edge of the sheet

    Default value: none

  • PickTrayByPDFSize boolean (Optional; PDF 1.7) A flag specifying whether the PDF page size is used to select the input paper tray. This setting influences only the preset values used to populate the print dialog presented by a PDF viewer application. If PickTrayByPDFSize is true, the check box in the print dialog associated with input paper tray is checked. Note: This setting has no effect on Mac OS systems, which do not provide the ability to pick the input tray by size.

  • PrintPageRange array (Optional; PDF 1.7) The page numbers used to initialize the print dialog box when the file is printed. The first page of the PDF file is denoted by 1. Each pair consists of the first and last pages in the sub-range. An odd number of integers causes this entry to be ignored. Negative numbers cause the entire array to be ignored. Default value: as defined by PDF viewer application

  • NumCopies integer (Optional; PDF 1.7) The number of copies to be printed when the print dialog is opened for this file. Supported values are the integers 2 through 5. Values outside this range are ignored. Default value: as defined by PDF viewer application, but typically 1

@param array :preferences

array of options.

@author

Nicola Asuni

@access public
@since 3.1.000 (2008-06-09)


10067
10068
10069
# File 'lib/rbpdf.rb', line 10067

def setViewerPreferences(preferences)
  @viewer_preferences = preferences
end

#setVisibility(v) ⇒ Object Also known as: set_visibility

Set the visibility of the successive elements. This can be useful, for instance, to put a background image or color that will show on screen but won’t print.

@param string :v

visibility mode. Legal values are: all, print, screen.

@access public
@since 3.0.000 (2008-03-27)


9871
9872
9873
9874
9875
9876
9877
9878
9879
9880
9881
9882
9883
9884
9885
9886
9887
9888
9889
9890
# File 'lib/rbpdf.rb', line 9871

def setVisibility(v)
  if @open_marked_content
    # close existing open marked-content
    out('EMC')
    @open_marked_content = false
  end
  case v
  when 'print'
    out('/OC /OC1 BDC')
    @open_marked_content = true
  when 'screen'
    out('/OC /OC2 BDC')
    @open_marked_content = true
  when 'all'
    out('')
  else
    Error('Incorrect visibility: ' + v)
  end
  @visibility = v
end

#SetX(x, rtloff = false) ⇒ Object Also known as: set_x

Defines the abscissa of the current position. If the passed value is negative, it is relative to the right of the page (or left if language is RTL).

@param float :x

The value of the abscissa.

@param boolean :rtloff

if true always uses the page top-left corner as origin of axis.

@access public
@since 1.2
@see

GetX(), GetY(), SetY(), SetXY()



5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
# File 'lib/rbpdf.rb', line 5309

def SetX(x, rtloff=false)
  #Set x position
  if !rtloff and @rtl
    if x >= 0
      @x = @w - x
    else
      @x = x.abs
    end
  else
    if x >= 0
      @x = x
    else
      @x = @w + x
    end
  end
end

#SetXY(x, y, rtloff = false) ⇒ Object Also known as: set_xy

Defines the abscissa and ordinate of the current position. If the passed values are negative, they are relative respectively to the right and bottom of the page.

@param float :x

The value of the abscissa.

@param float :y

The value of the ordinate.

@param boolean :rtloff

if true always uses the page top-left corner as origin of axis.

@access public
@since 1.2
@see

SetX(), SetY()



5370
5371
5372
5373
# File 'lib/rbpdf.rb', line 5370

def SetXY(x, y, rtloff=false)
  SetY(y, false, rtloff)
  SetX(x, rtloff)
end

#SetY(y, resetx = true, rtloff = false) ⇒ Object Also known as: set_y

Moves the current abscissa back to the left margin and sets the ordinate. If the passed value is negative, it is relative to the bottom of the page.

@param float :y

The value of the ordinate.

@param bool :resetx

if true (default) reset the X position.

@param boolean :rtloff

if true always uses the page top-left corner as origin of axis.

@access public
@since 1.0
@see

GetX(), GetY(), SetY(), SetXY()



5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
# File 'lib/rbpdf.rb', line 5337

def SetY(y, resetx=true, rtloff=false)
  if resetx
    # reset x
    if !rtloff and @rtl
      @x = @w - @r_margin
    else
      @x = @l_margin
    end
  end
  if (y>=0)
    @y = y;
  else
    @y=@h+y;
  end

  if @y < 0
    @y = 0
  end
  if @y > @h
    @y = @h
  end
end

#StarPolygon(x0, y0, r, nv, ng, angle = 0, draw_circle = false, style = '', line_style = nil, fill_color = nil, circle_style = '', circle_outLine_style = nil, circle_fill_color = nil) ⇒ Object Also known as: star_polygon

Draws a star polygon

@param float :x0

Abscissa of center point.

@param float :y0

Ordinate of center point.

@param float :r

Radius of inscribed circle.

@param integer :nv

Number of vertices.

@param integer :ng

Number of gap (if (:ng % :nv = 1) then is a regular polygon).

@param float :angle

Angle oriented (anti-clockwise). Default value: 0.

@param boolean :draw_circle

Draw inscribed circle or not. Default value is false.

@param string :style

Style of rendering. See the getPathPaintOperator() function for more information.

@param array :line_style

Line style of polygon sides. Array with keys among the following:

  • all: Line style of all sides. Array like for SetLineStyle SetLineStyle.

  • 0 to (n - 1): Line style of each side. Array like for SetLineStyle SetLineStyle.

If a key is not present or is null, not draws the side. Default value is default line style (empty array). [@param array :fill_color ]Fill color. Format: array(red, green, blue). Default value: default color (empty array).

@param string :circle_style

Style of rendering of inscribed circle (if draws). Possible values are:

  • D or empty string: Draw (default).

  • F: Fill.

  • DF or FD: Draw and fill.

  • CNZ: Clipping mode (using the even-odd rule to determine which regions lie inside the clipping path).

  • CEO: Clipping mode (using the nonzero winding number rule to determine which regions lie inside the clipping path).

@param array :circle_outLine_style

Line style of inscribed circle (if draws). Array like for SetLineStyle SetLineStyle. Default value: default line style (empty array).

@param array :circle_fill_color

Fill color of inscribed circle (if draws). Format: array(red, green, blue). Default value: default color (empty array).

@access public
@since 2.1.000 (2008-01-08)


8792
8793
8794
8795
8796
8797
8798
8799
8800
8801
8802
8803
8804
8805
8806
8807
8808
8809
8810
8811
8812
8813
8814
8815
8816
8817
8818
8819
8820
# File 'lib/rbpdf.rb', line 8792

def StarPolygon(x0, y0, r, nv, ng, angle=0, draw_circle=false, style='', line_style=nil, fill_color=nil, circle_style='', circle_outLine_style=nil, circle_fill_color=nil)
  draw_circle = false if draw_circle == 0
  if nv < 2
    nv = 2
  end
  if draw_circle
    Circle(x0, y0, r, 0, 360, circle_style, circle_outLine_style, circle_fill_color)
  end
  p2 = []
  visited = []
  0.upto(nv -1) do |i|
    a = angle + i * 360 / nv
    a_rad = a * ::Math::PI / 180 # deg2rad
    p2.push x0 + r * ::Math.sin(a_rad)
    p2.push y0 + r * ::Math.cos(a_rad)
    visited.push false
  end
  p = []
  i = 0
  while true
    p.push p2[i * 2]
    p.push p2[i * 2 + 1]
    visited[i] = true
    i += ng
    i %= nv
    break if visited[i]
  end
  Polygon(p, style, line_style, fill_color)
end

#startPage(orientation = '', format = '', tocpage = false) ⇒ Object Also known as: start_page

Starts a new page to the document. The page must be closed using the endPage() function. The origin of the coordinate system is at the top-left corner and increasing ordinates go downwards.

@param string :orientation

page orientation. Possible values are (case insensitive):

  • P or PORTRAIT (default)

  • L or LANDSCAPE

@param mixed :format

The format used for pages. It can be either: A string indicating the page format:

  • 4A0,2A0,A0,A1,A2,A3,A4 (default),A5,A6,A7,A8,A9,A10

  • B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10

  • C0,C1,C2,C3,C4,C5,C6,C7,C8,C9,C10

  • RA0,RA1,RA2,RA3,RA4

  • SRA0,SRA1,SRA2,SRA3,SRA4

  • LETTER,LEGAL,EXECUTIVE,FOLIO

An array containing page measures and advanced options: see setPageFormat()

@param boolean :tocpage

if true set the tocpage state to true (the added page will be used to display Table of Content).

@access public
@since 4.2.010 (2008-11-14)
@see

AddPage(), endPage(), addTOCPage(), endTOCPage()



1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
# File 'lib/rbpdf.rb', line 1704

def startPage(orientation='', format='', tocpage=false)
  if tocpage
    @tocpage = true
  end
  if @numpages > @page
    # this page has been already added
    setPage(@page + 1)
    SetY(@t_margin)
    return
  end
  # start a new page
  if @state == 0
    Open()
  end
  @numpages += 1
  swapMargins(@booklet)
  # save current graphic settings
  gvars = getGraphicVars()
  # start new page
  beginpage(orientation, format)
  # mark page as open
  @pageopen[@page] = true
  # restore graphic settings
  setGraphicVars(gvars)
  # mark this point
  setPageMark()
  # print page header
  setHeader()
  # restore graphic settings
  setGraphicVars(gvars)
  # mark this point
  setPageMark()
  # print table header (if any)
  setTableHeader()
end

#startPageGroup(page = 0) ⇒ Object Also known as: start_page_group

Create a new page group.

  • NOTE: call this function before calling AddPage()

@param int :page

starting group page (leave empty for next page).

@access public
@since 3.0.000 (2008-03-27)


9691
9692
9693
9694
9695
9696
# File 'lib/rbpdf.rb', line 9691

def startPageGroup(page=0)
  if !page.is_a? Integer or page.zero?
    page = @page + 1
  end
  @newpagegroup[page] = true
end

#startTransactionObject Also known as: start_transaction

Stores a copy of the current RBPDF object used for undo operation.

@access public
@since 4.5.029 (2009-03-19)


14279
14280
14281
14282
14283
14284
14285
14286
14287
14288
14289
# File 'lib/rbpdf.rb', line 14279

def startTransaction()
  if @objcopy
    # remove previous copy
    commitTransaction()
  end
  # record current page number and Y position
  @start_transaction_page = @page
  @start_transaction_y = @y
  # clone current object
  @objcopy = objclone(self)
end

#StartTransformObject Also known as: start_transform

Starts a 2D tranformation saving current graphic state. This function must be called before scaling, mirroring, translation, rotation and skewing. Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior.

@access public
@since 2.1.000 (2008-01-07)
@see

StartTransform(), StopTransform()



8077
8078
8079
8080
8081
8082
# File 'lib/rbpdf.rb', line 8077

def StartTransform
  out('q');
  @transfmrk[@page] = @pagelen[@page]
  @transfmatrix_key += 1
  @transfmatrix[@transfmatrix_key] = []
end

#StopTransformObject Also known as: stop_transform

Stops a 2D tranformation restoring previous graphic state. This function must be called after scaling, mirroring, translation, rotation and skewing. Use StartTransform() before, and StopTransform() after the transformations to restore the normal behavior.

@access public
@since 2.1.000 (2008-01-07)
@see

StartTransform(), StopTransform()



8093
8094
8095
8096
8097
8098
8099
8100
# File 'lib/rbpdf.rb', line 8093

def StopTransform
  out('Q');
  if @transfmatrix[@transfmatrix_key]
    @transfmatrix[@transfmatrix_key].pop
    @transfmatrix_key -= 1
  end
  @transfmrk[@page] = nil
end

#Text(x, y, txt, fstroke = false, fclip = false, ffill = true, border = 0, ln = 0, align = '', fill = 0, link = '', stretch = 0, ignore_min_height = false, calign = 'T', valign = 'M', rtloff = false) ⇒ Object Also known as: text

Prints a text cell at the specified position. The origin is on the left of the first charcter, on the baseline. This method allows to place a string precisely on the page.

@param float :x

Abscissa of the cell origin

@param float :y

Ordinate of the cell origin

@param string :txt

String to print

@param int :fstroke

outline size in user units (false = disable)

@param boolean :fclip

if true activate clipping mode (you must call StartTransform() before this function and StopTransform() to stop the clipping tranformation).

@param boolean :ffill

if true fills the text

@param mixed :border

Indicates if borders must be drawn around the cell. The value can be either a number:

  • 0: no border (default)

  • 1: frame

or a string containing some or all of the following characters (in any order):

  • L: left

  • T: top

  • R: right

  • B: bottom

@param int :ln

Indicates where the current position should go after the call. Possible values are:

  • 0: to the right (or left for RTL languages)

  • 1: to the beginning of the next line

  • 2: below

Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.

@param string :align

Allows to center or align the text. Possible values are:

  • L or empty string: left align (default value)

  • C: center

  • R: right align

  • J: justify

@param int :fill

Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.

@param mixed :link

URL or identifier returned by AddLink().

@param int :stretch

stretch carachter mode:

  • 0 = disabled

  • 1 = horizontal scaling only if necessary

  • 2 = forced horizontal scaling

  • 3 = character spacing only if necessary

  • 4 = forced character spacing

@param boolean :ignore_min_height

if true ignore automatic minimum height value.

@param string :calign

cell vertical alignment relative to the specified Y value. Possible values are:

  • T : cell top

  • A : font top

  • L : font baseline

  • D : font bottom

  • B : cell bottom

@param string :valign

text vertical alignment inside the cell. Possible values are:

  • T : top

  • C : center

  • B : bottom

@param boolean :rtloff

if true uses the page top-left corner as origin of axis for :x and :y initial position.

@access public
@since 1.0
@see

SetFont(), SetTextColor(), Cell(), MultiCell(), Write()



3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
# File 'lib/rbpdf.rb', line 3119

def Text(x, y, txt, fstroke=false, fclip=false, ffill=true, border=0, ln=0, align='', fill=0, link='', stretch=0, ignore_min_height=false, calign='T', valign='M', rtloff=false)
  fstroke = 0 if fstroke == false

  textrendermode = @textrendermode
  textstrokewidth = @textstrokewidth
  setTextRenderingMode(fstroke, ffill, fclip)
  SetXY(x, y, rtloff)
  Cell(0, 0, txt, border, ln, align, fill, link, stretch, ignore_min_height, calign, valign)
  # restore previous rendering mode
  @textrendermode = textrendermode
  @textstrokewidth = textstrokewidth
end

#unhtmlentities(string) ⇒ Object

Reverse function for htmlentities. Convert entities in UTF-8.

@param :text_to_convert

Text to convert.

@return string

converted

@access public


8032
8033
8034
8035
8036
8037
8038
# File 'lib/rbpdf.rb', line 8032

def unhtmlentities(string)
  if @@decoder.nil?
    CGI.unescapeHTML(string)
  else
    @@decoder.decode(string)
  end
end

#UniArrSubString(uniarr, start = 0, last = uniarr.length) ⇒ Object Also known as: uni_arr_sub_string

Extract a slice of the :uniarr array and return it as string.

@param string :uniarr

The input array of characters. (UTF-8)

@param int :start

the starting element of :strarr.

[@param int :las]t first element that will not be returned.

@return

Return part of a string (UTF-8)

@access public
@since 4.5.037 (2009-04-07)


4591
4592
4593
4594
4595
4596
4597
# File 'lib/rbpdf.rb', line 4591

def UniArrSubString(uniarr, start=0, last=uniarr.length)
  string = ''
  start.upto(last - 1) do |i|
    string << uniarr[i]
  end
  return string
end

#unichr(c) ⇒ Object

Returns the unicode caracter specified by UTF-8 value

@param int :c

UTF-8 value (UCS4)

@return

Returns the specified character. (UTF-8)

@author

Miguel Perez, Nicola Asuni

@access public
@since 2.3.000 (2008-03-05)


4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
# File 'lib/rbpdf.rb', line 4624

def unichr(c)
  if !@is_unicode
    return c.chr
  elsif c <= 0x7F
    # one byte
    return c.chr
  elsif c <= 0x7FF
    # two bytes
    return (0xC0 | c >> 6).chr + (0x80 | c & 0x3F).chr
  elsif c <= 0xFFFF
    # three bytes
    return (0xE0 | c >> 12).chr + (0x80 | c >> 6 & 0x3F).chr + (0x80 | c & 0x3F).chr
  elsif c <= 0x10FFFF
    # four bytes
    return (0xF0 | c >> 18).chr + (0x80 | c >> 12 & 0x3F).chr + (0x80 | c >> 6 & 0x3F).chr + (0x80 | c & 0x3F).chr
  else
    return ""
  end
end

#UTF8ArrayToUniArray(ta) ⇒ Object Also known as: utf8_array_to_uni_array

Convert an array of UTF8 values to array of unicode characters

@param string :ta

The input array of UTF8 values. (UCS4)

@return

Return array of unicode characters (UTF-8)

@access public
@since 4.5.037 (2009-04-07)


4607
4608
4609
4610
4611
4612
4613
# File 'lib/rbpdf.rb', line 4607

def UTF8ArrayToUniArray(ta)
  string = []
  ta.each do |i|
    string << unichr(i)
  end
  return string
end

#UTF8ArrSubString(strarr, start = 0, last = strarr.size) ⇒ Object Also known as: utf8_arr_sub_string

Extract a slice of the :strarr array and return it as string.

@param string :strarr

The input array of characters. (UCS4)

@param int :start

the starting element of :strarr.

@param int :last

first element that will not be returned.

@return

Return part of a string (UTF-8)

@access public


4573
4574
4575
4576
4577
4578
4579
# File 'lib/rbpdf.rb', line 4573

def UTF8ArrSubString(strarr, start=0, last=strarr.size)
  string = ""
  start.upto(last - 1) do |i|
    string << unichr(strarr[i])
  end
  return string
end

#Write(h, txt, link = nil, fill = 0, align = '', ln = false, stretch = 0, firstline = false, firstblock = false, maxh = 0) ⇒ Object Also known as: write

This method prints text from the current position.

@param float :h

Line height

@param string :txt

String to print

@param mixed :link

URL or identifier returned by AddLink()

@param int :fill

Indicates if the background must be painted (1) or transparent (0). Default value: 0.

@param string :align

Allows to center or align the text. Possible values are:

  • L or empty string: left align (default value)

  • C: center

  • R: right align

  • J: justify

@param boolean :ln

if true set cursor at the bottom of the line, otherwise set cursor at the top of the line.

@param int :stretch

stretch carachter mode:

  • 0 = disabled

  • 1 = horizontal scaling only if necessary

  • 2 = forced horizontal scaling

  • 3 = character spacing only if necessary

  • 4 = forced character spacing

@param boolean :firstline

if true prints only the first line and return the remaining string.

@param boolean :firstblock

if true the string is the starting of a line.

@param float :maxh

maximum height. The remaining unprinted text will be returned. It should be >= :h and less then remaining space to the bottom of the page, or 0 for disable this feature.

@return mixed

Return the number of cells or the remaining string if :firstline = true.

@access public
@since 1.5


4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
# File 'lib/rbpdf.rb', line 4213

def Write(h, txt, link=nil, fill=0, align='', ln=false, stretch=0, firstline=false, firstblock=false, maxh=0)
  txt = txt.dup
  txt.force_encoding('ASCII-8BIT') if txt.respond_to?(:force_encoding)
  if txt.length == 0
    txt = ' '
  end

  # remove carriage returns
  s = txt.gsub("\r", '');

  # check if string contains arabic text
  if s =~ @@k_re_pattern_arabic
    arabic = true
  else
    arabic = false
  end

  # check if string contains RTL text
  if arabic or (@tmprtl == 'R') or (txt =~ @@k_re_pattern_rtl)
    rtlmode = true
  else
    rtlmode = false
  end

  # get a char width
  chrwidth = GetCharWidth('.')
  # get array of unicode values
  chars = UTF8StringToArray(s)
  # get array of chars
  uchars = UTF8ArrayToUniArray(chars)

  # get the number of characters
  nb = chars.size

  # replacement for SHY character (minus symbol)
  shy_replacement = 45
  shy_replacement_char = unichr(shy_replacement)
  # widht for SHY replacement
  shy_replacement_width = GetCharWidth(shy_replacement)

  # store current position
  prevx = @x
  prevy = @y

  # max Y
  maxy = @y + maxh - h - (2 * @c_margin)

  # calculating remaining line width (w)
  if @rtl
    w = @x - @l_margin
  else
    w = @w - @r_margin - @x
  end
  
  # max column width
  wmax = w - (2 * @c_margin)
  if !firstline and (chrwidth > wmax or (GetCharWidth(chars[0]) > wmax))
    # a single character do not fit on column
    return ''
  end

  i = 0    # character position
  j = 0    # current starting position
  sep = -1 # position of the last blank space
  shy = false # true if the last blank is a soft hypen (SHY)
  l = 0    # current string length
  nl = 0   # number of lines
  linebreak = false

  pc = 0 # previous character
  # for each character
  while(i<nb)
    if (maxh > 0) and (@y >= maxy)
      break
    end
    # Get the current character
    c = chars[i]
    if (c == 10) # 10 = "\n" = new line
      #Explicit line break
      if align == 'J'
        if @rtl
          talign = 'R'
        else
          talign = 'L'
        end
      else
        talign = align
      end
      tmpstr = UniArrSubString(uchars, j, i)
      if firstline
        startx = @x
        tmparr = chars[j, i - j]
        if rtlmode
          tmparr = utf8Bidi(tmparr, tmpstr, @tmprtl)
        end
        linew = GetArrStringWidth(tmparr)
        tmparr = ''
        if @rtl
          @endlinex = startx - linew
        else
          @endlinex = startx + linew
        end
        w = linew
        tmpcmargin = @c_margin
        if maxh == 0
          @c_margin = 0
        end
      end
      if firstblock and isRTLTextDir()
        tmpstr = tmpstr.rstrip
      end
      Cell(w, h, tmpstr, 0, 1, talign, fill, link, stretch)
      tmpstr = ''
      if firstline
        @c_margin = tmpcmargin
        return UniArrSubString(uchars, i)
      end
      nl += 1
      j = i + 1
      l = 0
      sep = -1
      shy = false;
      # account for margin changes
      if ((@y + @lasth) > @page_break_trigger) and !@in_footer
        AcceptPageBreak()
      end
      w = getRemainingWidth()
      wmax = w - (2 * @c_margin)
    else 
      # 160 is the non-breaking space, 173 is SHY (Soft Hypen)
      if (c != 160) and ((unichr(c) =~ /\s/) or (c == 173))
        # update last blank space position
        sep = i
        # check if is a SHY
        if c == 173
          shy = true
          if pc == 45
            tmp_shy_replacement_width = 0
            tmp_shy_replacement_char = ''
          else
            tmp_shy_replacement_width = shy_replacement_width
            tmp_shy_replacement_char = shy_replacement_char
          end
        else 
          shy = false
        end
      end

      # update string length
      if ((@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')) and arabic
        # with bidirectional algorithm some chars may be changed affecting the line length
        # *** very slow ***
        l = GetArrStringWidth(utf8Bidi(chars[j,i-j], '', @tmprtl))
      else
        l += GetCharWidth(c)
      end

      if (l > wmax) or ((c == 173) and ((l + tmp_shy_replacement_width) > wmax))
        # we have reached the end of column
        if (sep == -1)
          # check if the line was already started
          if (@rtl and (@x <= @w - @r_margin - chrwidth)) or (!@rtl and (@x >= @l_margin + chrwidth))
            # print a void cell and go to next line
            Cell(w, h, '', 0, 1)
            linebreak = true
            if firstline
              return UniArrSubString(uchars, j)
            end
          else
            # truncate the word because do not fit on column
            tmpstr = UniArrSubString(uchars, j, i)
            if firstline
              startx = @x
              tmparr = chars[j, i - j]
              if rtlmode
                tmparr = utf8Bidi(tmparr, tmpstr, @tmprtl)
              end
              linew = GetArrStringWidth(tmparr)
              tmparr = ''
              if @rtl
                @endlinex = startx - linew
              else
                @endlinex = startx + linew
              end
              w = linew
              tmpcmargin = @c_margin
              if maxh == 0
                @c_margin = 0
              end
            end
            if firstblock and isRTLTextDir()
              tmpstr = tmpstr.rstrip
            end
            Cell(w, h, tmpstr, 0, 1, align, fill, link, stretch)
            tmpstr = ''
            if firstline
              @c_margin = tmpcmargin
              return UniArrSubString(uchars, i)
            end
            j = i
            i -= 1
          end
        else
          # word wrapping
          if @rtl and !firstblock
            endspace = 1
          else
            endspace = 0
          end
          if shy
            # add hypen (minus symbol) at the end of the line
            shy_width = tmp_shy_replacement_width
            if @rtl
              shy_char_left = tmp_shy_replacement_char
              shy_char_right = ''
            else
              shy_char_left = ''
              shy_char_right = tmp_shy_replacement_char
            end
          else
            shy_width = 0
            shy_char_left = ''
            shy_char_right = ''
          end
          tmpstr = UniArrSubString(uchars, j, sep + endspace)
          if firstline
            startx = @x
            tmparr = chars[j, sep + endspace - j]
            if rtlmode
              tmparr = utf8Bidi(tmparr, tmpstr, @tmprtl)
            end
            linew = GetArrStringWidth(tmparr)
            tmparr = ''
            if @rtl
              @endlinex = startx - linew - shy_width
            else
              @endlinex = startx + linew + shy_width
            end
            w = linew
            tmpcmargin = @c_margin
            if maxh == 0
              @c_margin = 0
            end
          end
          # print the line
          if firstblock and isRTLTextDir()
            tmpstr = tmpstr.rstrip
          end
          Cell(w, h, shy_char_left + tmpstr + shy_char_right, 0, 1, align, fill, link, stretch)
          tmpstr = ''
          if firstline
            # return the remaining text
            @c_margin = tmpcmargin
            return UniArrSubString(uchars, sep + endspace)
          end
          i = sep
          sep = -1
          shy = false
          j = i + 1
        end
        # account for margin changes
        if (@y + @lasth > @page_break_trigger) and !@in_footer
          AcceptPageBreak()
        end
        w = getRemainingWidth()
        wmax = w - (2 * @c_margin)
        if linebreak
          linebreak = false
        else
          nl += 1
          l = 0
        end
      end
    end
    # save last character
    pc = c
    i +=1
  end # end while i < nb

  # print last substring (if any)
  if l > 0
    case align
    when 'J' , 'C'
      w = w
    when 'L'
      if @rtl
        w = w
      else
        w = l
      end
    when 'R'
      if @rtl
        w = l
      else
        w = w
      end
    else
      w = l
    end
    tmpstr = UniArrSubString(uchars, j, nb)
    if firstline
      startx = @x
      tmparr = chars[j, nb - j]
      if rtlmode
        tmparr = utf8Bidi(tmparr, tmpstr, @tmprtl)
      end
      linew = GetArrStringWidth(tmparr)
      tmparr = ''
      if @rtl
        @endlinex = startx - linew
      else
        @endlinex = startx + linew
      end
      w = linew
      tmpcmargin = @c_margin
      if maxh == 0
        @c_margin = 0
      end
    end
    if firstblock and isRTLTextDir()
      tmpstr = tmpstr.rstrip
    end
    Cell(w, h, tmpstr, 0, (ln ? 1 : 0), align, fill, link, stretch)
    tmpstr = ''
    if firstline
      @c_margin = tmpcmargin
      return UniArrSubString(uchars, nb)
    end
    nl += 1
  end

  if firstline
    return ''
  end
  return nl
end

#writeHTML(html, ln = true, fill = 0, reseth = false, cell = false, align = '') ⇒ Object Also known as: write_html

Allows to preserve some HTML formatting (limited support). IMPORTANT: The HTML must be well formatted - try to clean-up it using an application like HTML-Tidy before submitting. Supported tags are: a, b, blockquote, br, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, img, li, ol, p, pre, small, span, strong, sub, sup, table, td, th, thead, tr, tt, u, ul

@param string :html

text to display

@param boolean :ln

if true add a new line after text (default = true)

@param int :fill

Indicates if the background must be painted (1:true) or transparent (0:false).

@param boolean :reseth

if true reset the last cell height (default false).

@param boolean :cell

if true add the default c_margin space to each Write (default false).

@param string :align

Allows to center or align the text. Possible values are:

  • L : left align

  • C : center

  • R : right align

  • ” : empty string : left for LTR or right for RTL

@access public


11262
11263
11264
11265
11266
11267
11268
11269
11270
11271
11272
11273
11274
11275
11276
11277
11278
11279
11280
11281
11282
11283
11284
11285
11286
11287
11288
11289
11290
11291
11292
11293
11294
11295
11296
11297
11298
11299
11300
11301
11302
11303
11304
11305
11306
11307
11308
11309
11310
11311
11312
11313
11314
11315
11316
11317
11318
11319
11320
11321
11322
11323
11324
11325
11326
11327
11328
11329
11330
11331
11332
11333
11334
11335
11336
11337
11338
11339
11340
11341
11342
11343
11344
11345
11346
11347
11348
11349
11350
11351
11352
11353
11354
11355
11356
11357
11358
11359
11360
11361
11362
11363
11364
11365
11366
11367
11368
11369
11370
11371
11372
11373
11374
11375
11376
11377
11378
11379
11380
11381
11382
11383
11384
11385
11386
11387
11388
11389
11390
11391
11392
11393
11394
11395
11396
11397
11398
11399
11400
11401
11402
11403
11404
11405
11406
11407
11408
11409
11410
11411
11412
11413
11414
11415
11416
11417
11418
11419
11420
11421
11422
11423
11424
11425
11426
11427
11428
11429
11430
11431
11432
11433
11434
11435
11436
11437
11438
11439
11440
11441
11442
11443
11444
11445
11446
11447
11448
11449
11450
11451
11452
11453
11454
11455
11456
11457
11458
11459
11460
11461
11462
11463
11464
11465
11466
11467
11468
11469
11470
11471
11472
11473
11474
11475
11476
11477
11478
11479
11480
11481
11482
11483
11484
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495
11496
11497
11498
11499
11500
11501
11502
11503
11504
11505
11506
11507
11508
11509
11510
11511
11512
11513
11514
11515
11516
11517
11518
11519
11520
11521
11522
11523
11524
11525
11526
11527
11528
11529
11530
11531
11532
11533
11534
11535
11536
11537
11538
11539
11540
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601
11602
11603
11604
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
11616
11617
11618
11619
11620
11621
11622
11623
11624
11625
11626
11627
11628
11629
11630
11631
11632
11633
11634
11635
11636
11637
11638
11639
11640
11641
11642
11643
11644
11645
11646
11647
11648
11649
11650
11651
11652
11653
11654
11655
11656
11657
11658
11659
11660
11661
11662
11663
11664
11665
11666
11667
11668
11669
11670
11671
11672
11673
11674
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688
11689
11690
11691
11692
11693
11694
11695
11696
11697
11698
11699
11700
11701
11702
11703
11704
11705
11706
11707
11708
11709
11710
11711
11712
11713
11714
11715
11716
11717
11718
11719
11720
11721
11722
11723
11724
11725
11726
11727
11728
11729
11730
11731
11732
11733
11734
11735
11736
11737
11738
11739
11740
11741
11742
11743
11744
11745
11746
11747
11748
11749
11750
11751
11752
11753
11754
11755
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769
11770
11771
11772
11773
11774
11775
11776
11777
11778
11779
11780
11781
11782
11783
11784
11785
11786
11787
11788
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811
11812
11813
11814
11815
11816
11817
11818
11819
11820
11821
11822
11823
11824
11825
11826
11827
11828
11829
11830
11831
11832
11833
11834
11835
11836
11837
11838
11839
11840
11841
11842
11843
11844
11845
11846
11847
11848
11849
11850
11851
11852
11853
11854
11855
11856
11857
11858
11859
11860
11861
11862
11863
11864
11865
11866
11867
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878
11879
11880
11881
11882
11883
11884
11885
11886
11887
11888
11889
11890
11891
11892
11893
11894
11895
11896
11897
11898
11899
11900
11901
11902
11903
11904
11905
11906
11907
11908
11909
11910
11911
11912
11913
11914
11915
11916
11917
11918
11919
11920
11921
11922
11923
11924
11925
11926
11927
11928
11929
11930
11931
11932
11933
11934
11935
11936
11937
11938
11939
11940
11941
11942
11943
11944
11945
11946
11947
11948
11949
11950
11951
11952
11953
11954
11955
11956
11957
11958
11959
11960
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972
11973
11974
11975
11976
11977
11978
11979
11980
11981
11982
11983
11984
11985
11986
11987
11988
11989
11990
11991
11992
11993
11994
11995
11996
11997
11998
11999
12000
12001
12002
12003
12004
12005
12006
12007
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026
12027
12028
12029
12030
12031
12032
12033
12034
12035
12036
12037
12038
12039
12040
12041
12042
12043
12044
12045
12046
12047
12048
12049
12050
12051
12052
12053
12054
12055
12056
12057
12058
12059
12060
12061
12062
12063
12064
12065
12066
12067
12068
12069
12070
12071
12072
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130
12131
12132
12133
12134
12135
12136
12137
12138
12139
12140
12141
12142
12143
12144
12145
12146
12147
12148
12149
12150
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161
12162
12163
12164
12165
12166
12167
12168
12169
12170
12171
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197
12198
12199
12200
12201
12202
12203
12204
12205
12206
12207
12208
12209
12210
12211
12212
12213
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254
12255
12256
12257
12258
12259
12260
12261
12262
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278
12279
12280
12281
12282
12283
12284
12285
12286
12287
12288
12289
12290
12291
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
12328
12329
12330
12331
12332
12333
12334
12335
12336
12337
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363
12364
12365
12366
12367
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397
12398
12399
12400
# File 'lib/rbpdf.rb', line 11262

def writeHTML(html, ln=true, fill=0, reseth=false, cell=false, align='')
  ln = false if ln == 0
  reseth = false if reseth == 0
  cell = false if cell == 0
  case fill
  when true
    fill = 1 
  when false
    fill = 0 
  end

  gvars = getGraphicVars()
  # store current values
  prevPage = @page
  prevlMargin = @l_margin
  prevrMargin = @r_margin
  curfontname = @font_family
  curfontstyle = @font_style
  curfontsize = @font_size_pt
  curfontascent = getFontAscent(curfontname, curfontstyle, curfontsize)
  curfontdescent = getFontDescent(curfontname, curfontstyle, curfontsize)
  @newline = true
  startlinepage = @page
  minstartliney = @y
  maxbottomliney = 0
  startlinex = @x
  startliney = @y
  yshift = 0
  newline = true
  loop = 0
  curpos = 0
  opentagpos = nil
  this_method_vars = {}
  undo = false
  fontaligned = false
  @premode = false
  if !@page_annots[@page].nil?
    pask = @page_annots[@page].length
  else
    pask = 0
  end
  if !@in_footer
    if !@footerlen[@page].nil?
      @footerpos[@page] = @pagelen[@page] - @footerlen[@page]
    else
      @footerpos[@page] = @pagelen[@page]
    end
    startlinepos = @footerpos[@page]
  else
    startlinepos = @pagelen[@page]
  end
  lalign = align
  plalign = align
  if @rtl
    w = @x - @l_margin
  else
    w = @w - @r_margin - @x
  end
  w -= 2 * @c_margin

  if cell
    if @rtl
      @x -= @c_margin
    else
      @x += @c_margin
    end
  end
  if @customlistindent >= 0
    @listindent = @customlistindent
  else
    @listindent = GetStringWidth('0000')
  end
  @listindentlevel = 0
  # save previous states
  prev_cell_height_ratio = @cell_height_ratio
  prev_listnum = @listnum
  prev_listordered = @listordered
  prev_listcount = @listcount
  prev_lispacer = @lispacer
  @listnum = 0
  @listordered = []
  @listcount = []
  @lispacer = ''
  if empty_string(@lasth) or reseth
    #set row height
    @lasth = @font_size * @cell_height_ratio
  end
  dom = getHtmlDomArray(html)
  maxel = dom.size
  key = 0
  while key < maxel
    if dom[key]['tag'] and dom[key]['attribute'] and dom[key]['attribute']['pagebreak']
      # check for pagebreak 
      if (dom[key]['attribute']['pagebreak'] == 'true') or (dom[key]['attribute']['pagebreak'] == 'left') or (dom[key]['attribute']['pagebreak'] == 'right')
        # add a page (or trig AcceptPageBreak() for multicolumn mode)
        checkPageBreak(@page_break_trigger + 1)
      end
      if ((dom[key]['attribute']['pagebreak'] == 'left') and ((!@rtl and (@page % 2 == 0)) or (@rtl and (@page % 2 != 0)))) or ((dom[key]['attribute']['pagebreak'] == 'right') and ((!@rtl and (@page % 2 != 0)) or (@rtl and (@page % 2 == 0))))
        # add a page (or trig AcceptPageBreak() for multicolumn mode)
        checkPageBreak(@page_break_trigger + 1)
      end
    end
    if dom[key]['tag'] and dom[key]['opening'] and dom[key]['attribute']['nobr'] and (dom[key]['attribute']['nobr'] == 'true')
      if dom[(dom[key]['parent'])]['attribute']['nobr'] and (dom[(dom[key]['parent'])]['attribute']['nobr'] == 'true')
        dom[key]['attribute']['nobr'] = false
      else
        # store current object
        startTransaction()
        # save this method vars
        this_method_vars['html'] = html.dup
        this_method_vars['ln'] = ln
        this_method_vars['fill'] = fill
        this_method_vars['reseth'] = reseth
        this_method_vars['cell'] = cell
        this_method_vars['align'] = align.dup
        this_method_vars['gvars'] = Marshal.load(Marshal.dump(gvars))
        this_method_vars['prevPage'] = prevPage
        this_method_vars['prevlMargin'] = prevlMargin
        this_method_vars['prevrMargin'] = prevrMargin
        this_method_vars['curfontname'] = curfontname.dup
        this_method_vars['curfontstyle'] = curfontstyle.dup
        this_method_vars['curfontsize'] = curfontsize
        this_method_vars['curfontascent'] = curfontascent
        this_method_vars['curfontdescent'] = curfontdescent
        this_method_vars['minstartliney'] = minstartliney
        this_method_vars['maxbottomliney'] = maxbottomliney
        this_method_vars['yshift'] = yshift
        this_method_vars['startlinepage'] = startlinepage
        this_method_vars['startlinepos'] = startlinepos
        this_method_vars['startlinex'] = startlinex
        this_method_vars['startliney'] = startliney
        this_method_vars['newline'] = newline
        this_method_vars['loop'] = loop
        this_method_vars['curpos'] = curpos
        this_method_vars['pask'] = pask
        this_method_vars['lalign'] = lalign
        this_method_vars['plalign'] = plalign
        this_method_vars['w'] = w
        this_method_vars['prev_cell_height_ratio'] = prev_cell_height_ratio
        this_method_vars['prev_listnum'] = prev_listnum
        this_method_vars['prev_listordered'] = prev_listordered
        this_method_vars['prev_listcount'] = prev_listcount
        this_method_vars['prev_lispacer'] = prev_lispacer
        this_method_vars['fontaligned'] = fontaligned
        this_method_vars['key'] = key
        this_method_vars['dom'] = Marshal.load(Marshal.dump(dom))
      end
    end
    # print THEAD block
    if (dom[key]['value'] == 'tr') and dom[key]['thead'] and dom[key]['thead']
      if dom[key]['parent'] and dom[(dom[key]['parent'])]['thead'] and !empty_string(dom[(dom[key]['parent'])]['thead'])
        @in_thead = true
        # print table header (thead)
        writeHTML(@thead, false, false, false, false, '')
        if (@start_transaction_page == (@numpages - 1)) or (@y < @start_transaction_y) or checkPageBreak(@lasth, '', false)
          # restore previous object
          rollbackTransaction(true)
          # restore previous values
          this_method_vars.each {|vkey , vval|
            eval("#{vkey} = vval") 
          }
          # add a page (or trig AcceptPageBreak() for multicolumn mode)
          pre_y = @y
          if !checkPageBreak(@page_break_trigger + 1) and (@y < pre_y)
            # fix for multicolumn mode
            startliney = @y
          end
          @start_transaction_page = @page
          @start_transaction_y = @y
        end
      end
      # move :key index forward to skip THEAD block
      while (key < maxel) and !((dom[key]['tag'] and dom[key]['opening'] and (dom[key]['value'] == 'tr') and (dom[key]['thead'].nil? or !dom[key]['thead'])) or (dom[key]['tag'] and !dom[key]['opening'] and (dom[key]['value'] == 'table')))
        key += 1
      end
    end
    if dom[key]['tag'] or (key == 0)
      if dom[key]['line-height']
        # set line height
        @cell_height_ratio = dom[key]['line-height']
        @lasth = @font_size * @cell_height_ratio
      end
      if ((dom[key]['value'] == 'table') or (dom[key]['value'] == 'tr')) and !dom[key]['align'].nil?
        dom[key]['align'] = @rtl ? 'R' : 'L'
      end
      # vertically align image in line
      if !@newline and (dom[key]['value'] == 'img') and !dom[key]['attribute']['height'].nil? and (dom[key]['attribute']['height'].to_i > 0)
        # get image height
        imgh = getHTMLUnitToUnits(dom[key]['attribute']['height'], @lasth, 'px')
        # check for automatic line break
        autolinebreak = false
        if dom[key]['attribute']['width'] and (dom[key]['attribute']['width'].to_i > 0)
          imgw = getHTMLUnitToUnits(dom[key]['attribute']['width'], 1, 'px', false)
          if (@rtl and (@x - imgw < @l_margin + @c_margin)) or (!@rtl and (@x + imgw > @w - @r_margin - @c_margin))
            # add automatic line break
            autolinebreak = true
            Ln('', cell)
            # go back to evaluate this line break
            key -= 1
          end
        end
        if !autolinebreak
          if !@in_footer
            pre_y = @y
            # check for page break
            if !checkPageBreak(imgh) and (@y < pre_y)
              # fix for multicolumn mode
              startliney = @y
            end
          end
          if @page > startlinepage
            # fix line splitted over two pages
            if !@footerlen[startlinepage].nil?
              curpos = @pagelen[startlinepage] - @footerlen[startlinepage]
            end
            # line to be moved one page forward
            pagebuff = getPageBuffer(startlinepage)
            linebeg = pagebuff[startlinepos, curpos - startlinepos]
            tstart = pagebuff[0, startlinepos]
            tend = pagebuff[curpos..-1]
            # remove line from previous page
            setPageBuffer(startlinepage, tstart + '' + tend)
            pagebuff = getPageBuffer(@page)
            tstart = pagebuff[0, @cntmrk[@page]]
            tend = pagebuff[@cntmrk[@page]..-1]
            # add line start to current page
            yshift = minstartliney - @y
            if fontaligned
              yshift += curfontsize / @k
            end
            try = sprintf('1 0 0 1 0 %.3f cm', (yshift * @k))
            setPageBuffer(@page, tstart + "\nq\n" + try + "\n" + linebeg + "\nQ\n" + tend)
            # shift the annotations and links
            if @page_annots[@page]
              next_pask = @page_annots[@page].length
            else
              next_pask = 0
            end
            if !@page_annots[startlinepage].nil?
              @page_annots[startlinepage].each_with_index { |pac, pak|
                if pak >= pask
                  @page_annots[@page].push pac
                  @page_annots[startlinepage].delete_at(pak)
                  npak = @page_annots[@page].length - 1
                  @page_annots[@page][npak]['y'] -= yshift
                end
              }
            end
            pask = next_pask
            startlinepos = @cntmrk[@page]
            startlinepage = @page
            startliney = @y
          end
          @y += ((curfontsize * @cell_height_ratio / @k) + curfontascent - curfontdescent) / 2  - imgh
          minstartliney = [@y, minstartliney].min
          maxbottomliney = startliney + @font_size * @cell_height_ratio
        end
      elsif !dom[key]['fontname'].nil? or !dom[key]['fontstyle'].nil? or !dom[key]['fontsize'].nil?
        # account for different font size
        pfontname = curfontname
        pfontstyle = curfontstyle
        pfontsize = curfontsize
        fontname  = !dom[key]['fontname'].nil?  ? dom[key]['fontname']  : curfontname
        fontstyle = !dom[key]['fontstyle'].nil? ? dom[key]['fontstyle'] : curfontstyle
        fontsize  = !dom[key]['fontsize'].nil?  ? dom[key]['fontsize']  : curfontsize
        fontascent = getFontAscent(fontname, fontstyle, fontsize)
        fontdescent = getFontDescent(fontname, fontstyle, fontsize)
        if (fontname != curfontname) or (fontstyle != curfontstyle) or (fontsize != curfontsize)
          if fontsize.is_a?(Numeric) and (fontsize >= 0) and curfontsize.is_a?(Numeric) and (curfontsize >= 0) and (fontsize != curfontsize) and !@newline and (key < maxel - 1)
            if !@newline and (@page > startlinepage)
              # fix lines splitted over two pages
              if !@footerlen[startlinepage].nil?
                curpos = @pagelen[startlinepage] - @footerlen[startlinepage]
              end
              # line to be moved one page forward
              pagebuff = getPageBuffer(startlinepage)
              linebeg = pagebuff[startlinepos, curpos - startlinepos]
              tstart = pagebuff[0, startlinepos]
              tend = pagebuff[curpos..-1]
              # remove line from previous page
              setPageBuffer(startlinepage, tstart + '' + tend)
              pagebuff = getPageBuffer(@page)
              tstart = pagebuff[0, @cntmrk[@page]]
              tend = pagebuff[@cntmrk[@page]..-1]
              # add line start to current page
              yshift = minstartliney - @y
              try = sprintf('1 0 0 1 0 %.3f cm', yshift * @k)
              setPageBuffer(@page, tstart + "\nq\n" + try + "\n" + linebeg + "\nQ\n" + tend)
              # shift the annotations and links
              if @page_annots[@page]
                next_pask = @page_annots[@page].length
              else
                next_pask = 0
              end
              if !@page_annots[startlinepage].nil?
                @page_annots[startlinepage].each_with_index { |pac, pak|
                  if pak >= pask
                    @page_annots[@page].push = pac
                    @page_annots[startlinepage].delete_at(pak)
                    npak = @page_annots[@page].length - 1
                    @page_annots[@page][npak]['y'] -= yshift
                  end
                }
              end
              pask = next_pask
              startlinepos = @cntmrk[@page]
              startlinepage = @page
              startliney = @y
            end
            if !dom[key]['block']
              @y += (((curfontsize - fontsize) * @cell_height_ratio / @k) + curfontascent - fontascent - curfontdescent + fontdescent) / 2
              if (dom[key]['value'] != 'sup') and (dom[key]['value'] != 'sub')
                minstartliney = [@y, minstartliney].min
                maxbottomliney = [@y + ((fontsize * @cell_height_ratio) / @k), maxbottomliney].max
              end
            end
            fontaligned = true
          end
          SetFont(fontname, fontstyle, fontsize)
          @lasth = @font_size * @cell_height_ratio
          curfontname = fontname
          curfontstyle = fontstyle
          curfontsize = fontsize
          curfontascent = fontascent
          curfontdescent = fontdescent
        end
      end
      # set text rendering mode
      textstroke = !dom[key]['stroke'].nil? ? dom[key]['stroke'] : @textstrokewidth
      textfill = !dom[key]['fill'].nil? ? dom[key]['fill'] : ((@textrendermode % 2) == 0) 
      textclip = !dom[key]['clip'].nil? ? dom[key]['clip'] : (@textrendermode > 3)
      setTextRenderingMode(textstroke, textfill, textclip)
      if (plalign == 'J') and dom[key]['block']
        plalign = ''
      end
      # get current position on page buffer
      curpos = @pagelen[startlinepage]
      if !dom[key]['bgcolor'].nil? and (dom[key]['bgcolor'].length > 0)
        SetFillColorArray(dom[key]['bgcolor'])
        wfill = 1
      else
        wfill = fill
      end
      if !dom[key]['fgcolor'].nil? and (dom[key]['fgcolor'].length > 0)
        SetTextColorArray(dom[key]['fgcolor'])
      end
      if !dom[key]['strokecolor'].nil? and (dom[key]['strokecolor'].length > 0)
        SetDrawColorArray(dom[key]['strokecolor'])
      end
      if !dom[key]['align'].nil?
        lalign = dom[key]['align']
      end
      if empty_string(lalign)
        lalign = align
      end
    end
    # align lines
    if @newline and (dom[key]['value'].length > 0) and (dom[key]['value'] != 'td') and (dom[key]['value'] != 'th')
      newline = true
      fontaligned = false
      # we are at the beginning of a new line
      if !startlinex.nil?
        yshift = minstartliney - startliney
        if (yshift > 0) or (@page > startlinepage)
          yshift = 0
        end
        t_x = 0
        # the last line must be shifted to be aligned as requested
        linew = (@endlinex - startlinex).abs
        pstart = getPageBuffer(startlinepage)[0, startlinepos]
        if !opentagpos.nil? and !@footerlen[startlinepage].nil? and !@in_footer
          @footerpos[startlinepage] = @pagelen[startlinepage] - @footerlen[startlinepage]
          midpos = [opentagpos, @footerpos[startlinepage]].min
        elsif !opentagpos.nil?
          midpos = opentagpos
        elsif !@footerlen[startlinepage].nil? and !@in_footer
          @footerpos[startlinepage] = @pagelen[startlinepage] - @footerlen[startlinepage]
          midpos = @footerpos[startlinepage]
        else
          midpos = 0
        end
        if midpos > 0
          pmid = getPageBuffer(startlinepage)[startlinepos, midpos - startlinepos]
          pend = getPageBuffer(startlinepage)[midpos..-1]
        else
          pmid = getPageBuffer(startlinepage)[startlinepos..-1]
          pend = ''
        end
        if (!plalign.nil? and ((plalign == 'C') or (plalign == 'J') or ((plalign == 'R') and !@rtl) or ((plalign == 'L') and @rtl))) or (yshift < 0)
          # calculate shifting amount
          tw = w
          if (plalign == 'J') and isRTLTextDir() and (@num_columns > 1)
            tw += @c_margin
          end
          if @l_margin != prevlMargin
            tw += prevlMargin - @l_margin
          end
          if @r_margin != prevrMargin
            tw += prevrMargin - @r_margin
          end
          one_space_width = GetStringWidth(32.chr)
          mdiff = (tw - linew).abs
          if plalign == 'C'
            if @rtl
              t_x = -(mdiff / 2)
            else
              t_x = (mdiff / 2)
            end
          elsif (plalign == 'R') and !@rtl
            # right alignment on LTR document
            if revstrpos(pmid, ')]').to_i == revstrpos(pmid, ' )]').to_i + 1
              # remove last space (if any)
              linew -= one_space_width
              mdiff = (tw - linew).abs
            end
            t_x = mdiff
          elsif (plalign == 'L') and @rtl
            # left alignment on RTL document
            if revstrpos(pmid, '[(') and ((revstrpos(pmid, '[( ').to_i == revstrpos(pmid, '[(').to_i) or (revstrpos(pmid, '[(' + 0.chr + 32.chr).to_i == revstrpos(pmid, '[(').to_i))
              # remove first space (if any)
              linew -= one_space_width
            end
            if pmid.index('[(') and (pmid.index('[(').to_i == revstrpos(pmid, '[(').to_i)
              # remove last space (if any)
              linew -= one_space_width
              if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
                linew -= one_space_width
              end
            end
            mdiff = (tw - linew).abs
            t_x = -mdiff
          elsif (plalign == 'J') and (plalign == lalign)
            # Justification
            if isRTLTextDir()
              t_x = @l_margin - @endlinex + @c_margin
            end
            no = 0 # spaces without trim
            ns = 0 # spaces with trim

            pmidtemp = pmid
            # escape special characters
            pmidtemp.gsub!(/[\\][\(]/x, '\\#!#OP#!#')
            pmidtemp.gsub!(/[\\][\)]/x, '\\#!#CP#!#')
            # search spaces
            lnstring = pmidtemp.scan(/\[\(([^\)]*)\)\]/x)
            if !lnstring.empty?
              spacestr = getSpaceString()
              maxkk = lnstring.length - 1
              0.upto(maxkk) do |kk|
                # restore special characters
                lnstring[kk][0].gsub!('#!#OP#!#', '(')
                lnstring[kk][0].gsub!('#!#CP#!#', ')')
                if kk == maxkk
                  if isRTLTextDir()
                    tvalue = lnstring[kk][0].lstrip
                  else
                    tvalue = lnstring[kk][0].rstrip
                  end
                else
                  tvalue = lnstring[kk][0]
                end
                # store number of spaces on the strings
                lnstring[kk][1] = lnstring[kk][0].count(spacestr)
                lnstring[kk][2] = tvalue.count(spacestr)
                # count total spaces on line
                no += lnstring[kk][1]
                ns += lnstring[kk][2]
                lnstring[kk][3] = no
                lnstring[kk][4] = ns
              end
              if isRTLTextDir()
                t_x = @l_margin - @endlinex + @c_margin - ((no - ns) * one_space_width)
              end
              # calculate additional space to add to each space
              spacelen = one_space_width
              spacewidth = (((tw - linew) + ((no - ns) * spacelen)) / (ns ? ns : 1)) * @k
              spacewidthu = -1000 * ((tw - linew) + (no * spacelen)) / (ns ? ns : 1) / @font_size
              nsmax = ns
              ns = 0
              # reset(lnstring)
              offset = 0
              strcount = 0
              prev_epsposbeg = 0
              textpos = 0;
              if isRTLTextDir()
                textpos = @w_pt
              end
              while pmid_offset = pmid.index(/([0-9\.\+\-]*)[\s](Td|cm|m|l|c|re)[\s]/x, offset)
                pmid_data = $1
                pmid_mark = $2
                # check if we are inside a string section '[( ... )]'
                stroffset = pmid.index('[(', offset)
                if (stroffset != nil) and (stroffset <= pmid_offset)
                  # set offset to the end of string section 
                  offset = pmid.index(')]', stroffset)
                  while (offset != nil) and (pmid[offset - 1, 1] == '\\')
                    offset = pmid.index(')]', offset + 1)
                  end
                  if offset == false
                    Error('HTML Justification: malformed PDF code.')
                  end
                  next
                end
                if isRTLTextDir()
                  spacew = spacewidth * (nsmax - ns)
                else
                  spacew = spacewidth * ns
                end
                offset = pmid_offset + $&.length
                epsposbeg = pmid.index('q' + @epsmarker, offset)
                epsposbeg = 0 if epsposbeg.nil?
                epsposend = pmid.index(@epsmarker + 'Q', offset)
                epsposend = 0 if epsposend.nil?
                epsposend += (@epsmarker + 'Q').length
                if ((epsposbeg > 0) and (epsposend > 0) and (offset > epsposbeg) and (offset < epsposend)) or ((epsposbeg === false) and (epsposend > 0) and (offset < epsposend))
                  # shift EPS images
                  trx = sprintf('1 0 0 1 %.3f 0 cm', spacew)
                  epsposbeg = pmid.index('q' + @epsmarker, prev_epsposbeg - 6)
                  epsposbeg = 0 if epsposbeg.nil?
                  pmid_b = pmid[0, epsposbeg]
                  pmid_m = pmid[epsposbeg, epsposend - epsposbeg]
                  pmid_e = pmid[epsposend..-1]
                  pmid = pmid_b + "\nq\n" + trx + "\n" + pmid_m + "\nQ\n" + pmid_e
                  offset = epsposend
                  next
                end
                prev_epsposbeg = epsposbeg
                currentxpos = 0
                # shift blocks of code
                case pmid_mark
                when 'Td', 'cm', 'm', 'l'
                  # get current X position
                  pmid =~ /([0-9\.\+\-]*)[\s](#{pmid_data})[\s](#{pmid_mark})([\s]*)/x
                  currentxpos = $1.to_i
                  textpos = currentxpos
                  if (strcount <= maxkk) and (pmid_mark == 'Td')
                    if strcount == maxkk
                      if isRTLTextDir()
                        tvalue = lnstring[strcount][0]
                      else
                        tvalue = lnstring[strcount][0].rstrip
                      end
                    else
                      tvalue = lnstring[strcount][0]
                    end
                    ns += tvalue.count(spacestr)
                    strcount += 1
                  end
                  if isRTLTextDir()
                    spacew = spacewidth * (nsmax - ns)
                  end
                  # justify block
                  pmid.sub!(/([0-9\.\+\-]*)[\s](#{pmid_data})[\s](#{pmid_mark})([\s]*)/x, "" + sprintf("%.2f", $1.to_f + spacew) + " " + $2 + " x*#!#*x" + $3 + $4)
                when 're'
                  # justify block
                  pmid =~ /([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s](#{pmid_data})[\s](re)([\s]*)/x
                  currentxpos = $1.to_i
                  x_diff = 0
                  w_diff = 0
                  if isRTLTextDir() # RTL
                    if currentxpos < textpos
                      x_diff = spacewidth * (nsmax - lnstring[strcount][4])
                      w_diff = spacewidth * lnstring[strcount][2]
                    else
                      if strcount > 0
                        x_diff = spacewidth * (nsmax - lnstring[strcount - 1][4])
                        w_diff = spacewidth * lnstring[strcount - 1][2]
                      end
                    end
                  else # LTR
                    if currentxpos > textpos
                      if strcount > 0
                        x_diff = spacewidth * lnstring[strcount - 1][3]
                      end
                      w_diff = spacewidth * lnstring[strcount][2]
                    else
                      if strcount > 1
                        x_diff = spacewidth * lnstring[strcount - 2][3]
                      end
                      if strcount > 0
                        w_diff = spacewidth * lnstring[strcount - 1][2]
                      end
                    end
                  end
                  pmid.sub!(/(#{$1})[\s](#{$2})[\s](#{$3})[\s](#{pmid_data})[\s](re)([\s]*)/x, "" + sprintf("%.2f", $1.to_f + x_diff) + " " + $2 + " " + sprintf("%.2f", $3.to_f + w_diff) + " " + $4 + " x*#!#*x" + $5 + $6)
                when 'c'
                  # get current X position
                  pmid =~ /([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s](#{pmid_data})[\s](c)([\s]*)/x
                  currentxpos = $1.to_i
                  # justify block
                  pmid.sub!(/(#{$1})[\s](#{$2})[\s](#{$3})[\s](#{$4})[\s](${5})[\s](#{pmid_data})[\s](c)([\s]*)/x, "" + sprintf("%.3f", $1.to_f + spacew) + " " + $2 + " " +  sprintf("%.3f", $3.to_f + spacew) + " " + $4 + " " + sprintf("%.3f", $5.to_f + spacew) + " " + $6 + " x*#!#*x" + $7 + $8)
                end
                # shift the annotations and links
                if !@page_annots[@page].nil?
                  cxpos = currentxpos / @k
                  lmpos = @l_margin + @c_margin + @feps

                  @page_annots[@page].each_with_index { |pac, pak|
                    if (pac['y'] >= minstartliney) and (pac['x'] * @k >= currentxpos - @feps) and (pac['x'] * @k <= currentxpos + @feps)
                      if cxpos > lmpos
                        @page_annots[@page][pak]['x'] += (spacew - one_space_width) / @k
                        @page_annots[@page][pak]['w'] += (spacewidth * pac['numspaces']) / @k
                      else
                        @page_annots[@page][pak]['w'] += ((spacewidth * pac['numspaces']) - one_space_width) / @k
                      end
                      break
                    end
                  }
                end
              end # end of while
              # remove markers
              pmid.gsub!('x*#!#*x', '')
              if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
                # multibyte characters
                spacew = spacewidthu
                pmidtemp = pmid
                # escape special characters
                pmidtemp.gsub!(/[\\][\(]/x, '\\#!#OP#!#')
                pmidtemp.gsub!(/[\\][\)]/x, '\\#!#CP#!#')
                pmidtemp =~ /\[\(([^\)]*)\)\]/x
                matches1 = $1.gsub("#!#OP#!#", "(")
                matches1.gsub!("#!#CP#!#", ")")
                pmid = pmidtemp.sub(/\[\(([^\)]*)\)\]/x,  "[(" + matches1.gsub(0.chr + 32.chr, ") " + sprintf("%.3f", spacew) + " (") + ")]")
                setPageBuffer(startlinepage, pstart + "\n" + pmid + "\n" + pend)
                endlinepos = (pstart + "\n" + pmid + "\n").length
              else
                # non-unicode (single-byte characters)
                rs = sprintf("%.3f Tw", spacewidth)
                pmid.gsub!(/\[\(/x, "#{rs} [(")
                setPageBuffer(startlinepage, pstart + "\n" + pmid + "\nBT 0 Tw ET\n" + pend)
                endlinepos = (pstart + "\n" + pmid + "\nBT 0 Tw ET\n").length
              end
            end
          end # end of J
        end # end if $startlinex
        if (t_x != 0) or (yshift < 0)
          # shift the line
          trx = sprintf('1 0 0 1 %.3f %.3f cm', t_x * @k, yshift * @k)
          setPageBuffer(startlinepage, pstart + "\nq\n" + trx + "\n" + pmid + "\nQ\n" + pend)
          endlinepos = (pstart + "\nq\n" + trx + "\n" + pmid + "\nQ\n").length
          # shift the annotations and links
          if !@page_annots[@page].nil?
            @page_annots[@page].each_with_index { |pac, pak|
              if pak >= pask
                @page_annots[@page][pak]['x'] += t_x
                @page_annots[@page][pak]['y'] -= yshift
              end
            }
          end
          @y -= yshift
        end
      end
      pbrk = checkPageBreak(@lasth)
      @newline = false
      startlinex = @x
      startliney = @y
      if dom[dom[key]['parent']]['value'] == 'sup'
        startliney -= (0.3 * @font_size_pt) / @k
      elsif dom[dom[key]['parent']]['value'] == 'sub'
        startliney -= (@font_size_pt / 0.7) / @k
      else
        minstartliney = startliney
        maxbottomliney = startliney + @font_size * @cell_height_ratio
      end
      if startlinepage == @page and !endlinepos.nil? and !pbrk # fix startlinepos at page break case.
        startlinepos = endlinepos
      else
        startlinepage = @page
        if !@in_footer
          if !@footerlen[@page].nil?
            @footerpos[@page] = @pagelen[@page] - @footerlen[@page]
          else
            @footerpos[@page] = @pagelen[@page]
          end
          startlinepos = @footerpos[@page]
        else
          startlinepos = @pagelen[@page]
        end
      end
      endlinepos = nil
      plalign = lalign
      if !@page_annots[@page].nil?
        pask = @page_annots[@page].length
      else
        pask = 0
      end
      SetFont(fontname, fontstyle, fontsize)
      if wfill  == 1
        SetFillColorArray(@bgcolor)
      end
    end # end newline
    if !opentagpos.nil?
      opentagpos = nil
    end
    if dom[key]['tag']
      if dom[key]['opening']    
        # get text indentation (if any)
        if dom[key]['text-indent'] and dom[key]['block']
          @textindent = dom[key]['text-indent']
          @newline = true
        end
        if dom[key]['value'] == 'table'
          # available page width
          if @rtl
            wtmp = @x - @l_margin
          else
            wtmp = @w - @r_margin - @x
          end
          if (@nested_table == true) or (dom[key]['attribute']['nested'] and (dom[key]['attribute']['nested'] == 'true'))
            # add margin for nested tables
            wtmp -= @c_margin
          end
          # table width
          if !dom[key]['width'].nil?
            table_width = getHTMLUnitToUnits(dom[key]['width'], wtmp, 'px')
          else
            table_width = wtmp
          end
        end
        if (dom[key]['value'] == 'td') or (dom[key]['value'] == 'th')
          trid = dom[key]['parent']
          table_el = dom[trid]['parent']
          if dom[table_el]['cols'].nil?
            dom[table_el]['cols'] = dom[trid]['cols']
          end
          oldmargin = @c_margin
          if !dom[(dom[trid]['parent'])]['attribute']['cellpadding'].nil?
            currentcmargin = getHTMLUnitToUnits(dom[(dom[trid]['parent'])]['attribute']['cellpadding'], 1, 'px')
          else
            currentcmargin = 0
          end
          @c_margin = currentcmargin
          if !dom[(dom[trid]['parent'])]['attribute']['cellspacing'].nil?
            cellspacing = getHTMLUnitToUnits(dom[(dom[trid]['parent'])]['attribute']['cellspacing'], 1, 'px')
          else
            cellspacing = 0
          end
          if @rtl
            cellspacingx = -cellspacing
          else
            cellspacingx = cellspacing
          end
          colspan = dom[key]['attribute']['colspan']
          table_columns_width = table_width - (cellspacing * (dom[table_el]['cols'] - 1))
          wtmp = colspan * (table_columns_width / dom[table_el]['cols']) + (colspan - 1) * cellspacing
          if !dom[key]['width'].nil?
            cellw = getHTMLUnitToUnits(dom[key]['width'], table_columns_width, 'px')
          else
            cellw = wtmp
          end
          if !dom[key]['height'].nil?
            # minimum cell height
            cellh = getHTMLUnitToUnits(dom[key]['height'], 0, 'px')
          else
            cellh = 0
          end
          if !dom[key]['content'].nil?
            cell_content = dom[key]['content']
          else
            cell_content = '&nbsp;'
          end
          tagtype = dom[key]['value']
          parentid = key
          while (key < maxel) and !(dom[key]['tag'] and !dom[key]['opening'] and (dom[key]['value'] == tagtype) and (dom[key]['parent'] == parentid))
            # move :key index forward
            key += 1
          end
          if dom[trid]['startpage'].nil?
            dom[trid]['startpage'] = @page
          else
             setPage(dom[trid]['startpage'])
          end
          if dom[trid]['starty'].nil?
            dom[trid]['starty'] = @y
          else
            @y = dom[trid]['starty']
          end
          if dom[trid]['startx'].nil?
            dom[trid]['startx'] = @x
          else
            @x += (cellspacingx / 2)
          end
          if !dom[parentid]['attribute']['rowspan'].nil?
            rowspan = dom[parentid]['attribute']['rowspan'].to_i
          else
            rowspan = 1
          end
          # skip row-spanned cells started on the previous rows
          if !dom[table_el]['rowspans'].nil?
            rsk = 0
            rskmax = dom[table_el]['rowspans'].length
            while rsk < rskmax
              trwsp = dom[table_el]['rowspans'][rsk]
              rsstartx = trwsp['startx']
              rsendx = trwsp['endx']
              # account for margin changes
              if trwsp['startpage'] < @page
                if @rtl and (@pagedim[@page]['orm'] != @pagedim[trwsp['startpage']]['orm'])
                  dl = @pagedim[@page]['orm'] - @pagedim[trwsp['startpage']]['orm']
                  rsstartx -= dl
                  rsendx -= dl
                elsif !@rtl and (@pagedim[@page]['olm'] != @pagedim[trwsp['startpage']]['olm'])
                  dl = @pagedim[@page]['olm'] - @pagedim[trwsp['startpage']]['olm']
                  rsstartx += dl
                  rsendx += dl
                end
              end
              if  (trwsp['rowspan'] > 0) and (rsstartx > @x - cellspacing - currentcmargin - @feps) and (rsstartx < @x + cellspacing + currentcmargin + @feps) and ((trwsp['starty'] < @y - @feps) or (trwsp['startpage'] < @page))
                # set the starting X position of the current cell
                @x = rsendx + cellspacingx
                if (trwsp['rowspan'] == 1) and !dom[trid]['endy'].nil? and !dom[trid]['endpage'].nil? and (trwsp['endpage'] == dom[trid]['endpage'])
                  # set ending Y position for row
                  dom[table_el]['rowspans'][rsk]['endy'] = [dom[trid]['endy'], trwsp['endy']].max
                  dom[trid]['endy'] = dom[table_el]['rowspans'][rsk]['endy']
                end
                rsk = 0
              else
                rsk += 1
              end
            end
          end
          # add rowspan information to table element
          if rowspan > 1
            dom[table_el]['rowspans'].push({'trid' => trid, 'rowspan' => rowspan, 'mrowspan' => rowspan, 'colspan' => colspan, 'startpage' => @page, 'startx' => @x, 'starty' => @y})
            trsid = dom[table_el]['rowspans'].size
          end
          dom[trid]['cellpos'].push({'startx' => @x})
          cellid = dom[trid]['cellpos'].size
          if rowspan > 1
            dom[trid]['cellpos'][cellid - 1]['rowspanid'] = trsid - 1
          end
          # push background colors
          if !dom[parentid]['bgcolor'].nil? and (dom[parentid]['bgcolor'].length > 0)
            dom[trid]['cellpos'][cellid - 1]['bgcolor'] = dom[parentid]['bgcolor'].dup
          end
          prevLastH = @lasth
          # ****** write the cell content ******
          MultiCell(cellw, cellh, cell_content, 0, lalign, 0, 2, '', '', true, 0, true)
          @lasth = prevLastH
          @c_margin = oldmargin
          dom[trid]['cellpos'][cellid - 1]['endx'] = @x
          # update the end of row position
          if rowspan <= 1
            if !dom[trid]['endy'].nil?
              if @page == dom[trid]['endpage']
                dom[trid]['endy'] = [@y, dom[trid]['endy']].max
              elsif @page > dom[trid]['endpage']
                dom[trid]['endy'] = @y
              end
            else
              dom[trid]['endy'] = @y
            end
            if !dom[trid]['endpage'].nil?
              dom[trid]['endpage'] = [@page, dom[trid]['endpage']].max
            else
              dom[trid]['endpage'] = @page
            end
          else
            # account for row-spanned cells
            dom[table_el]['rowspans'][trsid - 1]['endx'] = @x
            dom[table_el]['rowspans'][trsid - 1]['endy'] = @y
            dom[table_el]['rowspans'][trsid - 1]['endpage'] = @page                             
          end
          if !dom[table_el]['rowspans'].nil?
            # update endy and endpage on rowspanned cells
            dom[table_el]['rowspans'].each_with_index { |trwsp, k|
              if trwsp['rowspan'] > 0
                if !dom[trid]['endpage'].nil?
                  if trwsp['endpage'] == dom[trid]['endpage']
                    dom[table_el]['rowspans'][k]['endy'] = [dom[trid]['endy'], trwsp['endy']].max
                  elsif trwsp['endpage'] < dom[trid]['endpage']
                    dom[table_el]['rowspans'][k]['endy'] = dom[trid]['endy']
                    dom[table_el]['rowspans'][k]['endpage'] = dom[trid]['endpage']
                  else
                    dom[trid]['endy'] = @pagedim[dom[trid]['endpage']]['hk'] - @pagedim[dom[trid]['endpage']]['bm']
                  end
                end
              end
            }
          end
          @x += (cellspacingx / 2)
        else
          # opening tag (or self-closing tag)
          if opentagpos.nil?
            if !@in_footer
              if !@footerlen[@page].nil?
                @footerpos[@page] = @pagelen[@page] - @footerlen[@page]
              else
                @footerpos[@page] = @pagelen[@page]
              end
              opentagpos = @footerpos[@page]
            end
          end
          dom = openHTMLTagHandler(dom, key, cell)
        end
      else
        # closing tag
        prev_numpages = @numpages
        dom = closeHTMLTagHandler(dom, key, cell, maxbottomliney)
        if prev_numpages > @numpages
          startlinepage = @page
        end
      end
    elsif dom[key]['value'].length > 0
      # print list-item
      if !empty_string(@lispacer)
        SetFont(pfontname, pfontstyle, pfontsize)
        @lasth = @font_size * @cell_height_ratio
        minstartliney = @y
        maxbottomliney = startliney + @font_size * @cell_height_ratio
        putHtmlListBullet(@listnum, @lispacer, pfontsize)
        SetFont(curfontname, curfontstyle, curfontsize)
        @lasth = @font_size * @cell_height_ratio
        if pfontsize.is_a?(Numeric) and (pfontsize > 0) and curfontsize.is_a?(Numeric) and (curfontsize > 0) and (pfontsize != curfontsize)
          pfontascent = getFontAscent(pfontname, pfontstyle, pfontsize)
          pfontdescent = getFontDescent(pfontname, pfontstyle, pfontsize)
          @y += ((pfontsize - curfontsize) * @cell_height_ratio / @k + pfontascent - curfontascent - pfontdescent + curfontdescent) / 2
          minstartliney = [@y, minstartliney].min
          maxbottomliney = [@y + pfontsize * @cell_height_ratio / @k, maxbottomliney].max
        end
      end
      # text
      @htmlvspace = 0
      if !@premode and isRTLTextDir()
        # reverse spaces order
        len1 = dom[key]['value'].length
        lsp = len1 - dom[key]['value'].lstrip.length
        rsp = len1 - dom[key]['value'].rstrip.length
        tmpstr = ''
        if rsp > 0
          tmpstr << dom[key]['value'][-rsp..-1]
        end
        tmpstr << (dom[key]['value']).strip
        if lsp > 0
          tmpstr << dom[key]['value'][0, lsp]
        end
        dom[key]['value'] = tmpstr
      end
      if newline
        if !@premode
          prelen = dom[key]['value'].length
          if isRTLTextDir()
            dom[key]['value'] = dom[key]['value'].rstrip + 0.chr
          else
            dom[key]['value'] = dom[key]['value'].lstrip
          end
          postlen = dom[key]['value'].length
          if (postlen == 0) and (prelen > 0)
            dom[key]['trimmed_space'] = true
          end
        end
        newline = false
        firstblock = true
      else
        firstblock = false
      end
      strrest = ''
      if @rtl
        @x -= @textindent
      else
        @x += @textindent
      end
      if !@href.empty? and @href['url']
        # HTML <a> Link
        hrefcolor = ''
        if dom[(dom[key]['parent'])]['fgcolor'] and !dom[(dom[key]['parent'])]['fgcolor'].empty?
          hrefcolor = dom[(dom[key]['parent'])]['fgcolor']
        end
        hrefstyle = -1
        if dom[(dom[key]['parent'])]['fontstyle'] and (dom[(dom[key]['parent'])]['fontstyle'] != false)
          hrefstyle = dom[(dom[key]['parent'])]['fontstyle']
        end
        strrest = addHtmlLink(@href['url'], dom[key]['value'], wfill, true, hrefcolor, hrefstyle, true)
      else
        # ****** write only until the end of the line and get the rest ******
        strrest = Write(@lasth, dom[key]['value'], '', wfill, '', false, 0, true, firstblock, 0)
      end
      @textindent = 0

      if !strrest.nil? and strrest.length > 0
        # store the remaining string on the previous :key position
        @newline = true
        if cell
          if @rtl
            @x -= @c_margin
          else
            @x += @c_margin
          end
        end
        if strrest == dom[key]['value']
          # used to avoid infinite loop
          loop += 1
        else
          loop = 0
        end
        if !@href.empty? and @href['url']
          dom[key]['value'] = strrest.strip
        elsif @premode
          dom[key]['value'] = strrest
        elsif isRTLTextDir()
          dom[key]['value'] = strrest.rstrip
        else
          dom[key]['value'] = strrest.lstrip
        end
        if loop < 3
          key -= 1
        end
      else
        loop = 0
      end
    end
    key += 1
    if dom[key] and dom[key]['tag'] and (dom[key]['opening'].nil? or !dom[key]['opening']) and dom[(dom[key]['parent'])]['attribute']['nobr'] and (dom[(dom[key]['parent'])]['attribute']['nobr'] == 'true')
      if !undo and (@start_transaction_page == (@numpages - 1)) or (@y < @start_transaction_y)
        # restore previous object
        rollbackTransaction(true)
        # restore previous values
        this_method_vars.each {|vkey , vval|
          eval("#{vkey} = vval") 
        }
        # add a page (or trig AcceptPageBreak() for multicolumn mode)
        pre_y = @y
        if !checkPageBreak(@page_break_trigger + 1) and (@y < pre_y)
          startliney = @y
        end
        undo = true # avoid infinite loop
      else
        undo = false
      end
    end
  end # end for each :key
  # align the last line
  if !startlinex.nil?
    yshift = minstartliney - startliney
    if (yshift > 0) or (@page > startlinepage)
      yshift = 0
    end
    t_x = 0
    # the last line must be shifted to be aligned as requested
    linew = (@endlinex - startlinex).abs
    pstart = getPageBuffer(startlinepage)[0, startlinepos]
    if !opentagpos.nil? and !@footerlen[startlinepage].nil? and !@in_footer
      @footerpos[startlinepage] = @pagelen[startlinepage] - @footerlen[startlinepage]
      midpos = [opentagpos, @footerpos[startlinepage]].min
    elsif !opentagpos.nil?
      midpos = opentagpos
    elsif !@footerlen[startlinepage].nil? and !@in_footer
      @footerpos[startlinepage] = @pagelen[startlinepage] - @footerlen[startlinepage]
      midpos = @footerpos[startlinepage]
    else
      midpos = 0
    end
    if midpos > 0
      pmid = getPageBuffer(startlinepage)[startlinepos, midpos - startlinepos]
      pend = getPageBuffer(startlinepage)[midpos..-1]
    else
      pmid = getPageBuffer(startlinepage)[startlinepos..-1]
      pend = ""
    end
    if (!plalign.nil? and (((plalign == 'C') or ((plalign == 'R') and !@rtl) or ((plalign == 'L') and @rtl)))) or (yshift < 0)
      # calculate shifting amount
      tw = w
      if @l_margin != prevlMargin
        tw += prevlMargin - @l_margin
      end
      if @r_margin != prevrMargin
        tw += prevrMargin - @r_margin
      end
      one_space_width = GetStringWidth(32.chr)
      mdiff = (tw - linew).abs
      if plalign == 'C'
        if @rtl
          t_x = -(mdiff / 2)
        else
          t_x = (mdiff / 2)
        end
      elsif (plalign == 'R') and !@rtl
        # right alignment on LTR document
        if revstrpos(pmid, ')]').to_i == revstrpos(pmid, ' )]').to_i + 1
          # remove last space (if any)
          linew -= one_space_width
          mdiff = (tw - linew).abs
        end
        t_x = mdiff
      elsif (plalign == 'L') and @rtl
        # left alignment on RTL document
        if revstrpos(pmid, '[(') and ((revstrpos(pmid, '[( ').to_i == revstrpos(pmid, '[(').to_i) or (revstrpos(pmid, '[(' + 0.chr + 32.chr).to_i == revstrpos(pmid, '[(').to_i))
          # remove first space (if any)
          linew -= one_space_width
        end
        if pmid.index('[(') and (pmid.index('[(').to_i == revstrpos(pmid, '[(').to_i)
          # remove last space (if any)
          linew -= one_space_width
          if (@current_font['type'] == 'TrueTypeUnicode') or (@current_font['type'] == 'cidfont0')
            linew -= one_space_width
          end
        end
        mdiff = (tw - linew).abs
        t_x = -mdiff
      end
    end # end if startlinex
    if (t_x != 0) or (yshift < 0)
      # shift the line
      trx = sprintf('1 0 0 1 %.3f %.3f cm', t_x * @k, yshift * @k)
      setPageBuffer(startlinepage, pstart + "\nq\n" + trx + "\n" + pmid + "\nQ\n" + pend)
      endlinepos = (pstart + "\nq\n" + trx + "\n" + pmid + "\nQ\n").length

      # shift the annotations and links
      if !@page_annots[@page].nil?
        @page_annots[@page].each_with_index { |pac, pak|
          if pak >= pask
            @page_annots[@page][pak]['x'] += t_x
            @page_annots[@page][pak]['y'] -= yshift
          end
        }
      end
      @y -= yshift
    end
  end
  if ln and !(cell and (dom[key-1]['value'] == 'table'))
    Ln(@lasth)
    if @y < maxbottomliney
      @y = maxbottomliney
    end
  end
  # restore previous values
  setGraphicVars(gvars)
  if @page > prevPage
    @l_margin = @pagedim[@page]['olm']
    @r_margin = @pagedim[@page]['orm']
  end
  # restore previous list state
  @cell_height_ratio = prev_cell_height_ratio
  @listnum = prev_listnum
  @listordered = prev_listordered
  @listcount = prev_listcount
  @lispacer = prev_lispacer
  dom = nil
end

#writeHTMLCell(w, h, x, y, html = '', border = 0, ln = 0, fill = 0, reseth = true, align = '', autopadding = true) ⇒ Object Also known as: write_html_cell

Prints a cell (rectangular area) with optional borders, background color and html text string. The upper-left corner of the cell corresponds to the current position. After the call, the current position moves to the right or to the next line. If automatic page breaking is enabled and the cell goes beyond the limit, a page break is done before outputting.

@param float :w

Cell width. If 0, the cell extends up to the right margin.

@param float :h

Cell minimum height. The cell extends automatically if needed.

@param float :x

upper-left corner X coordinate

@param float :y

upper-left corner Y coordinate

@param string :html

html text to print. Default value: empty string.

@param mixed :border

Indicates if borders must be drawn around the cell. The value can be either a number:

  • 0: no border (default)

  • 1: frame

or a string containing some or all of the following characters (in any order):

  • L: left

  • T: top

  • R: right

  • B: bottom

@param int :ln

Indicates where the current position should go after the call. Possible values are:

  • 0: to the right (or left for RTL language)

  • 1: to the beginning of the next line

  • 2: below

Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: 0.

@param int :fill

Indicates if the cell background must be painted (1) or transparent (0). Default value: 0.

@param boolean :reseth

if true reset the last cell height (default true).

@param string :align

Allows to center or align the text. Possible values are:

  • L : left align

  • C : center

  • R : right align

  • ” : empty string : left for LTR or right for RTL

@param boolean :autopadding

if true, uses internal padding and automatically adjust it to account for line width.

@access public
@uses

MultiCell()

@see

Multicell(), writeHTML(), Cell()



11237
11238
11239
11240
11241
11242
# File 'lib/rbpdf.rb', line 11237

def writeHTMLCell(w, h, x, y, html='', border=0, ln=0, fill=0, reseth=true, align='', autopadding=true)
  @nested_table = true
  rtn = MultiCell(w, h, html, border, align, fill, ln, x, y, reseth, 0, true, autopadding, 0)
  @nested_table = false
  return rtn
end