Object
Generally, one would use the Prawn::Text::Formatted#formatted_text_box convenience method. However, using Text::Formatted::Box.new in conjunction with #(:dry_run => true) enables one to do look-ahead calculations prior to placing text on the page, or to determine how much vertical space was consumed by the printed text
Example (see Prawn::Text::Core::Formatted::Wrap for what is required of the wrap method if you want to override the default wrapping algorithm):
module MyWrap
def wrap(array)
initialize_wrap([{ :text => 'all your base are belong to us' }])
@line_wrap.wrap_line(:document => @document,
:kerning => @kerning,
:width => 10000,
:arranger => @arranger)
fragment = @arranger.retrieve_fragment
format_and_draw_fragment(fragment, 0, @line_wrap.width, 0)
[]
end
end
Prawn::Text::Formatted::Box.extensions << MyWrap
box = Prawn::Text::Formatted::Box.new('hello world')
box.render('why can't I print anything other than' +
'"all your base are belong to us"?')
# File lib/prawn/text/formatted/box.rb, line 166
166: def self.extensions
167: @extensions ||= []
168: end
See Prawn::Text#text_box for valid options
# File lib/prawn/text/formatted/box.rb, line 176
176: def initialize(formatted_text, options={})
177: @inked = false
178: Prawn.verify_options(valid_options, options)
179: options = options.dup
180:
181: self.class.extensions.reverse_each { |e| extend e }
182:
183: @overflow = options[:overflow] || :truncate
184:
185: self.original_text = formatted_text
186: @text = nil
187:
188: @document = options[:document]
189: @direction = options[:direction] || @document.text_direction
190: @fallback_fonts = options[:fallback_fonts] ||
191: @document.fallback_fonts
192: @at = (options[:at] ||
193: [@document.bounds.left, @document.bounds.top]).dup
194: @width = options[:width] ||
195: @document.bounds.right - @at[0]
196: @height = options[:height] || default_height
197: @align = options[:align] ||
198: (@direction == :rtl ? :right : :left)
199: @vertical_align = options[:valign] || :top
200: @leading = options[:leading] || @document.default_leading
201: @character_spacing = options[:character_spacing] ||
202: @document.character_spacing
203: @mode = options[:mode] || @document.text_rendering_mode
204: @rotate = options[:rotate] || 0
205: @rotate_around = options[:rotate_around] || :upper_left
206: @single_line = options[:single_line]
207: @skip_encoding = options[:skip_encoding] || @document.skip_encoding
208:
209: if @overflow == :expand
210: # if set to expand, then we simply set the bottom
211: # as the bottom of the document bounds, since that
212: # is the maximum we should expand to
213: @height = default_height
214: @overflow = :truncate
215: end
216: @min_font_size = options[:min_font_size] || 5
217: if options[:kerning].nil? then
218: options[:kerning] = @document.default_kerning?
219: end
220: @options = { :kerning => options[:kerning],
221: :size => options[:size],
222: :style => options[:style] }
223:
224: super(formatted_text, options)
225: end
The width available at this point in the box
# File lib/prawn/text/formatted/box.rb, line 271
271: def available_width
272: @width
273: end
True iff everything printed (or, if dry_run was used, everything would have been successfully printed)
# File lib/prawn/text/formatted/box.rb, line 119
119: def everything_printed?
120: @everything_printed
121: end
The height actually used during the previous render
# File lib/prawn/text/formatted/box.rb, line 277
277: def height
278: return 0 if @baseline_y.nil? || @descender.nil?
279: (@baseline_y - @descender).abs
280: end
# File lib/prawn/text/formatted/box.rb, line 134
134: def line_gap
135: line_height - (ascender + descender)
136: end
True iff nothing printed (or, if dry_run was used, nothing would have been successfully printed)
# File lib/prawn/text/formatted/box.rb, line 113
113: def nothing_printed?
114: @nothing_printed
115: end
Render text to the document based on the settings defined in initialize.
In order to facilitate look-ahead calculations, render accepts a :dry_run => true option. If provided, then everything is executed as if rendering, with the exception that nothing is drawn on the page. Useful for look-ahead computations of height, unprinted text, etc.
Returns any text that did not print under the current settings
# File lib/prawn/text/formatted/box.rb, line 237
237: def render(flags={})
238: unprinted_text = []
239:
240: @document.save_font do
241: @document.character_spacing(@character_spacing) do
242: @document.text_rendering_mode(@mode) do
243: process_options
244:
245: if @skip_encoding
246: text = original_text
247: else
248: text = normalize_encoding
249: end
250:
251: @document.font_size(@font_size) do
252: shrink_to_fit(text) if @overflow == :shrink_to_fit
253: process_vertical_alignment(text)
254: @inked = true unless flags[:dry_run]
255: if @rotate != 0 && @inked
256: unprinted_text = render_rotated(text)
257: else
258: unprinted_text = wrap(text)
259: end
260: @inked = false
261: end
262: end
263: end
264: end
265:
266: unprinted_text
267: end
# File lib/prawn/text/formatted/box.rb, line 94
94: def valid_options
95: Prawn::Core::Text::VALID_OPTIONS + [:at, :height, :width,
96: :align, :valign,
97: :rotate, :rotate_around,
98: :overflow, :min_font_size,
99: :leading, :character_spacing,
100: :mode, :single_line,
101: :skip_encoding,
102: :document,
103: :direction,
104: :fallback_fonts]
105: end
# File lib/prawn/text/formatted/box.rb, line 362
362: def analyze_glyphs_for_fallback_font_support(hash)
363: font_glyph_pairs = []
364:
365: original_font = @document.font.family
366: fragment_font = hash[:font] || original_font
367: @document.font(fragment_font)
368:
369: fallback_fonts = @fallback_fonts.dup
370: # always default back to the current font if the glyph is missing from
371: # all fonts
372: fallback_fonts << fragment_font
373:
374: hash[:text].unpack("U*").each do |char_int|
375: char = [char_int].pack("U")
376: @document.font(fragment_font)
377: font_glyph_pairs << [find_font_for_this_glyph(char,
378: @document.font.family,
379: fallback_fonts.dup),
380: char]
381: end
382:
383: @document.font(original_font)
384:
385: form_fragments_from_like_font_glyph_pairs(font_glyph_pairs, hash)
386: end
Returns the default height to be used if none is provided or if the overflow option is set to :expand. If we are in a stretchy bounding box, assume we can stretch to the bottom of the innermost non-stretchy box.
# File lib/prawn/text/formatted/box.rb, line 431
431: def default_height
432: # Find the "frame", the innermost non-stretchy bbox.
433: frame = @document.bounds
434: frame = frame.parent while frame.stretchy? && frame.parent
435:
436: @at[1] + @document.bounds.absolute_bottom - frame.absolute_bottom
437: end
# File lib/prawn/text/formatted/box.rb, line 523
523: def draw_fragment_overlay_anchor(fragment)
524: return unless fragment.anchor
525: box = fragment.absolute_bounding_box
526: @document.link_annotation(box,
527: :Border => [0, 0, 0],
528: :Dest => fragment.anchor)
529: end
# File lib/prawn/text/formatted/box.rb, line 513
513: def draw_fragment_overlay_link(fragment)
514: return unless fragment.link
515: box = fragment.absolute_bounding_box
516: @document.link_annotation(box,
517: :Border => [0, 0, 0],
518: :A => { :Type => :Action,
519: :S => :URI,
520: :URI => Prawn::Core::LiteralString.new(fragment.link) })
521: end
# File lib/prawn/text/formatted/box.rb, line 531
531: def draw_fragment_overlay_styles(fragment)
532: underline = fragment.styles.include?(:underline)
533: if underline
534: @document.stroke_line(fragment.underline_points)
535: end
536:
537: strikethrough = fragment.styles.include?(:strikethrough)
538: if strikethrough
539: @document.stroke_line(fragment.strikethrough_points)
540: end
541: end
# File lib/prawn/text/formatted/box.rb, line 504
504: def draw_fragment_overlays(fragment)
505: draw_fragment_overlay_styles(fragment)
506: draw_fragment_overlay_link(fragment)
507: draw_fragment_overlay_anchor(fragment)
508: fragment.callback_objects.each do |obj|
509: obj.render_in_front(fragment) if obj.respond_to?(:render_in_front)
510: end
511: end
# File lib/prawn/text/formatted/box.rb, line 498
498: def draw_fragment_underlays(fragment)
499: fragment.callback_objects.each do |obj|
500: obj.render_behind(fragment) if obj.respond_to?(:render_behind)
501: end
502: end
# File lib/prawn/text/formatted/box.rb, line 388
388: def find_font_for_this_glyph(char, current_font, fallback_fonts)
389: if fallback_fonts.length == 0 || @document.font.glyph_present?(char)
390: current_font
391: else
392: current_font = fallback_fonts.shift
393: @document.font(current_font)
394: find_font_for_this_glyph(char, @document.font.family, fallback_fonts)
395: end
396: end
# File lib/prawn/text/formatted/box.rb, line 398
398: def form_fragments_from_like_font_glyph_pairs(font_glyph_pairs, hash)
399: fragments = []
400: fragment = nil
401: current_font = nil
402:
403: font_glyph_pairs.each do |font, char|
404: if font != current_font
405: current_font = font
406: fragment = hash.dup
407: fragment[:text] = char
408: fragment[:font] = font
409: fragments << fragment
410: else
411: fragment[:text] += char
412: end
413: end
414:
415: fragments
416: end
# File lib/prawn/text/formatted/box.rb, line 418
418: def move_baseline_down
419: if @baseline_y == 0
420: @baseline_y = -@ascender
421: else
422: @baseline_y -= (@line_height + @leading)
423: end
424: end
# File lib/prawn/text/formatted/box.rb, line 331
331: def normalize_encoding
332: formatted_text = original_text
333:
334: unless @fallback_fonts.empty?
335: formatted_text = process_fallback_fonts(formatted_text)
336: end
337:
338: formatted_text.each do |hash|
339: if hash[:font]
340: @document.font(hash[:font]) do
341: hash[:text] = @document.font.normalize_encoding(hash[:text])
342: end
343: else
344: hash[:text] = @document.font.normalize_encoding(hash[:text])
345: end
346: end
347:
348: formatted_text
349: end
# File lib/prawn/text/formatted/box.rb, line 323
323: def original_text
324: @original_array.collect { |hash| hash.dup }
325: end
# File lib/prawn/text/formatted/box.rb, line 327
327: def original_text=(formatted_text)
328: @original_array = formatted_text
329: end
# File lib/prawn/text/formatted/box.rb, line 351
351: def process_fallback_fonts(formatted_text)
352: modified_formatted_text = []
353:
354: formatted_text.each do |hash|
355: fragments = analyze_glyphs_for_fallback_font_support(hash)
356: modified_formatted_text.concat(fragments)
357: end
358:
359: modified_formatted_text
360: end
# File lib/prawn/text/formatted/box.rb, line 463
463: def process_options
464: # must be performed within a save_font bock because
465: # document.process_text_options sets the font
466: @document.process_text_options(@options)
467: @font_size = @options[:size]
468: @kerning = @options[:kerning]
469: end
# File lib/prawn/text/formatted/box.rb, line 439
439: def process_vertical_alignment(text)
440: return if @vertical_align == :top
441: wrap(text)
442:
443: case @vertical_align
444: when :center
445: @at[1] = @at[1] - (@height - height) * 0.5
446: when :bottom
447: @at[1] = @at[1] - (@height - height)
448: end
449: @height = height
450: end
# File lib/prawn/text/formatted/box.rb, line 471
471: def render_rotated(text)
472: unprinted_text = ''
473:
474: case @rotate_around
475: when :center
476: x = @at[0] + @width * 0.5
477: y = @at[1] - @height * 0.5
478: when :upper_right
479: x = @at[0] + @width
480: y = @at[1]
481: when :lower_right
482: x = @at[0] + @width
483: y = @at[1] - @height
484: when :lower_left
485: x = @at[0]
486: y = @at[1] - @height
487: else
488: x = @at[0]
489: y = @at[1]
490: end
491:
492: @document.rotate(@rotate, :origin => [x, y]) do
493: unprinted_text = wrap(text)
494: end
495: unprinted_text
496: end
Decrease the font size until the text fits or the min font size is reached
# File lib/prawn/text/formatted/box.rb, line 454
454: def shrink_to_fit(text)
455: wrap(text)
456: until @everything_printed || @font_size <= @min_font_size
457: @font_size = [@font_size - 0.5, @min_font_size].max
458: @document.font_size = @font_size
459: wrap(text)
460: end
461: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.