Method: CombinePDF::Page_Methods#textbox
- Defined in:
- lib/combine_pdf/page_methods.rb
#textbox(text, properties = {}) ⇒ Object
This method adds a simple text box to the Page represented by the PDFWriter class. This function takes two values:
- text
-
the text to write in the box.
- properties
-
a Hash of box properties.
the symbols and values in the properties Hash could be any or all of the following:
- x
-
the left position of the box.
- y
-
the BOTTOM position of the box.
- width
-
the width/length of the box. negative values will be computed from edge of page. defaults to 0 (end of page).
- height
-
the height of the box. negative values will be computed from edge of page. defaults to 0 (end of page).
- text_align
-
symbol for horizontal text alignment, can be “:center” (default), “:right”, “:left”
- text_valign
-
symbol for vertical text alignment, can be “:center” (default), “:top”, “:bottom”
- text_padding
-
a Float between 0 and 1, setting the padding for the text. defaults to 0.05 (5%).
- font
-
a registered font name or an Array of names. defaults to “:Helvetica”. The 14 standard fonts names are:
-
:“Times-Roman”
-
:“Times-Bold”
-
:“Times-Italic”
-
:“Times-BoldItalic”
-
:Helvetica
-
:“Helvetica-Bold”
-
:“Helvetica-BoldOblique”
-
:“Helvetica- Oblique”
-
:Courier
-
:“Courier-Bold”
-
:“Courier-Oblique”
-
:“Courier-BoldOblique”
-
:Symbol
-
:ZapfDingbats
- font_size
-
an Integer for the font size, or :fit_text to fit the text in the box. defaults to “:fit_text”
- max_font_size
-
if font_size is set to :fit_text, this will be the maximum font size. defaults to nil (no maximum)
- font_color
-
text color in [R, G, B], an array with three floats, each in a value between 0 to 1 (gray will be “[0.5, 0.5, 0.5]”). defaults to black.
- stroke_color
-
text stroke color in [R, G, B], an array with three floats, each in a value between 0 to 1 (gray will be “[0.5, 0.5, 0.5]”). defounlts to nil (no stroke).
- stroke_width
-
text stroke width in PDF units. defaults to 0 (none).
- box_color
-
box fill color in [R, G, B], an array with three floats, each in a value between 0 to 1 (gray will be “[0.5, 0.5, 0.5]”). defaults to nil (none).
- border_color
-
box border color in [R, G, B], an array with three floats, each in a value between 0 to 1 (gray will be “[0.5, 0.5, 0.5]”). defaults to nil (none).
- border_width
-
border width in PDF units. defaults to nil (none).
- box_radius
-
border radius in PDF units. defaults to 0 (no corner rounding).
- opacity
-
textbox opacity, a float between 0 (transparent) and 1 (opaque)
- ctm
-
A PDF complient CTM data array that will manipulate the axis and allow transformations. i.e. ‘[1,0,0,1,0,0]`
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 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 |
# File 'lib/combine_pdf/page_methods.rb', line 186 def textbox(text, properties = {}) = { x: page_size[0], y: page_size[1], width: 0, height: -1, text_align: :center, text_valign: :center, text_padding: 0.1, font: nil, font_size: :fit_text, max_font_size: nil, font_color: [0, 0, 0], stroke_color: nil, stroke_width: 0, box_color: nil, border_color: nil, border_width: 0, box_radius: 0, opacity: 1, ctm: nil # ~= [1,0,0,1,0,0] } .update properties # reset the length and height to meaningful values, if negative [:width] = mediabox[2] - [:x] + [:width] if [:width] <= 0 [:height] = mediabox[3] - [:y] + [:height] if [:height] <= 0 # reset the padding value [:text_padding] = 0 if [:text_padding].to_f >= 1 # create box stream box_stream = '' # set graphic state for box if [:box_color] || ([:border_width].to_i > 0 && [:border_color]) # compute x and y position for text x = [:x] y = [:y] # set graphic state for the box box_stream << "q\n" box_stream << "#{[:ctm].join ' '} cm\n" if [:ctm] box_graphic_state = { ca: [:opacity], CA: [:opacity], LW: [:border_width], LC: 0, LJ: 0, LD: 0 } if [:box_radius] != 0 # if the text box has rounded corners box_graphic_state[:LC] = 2 box_graphic_state[:LJ] = 1 end box_graphic_state = graphic_state box_graphic_state # adds the graphic state to Resources and gets the reference box_stream << "#{object_to_pdf box_graphic_state} gs\n" # the following line was removed for Acrobat Reader compatability # box_stream << "DeviceRGB CS\nDeviceRGB cs\n" box_stream << "#{[:box_color].join(' ')} rg\n" if [:box_color] if [:border_width].to_i > 0 && [:border_color] box_stream << "#{[:border_color].join(' ')} RG\n" end # create the path radius = [:box_radius] half_radius = (radius.to_f / 2).round 4 ## set starting point box_stream << "#{[:x] + radius} #{[:y]} m\n" ## bottom and right corner - first line and first corner box_stream << "#{[:x] + [:width] - radius} #{[:y]} l\n" # bottom if [:box_radius] != 0 # make first corner, if not straight. box_stream << "#{[:x] + [:width] - half_radius} #{[:y]} " box_stream << "#{[:x] + [:width]} #{[:y] + half_radius} " box_stream << "#{[:x] + [:width]} #{[:y] + radius} c\n" end ## right and top-right corner box_stream << "#{[:x] + [:width]} #{[:y] + [:height] - radius} l\n" if [:box_radius] != 0 box_stream << "#{[:x] + [:width]} #{[:y] + [:height] - half_radius} " box_stream << "#{[:x] + [:width] - half_radius} #{[:y] + [:height]} " box_stream << "#{[:x] + [:width] - radius} #{[:y] + [:height]} c\n" end ## top and top-left corner box_stream << "#{[:x] + radius} #{[:y] + [:height]} l\n" if [:box_radius] != 0 box_stream << "#{[:x] + half_radius} #{[:y] + [:height]} " box_stream << "#{[:x]} #{[:y] + [:height] - half_radius} " box_stream << "#{[:x]} #{[:y] + [:height] - radius} c\n" end ## left and bottom-left corner box_stream << "#{[:x]} #{[:y] + radius} l\n" if [:box_radius] != 0 box_stream << "#{[:x]} #{[:y] + half_radius} " box_stream << "#{[:x] + half_radius} #{[:y]} " box_stream << "#{[:x] + radius} #{[:y]} c\n" end # fill / stroke path box_stream << "h\n" if [:box_color] && [:border_width].to_i > 0 && [:border_color] box_stream << "B\n" elsif [:box_color] # fill if fill color is set box_stream << "f\n" elsif [:border_width].to_i > 0 && [:border_color] # stroke if border is set box_stream << "S\n" end # exit graphic state for the box box_stream << "Q\n" end contents << box_stream # reset x,y by text alignment - x,y are calculated from the bottom left # each unit (1) is 1/72 Inch # create text stream text_stream = '' if !text.to_s.empty? && [:font_size] != 0 && ([:font_color] || [:stroke_color]) # compute x and y position for text x = [:x] + ([:width] * [:text_padding]) y = [:y] + ([:height] * [:text_padding]) # set the fonts (fonts array, with :Helvetica as fallback). fonts = [*[:font], :Helvetica] # fit text in box, if requested font_size = [:font_size] if [:font_size] == :fit_text font_size = fit_text text, fonts, ([:width] * (1 - [:text_padding])), ([:height] * (1 - [:text_padding])) font_size = [:max_font_size] if [:max_font_size] && font_size > [:max_font_size] end text_size = dimensions_of text, fonts, font_size if [:text_align] == :center x = (([:width] * (1 - (2 * [:text_padding]))) - text_size[0]) / 2 + x elsif [:text_align] == :right x = (([:width] * (1 - (1.5 * [:text_padding]))) - text_size[0]) + x end if [:text_valign] == :center y = (([:height] * (1 - (2 * [:text_padding]))) - text_size[1]) / 2 + y elsif [:text_valign] == :top y = ([:height] * (1 - (1.5 * [:text_padding]))) - text_size[1] + y end # set graphic state for text text_stream << "q\n" text_stream << "#{[:ctm].join ' '} cm\n" if [:ctm] text_graphic_state = graphic_state(ca: [:opacity], CA: [:opacity], LW: [:stroke_width].to_f, LC: 2, LJ: 1, LD: 0) text_stream << "#{object_to_pdf text_graphic_state} gs\n" # the following line was removed for Acrobat Reader compatability # text_stream << "DeviceRGB CS\nDeviceRGB cs\n" # set text render mode if [:font_color] text_stream << "#{[:font_color].join(' ')} rg\n" end if [:stroke_width].to_i > 0 && [:stroke_color] text_stream << "#{[:stroke_color].join(' ')} RG\n" if [:font_color] text_stream << "2 Tr\n" else final_stream << "1 Tr\n" end elsif [:font_color] text_stream << "0 Tr\n" else text_stream << "3 Tr\n" end # format text object(s) # text_stream << "#{options[:font_color].join(' ')} rg\n" # sets the color state encode_text(text, fonts).each do |encoded| text_stream << "BT\n" # the Begine Text marker text_stream << format_name_to_pdf(set_font(encoded[0])) # Set font name text_stream << " #{font_size.round 3} Tf\n" # set font size and add font operator text_stream << "#{x.round 4} #{y.round 4} Td\n" # set location for text object text_stream << (encoded[1]) # insert the encoded string to the stream text_stream << " Tj\n" # the Text object operator and the End Text marker text_stream << "ET\n" # the Text object operator and the End Text marker x += encoded[2] / 1000 * font_size # update text starting point y -= encoded[3] / 1000 * font_size # update text starting point end # exit graphic state for text text_stream << "Q\n" end contents << text_stream self end |