class Object
Public Class Methods
# File lib/asciidoctor/pdf/ext/prawn-gmagick.rb, line 9 def initialize image_blob super # apply patch for https://github.com/packetmonkey/prawn-gmagick/issues/19 if bits != 8 && (GMagick::Image.format image_blob) == 'PNG' (io = StringIO.new image_blob).read 8 chunk_size = io.read 4 self.bits = ((io.read chunk_size.unpack1 'N').unpack 'NNC')[-1] if (io.read 4) == 'IHDR' end end
Public Instance Methods
NOTE: see github.com/jruby/jruby/issues/7750
# File lib/asciidoctor/pdf/ext/core/file.rb, line 5 def absolute_path path, dir = nil return super unless dir && !(absolute_path? path) super File.join dir, path end
NOTE: JRuby < 9.4 doesn’t implement this method; JRuby 9.4 implements it incorrectly
# File lib/asciidoctor/pdf/ext/core/file.rb, line 11 def absolute_path? path (Pathname.new path).absolute? && !(%r/\A[[:alpha:]][[:alnum:]\-+]*:\/\/\S/.match? path) end
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/line_wrap.rb, line 4 def add_fragment_to_line fragment case fragment when '' true when ?\n @newline_encountered = true false else if (joined_string = @arranger.preview_joined_string) joined_string_width = @document.width_of (tokenize joined_string)[0], kerning: @kerning else joined_string_width = 0 end last_idx = (segments = tokenize fragment).length - 1 segments.each_with_index do |segment, idx| if segment == (zero_width_space segment.encoding) segment_width = effective_segment_width = 0 else segment_width = effective_segment_width = @document.width_of segment, kerning: @kerning effective_segment_width += joined_string_width if idx === last_idx end if @accumulated_width + effective_segment_width <= @width @accumulated_width += segment_width if segment[-1] == (shy = soft_hyphen segment.encoding) @accumulated_width -= (@document.width_of shy, kerning: @kerning) end @fragment_output += segment else @line_contains_more_than_one_word = false if @accumulated_width == 0 && @line_contains_more_than_one_word end_of_the_line_reached segment fragment_finished fragment return false end end fragment_finished fragment true end end
help Prawn
correctly resolve which font to analyze, including the font style also instruct Prawn
to ignore fragment for inline image since the text is just a placeholder
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb, line 37 def analyze_glyphs_for_fallback_font_support fragment_hash return [fragment_hash] if fragment_hash[:image_obj] fragment_font = fragment_hash[:font] || (original_font = @document.font.family) effective_font_styles = @document.font_styles fragment_font_opts = {} if (fragment_font_styles = fragment_hash[:styles]) effective_font_styles.merge fragment_font_styles if effective_font_styles.include? :bold fragment_font_opts[:style] = (effective_font_styles.include? :italic) ? :bold_italic : :bold elsif effective_font_styles.include? :italic fragment_font_opts[:style] = :italic end elsif !effective_font_styles.empty? fragment_font_opts[:style] = @document.resolve_font_style effective_font_styles end fallback_fonts = @fallback_fonts.drop 0 font_glyph_pairs = [] @document.save_font do fragment_hash[:text].each_char do |char| font_glyph_pairs << [(find_font_for_this_glyph char, fragment_font, fragment_font_opts, (fallback_fonts.drop 0)), char] end end # NOTE: don't add a :font to fragment if it wasn't there originally font_glyph_pairs.each {|pair| pair[0] = nil if pair[0] == original_font } if original_font form_fragments_from_like_font_glyph_pairs font_glyph_pairs, fragment_hash end
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb, line 40 def apply_font_size size, styles if (subscript? styles) || (superscript? styles) size ||= @document.font_size if String === size units = (size.end_with? 'em', '%') ? ((size.end_with? '%') ? '%' : 'em') : '' size = %(#{size.to_f * @sub_and_sup_relative_size}#{units}) else size *= @sub_and_sup_relative_size end @document.font_size(size) { yield } elsif size @document.font_size(size) { yield } else yield end end
Modify the built-in ascender write method to allow an override value to be specified using the format_state hash.
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/fragment.rb, line 29 def ascender= val @ascender = (format_state.key? :ascender) ? format_state[:ascender] : val end
# File lib/asciidoctor/pdf/ext/prawn-svg/loaders/file.rb, line 17 def assert_valid_path! path if jail_path && !(path.start_with? %(#{jail_path}#{File::SEPARATOR})) raise Prawn::SVG::UrlLoader::Error, %(file path points to location outside of jail #{jail_path}) end end
# File lib/asciidoctor/pdf/ext/prawn-table/cell.rb, line 6 def border_color= color color = [color, color] if Asciidoctor::PDF::ThemeLoader::CMYKColorValue === color super end
Prevent fragment from being written by discarding the text, optionally forcing the width to 0
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/fragment.rb, line 7 def conceal force_width_to_zero = false if force_width_to_zero @width = 0 @text = '' else @text = ' ' * space_count # preserve space_count so width is still computed correctly end end
Modify the built-in ascender write method to allow an override value to be specified using the format_state hash.
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/fragment.rb, line 35 def descender= val @descender = (format_state.key? :descender) ? format_state[:descender] : val end
Draws borders around the cell. Borders are centered on the bounds of the cell outside of any padding, so the caller is responsible for setting appropriate padding to ensure the border does not overlap with cell content.
Adds support for transparent border color.
# File lib/asciidoctor/pdf/ext/prawn-table/cell.rb, line 18 def draw_borders pt x, y = pt @pdf.mask :line_width, :stroke_color do @borders.each do |border| idx = { top: 0, right: 1, bottom: 2, left: 3 }[border] border_color = @border_colors[idx] border_width = @border_widths[idx] border_line = @border_lines[idx] next unless border_width > 0 # Left and right borders are drawn one-half border beyond the center # of the corner, so that the corners end up square. case border when :top from, to = [[x, y], [x + width, y]] when :bottom from, to = [[x, y - height], [x + width, y - height]] when :left from, to = [[x, y + (border_top_width / 2.0)], [x, y - height - (border_bottom_width / 2.0)]] else # :right from, to = [[x + width, y + (border_top_width / 2.0)], [x + width, y - height - (border_bottom_width / 2.0)]] end case border_line when :dashed @pdf.dash border_width * 4 when :dotted @pdf.dash border_width when :solid # normal line style else raise ArgumentError, 'border_line must be :solid, :dotted or :dashed' end @pdf.line_width = border_width if border_color == 'transparent' @pdf.stroke_color = '000000' @pdf.transparent 0 do @pdf.stroke_line from, to end else @pdf.stroke_color = border_color @pdf.stroke_line from, to end @pdf.undash end end end
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb, line 21 def draw_fragment_overlay_styles fragment if (underline = (styles = fragment.styles).include? :underline) || (styles.include? :strikethrough) (doc = fragment.document).save_graphics_state do if (text_decoration_width = (fs = fragment.format_state)[:text_decoration_width] || doc.text_decoration_width) doc.line_width = text_decoration_width end if (text_decoration_color = fs[:text_decoration_color]) doc.stroke_color = text_decoration_color end underline ? (doc.stroke_line fragment.underline_points) : (doc.stroke_line fragment.strikethrough_points) end end end
# File lib/asciidoctor/pdf/ext/asciidoctor/abstract_block.rb, line 4 def empty? blocks.empty? end
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb, line 20 def finalize_line @consumed.unshift text: Prawn::Text::ZWSP if @normalize_line_height super end
TODO: remove once Prawn
2.5 is released
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb, line 65 def find_font_for_this_glyph char, current_font, current_font_opts = {}, fallback_fonts_to_check = [], original_font = current_font (doc = @document).font current_font, current_font_opts if doc.font.glyph_present? char current_font elsif fallback_fonts_to_check.empty? if logger.info? && !doc.scratch? fonts_checked = [original_font].concat @fallback_fonts missing_chars = (doc.instance_variable_defined? :@missing_chars) ? (doc.instance_variable_get :@missing_chars) : (doc.instance_variable_set :@missing_chars, {}) previous_fonts_checked = (missing_chars[char] ||= []) if previous_fonts_checked.empty? && !(previous_fonts_checked.include? fonts_checked) logger.warn %(Could not locate the character `#{char}' (#{char.unpack('U*').map {|it| "\\u#{(it.to_s 16).rjust 4, '0'}" }.join}) in the following fonts: #{fonts_checked.join ', '}) previous_fonts_checked << fonts_checked end end original_font else find_font_for_this_glyph char, fallback_fonts_to_check.shift, current_font_opts, fallback_fonts_to_check, original_font end end
# File lib/asciidoctor/pdf/ext/prawn-svg/elements/image.rb, line 12 def find_image_handler data Prawn.image_handler.find data rescue nil end
# File lib/asciidoctor/pdf/ext/asciidoctor/abstract_block.rb, line 8 def first_child blocks[0] end
# File lib/asciidoctor/pdf/ext/asciidoctor/abstract_block.rb, line 16 def first_child? self == parent.blocks[0] end
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb, line 15 def format_array= array @normalize_line_height = !array.empty? && (array[0].delete :normalize_line_height) super end
# File lib/asciidoctor/pdf/ext/prawn-svg/loaders/web.rb, line 8 def from_url url (url.to_s.start_with? 'http://', 'https://') ? (load_open_uri.open_uri url, 'rb', &:read) : nil rescue raise Prawn::SVG::UrlLoader::Error, $!.message end
# File lib/asciidoctor/pdf/ext/prawn-svg/elements/image.rb, line 4 def image_dimensions data unless (handler = find_image_handler data) raise Prawn::SVG::Elements::Base::SkipElementError, 'Unsupported image type supplied to image tag' end image = handler.new data [image.width.to_f, image.height.to_f] end
Don’t strip soft hyphens when repacking unretrieved fragments
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/fragment.rb, line 17 def include_trailing_white_space! @format_state.delete :normalized_soft_hyphen super end
# File lib/asciidoctor/pdf/ext/prawn-table.rb, line 6 def initial_row_on_initial_page return 0 if fits_on_page? @pdf.bounds.height height_required = (row (0..number_of_header_rows)).height_with_span return -1 if fits_on_page? height_required, true @pdf.bounds.move_past_bottom 0 end
# File lib/asciidoctor/pdf/ext/asciidoctor/abstract_block.rb, line 12 def last_child blocks[-1] end
# File lib/asciidoctor/pdf/ext/asciidoctor/abstract_block.rb, line 20 def last_child? self == parent.blocks[-1] end
# File lib/asciidoctor/pdf/ext/prawn/document/column_box.rb, line 6 def last_column @columns - 1 end
# File lib/asciidoctor/pdf/ext/prawn-svg/loaders/web.rb, line 14 def load_open_uri if @open_uri_loader @open_uri_loader.call else require 'open-uri' unless defined? OpenURI OpenURI end end
# File lib/asciidoctor/pdf/ext/prawn/document/column_box.rb, line 10 def move_past_bottom (doc = @document).y = @y return if (@current_column = (@current_column + 1) % @columns) > 0 parent_ = @parent reset_top parent_ if (reflow_at = @reflow_margins) && (reflow_at == true || reflow_at > doc.page_number) initial_margins = doc.page.margins parent_.move_past_bottom if doc.page.margins != initial_margins doc.bounds = bounds = self.class.new doc, parent_, [(margin_box = doc.margin_box).absolute_left, @y], columns: @columns, reflow_margins: @reflow_margins, spacer: @spacer, width: margin_box.width, height: @height # ensure indentation is preserved across page break bounds.add_left_padding @total_left_padding if @total_left_padding > 0 bounds.add_right_padding @total_right_padding if @total_right_padding > 0 end nil end
# File lib/asciidoctor/pdf/ext/asciidoctor/abstract_block.rb, line 24 def next_sibling (siblings = parent.blocks)[(siblings.index self) + 1] end
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb, line 25 def next_string (string = super) == @dummy_text ? (string.extend Prawn::Text::NoopLstripBang) : string end
# File lib/asciidoctor/pdf/ext/prawn-svg/elements/use.rb, line 5 def parse result = super if @referenced_element_source.name == 'symbol' && !(@referenced_element_source.attributes.key? 'viewBox') @referenced_element_class = Prawn::SVG::Elements::Container end result end
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/arranger.rb, line 29 def preview_joined_string if (next_unconsumed = @unconsumed[0] || {})[:wj] && !(@consumed[-1] || [])[:wj] idx = 0 str = '' if (str = next_unconsumed[:text]) == @dummy_text while (next_unconsumed = @unconsumed[idx += 1] || {})[:wj] && (next_string = next_unconsumed[:text]) str += next_string unless next_string == @dummy_text end str unless str == '' end end
# File lib/asciidoctor/pdf/ext/asciidoctor/abstract_block.rb, line 28 def previous_sibling (self_idx = (siblings = parent.blocks).index self) > 0 ? siblings[self_idx - 1] : nil end
Override method in super class to provide support for a tuple consisting of alignment and offset
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb, line 96 def process_vertical_alignment text return super if Symbol === (valign = @vertical_align) return if defined? @vertical_alignment_processed @vertical_alignment_processed = true valign, offset = valign case valign when :center wrap text @at[1] -= (@height - (rendered_height = height) + @descender) * 0.5 + offset @height = rendered_height when :bottom wrap text @at[1] -= (@height - (rendered_height = height)) + offset @height = rendered_height else # :top @at[1] -= offset end nil end
# File lib/asciidoctor/pdf/ext/asciidoctor/abstract_block.rb, line 32 def remove parent.blocks.delete self end
# File lib/asciidoctor/pdf/ext/prawn/document/column_box.rb, line 27 def reset_top parent_ = @parent @current_column = 0 @height = parent_.height unless stretchy? @y = parent_.absolute_top end
# File lib/asciidoctor/pdf/optimizer.rb, line 18 def run RGhost::Config.config_platform unless File.exist? RGhost::Config::GS[:path].to_s (cmd = @params.slice 1, @params.length).unshift RGhost::Config::GS[:path].to_s #puts cmd if @debug _out, err, status = Open3.capture3(*cmd) unless (lines = err.lines.each_with_object([]) {|l, accum| (l.include? '-dNEWPDF=') ? accum.pop : (accum << l) }).empty? $stderr.write(*lines) end status.success? end
# File lib/asciidoctor/pdf/optimizer.rb, line 31 def shellescape str str end
Rearranges the column box into a single column, where the original columns are in a single file. Used for the purpose of computing the extent of content in a scratch document.
# File lib/asciidoctor/pdf/ext/prawn/document/column_box.rb, line 35 def single_file if @reflow_margins && @parent.absolute_top > @y && @columns > @current_column + 1 # defer reflow margins until all columns on current page have been exhausted @reflow_margins = @document.page_number + (@columns - @current_column) end @width = bare_column_width @columns = 1 @current_column = 0 nil end
Use .tr instead of .gsub to remove zero-width spaces
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/fragment.rb, line 23 def strip_zero_width_spaces string string.encoding == Encoding::UTF_8 ? (string.tr Prawn::Text::ZWSP, '') : string end
Convert the object to a serialized PDF
object.
# File lib/asciidoctor/pdf/ext/core/object.rb, line 5 def to_pdf_object ::PDF::Core.pdf_object self end
# File lib/asciidoctor/pdf/ext/prawn/extensions.rb, line 7 def warning *_args; end
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/fragment.rb, line 39 def width if (val = format_state[:width]) val = (val.end_with? 'em') ? val.to_f * @document.font_size : (@document.str_to_pt val) if String === val else val = super end if (border_offset = format_state[:border_offset]) val += border_offset * 2 end val end
Override method to force text justification when :force_justify option is set (typically for rendering a single line)
# File lib/asciidoctor/pdf/ext/prawn/formatted_text/box.rb, line 87 def word_spacing_for_this_line if @align == :justify && (@force_justify || (@line_wrap.space_count > 0 && !@line_wrap.paragraph_finished?)) (available_width - @line_wrap.width) / @line_wrap.space_count else 0 end end