rubyrmagick

How to render text on image with RMagick and Word wrap?


I need to render some text (unicode, helvetica, white, 22px, bold) on a image (1024x768).

This is my code so far:

img = Magick::ImageList.new("my_bg_img.jpg")
txt = Magick::Draw.new

img.annotate(txt, 800, 600, 0, 0, "my super long text that needs to be auto line breaked and cropped") {
      txt.gravity = Magick::NorthGravity
      txt.pointsize = 22
      txt.fill = "#ffffff"
      txt.font_family = 'helvetica'
      txt.font_weight = Magick::BoldWeight
}

img.format = "jpeg"

return img.to_blob

Its all fine but its not automatically breaking the lines (Word wrap) to fit all the text into my defined area ( 800x600 ).

What am I doing wrong?

Thanks for helping :)


Solution

  • On the Draw.annotate method the width parameter doesn't seem to have an effect on the rendering text.

    I have faced the same problem and I developed this functions to fit the text to a specified width by adding new lines.

    I have a function to check if a text fit a specified width when drawed on image

    def text_fit?(text, width)
      tmp_image = Image.new(width, 500)
      drawing = Draw.new
      drawing.annotate(tmp_image, 0, 0, 0, 0, text) { |txt|
        txt.gravity = Magick::NorthGravity
        txt.pointsize = 22
        txt.fill = "#ffffff"
        txt.font_family = 'helvetica'
        txt.font_weight = Magick::BoldWeight
      }
      metrics = drawing.get_multiline_type_metrics(tmp_image, text)
      (metrics.width < width)
    end
    

    And I have another function to transform the text to fit in the specified width by adding new lines

    def fit_text(text, width)
      separator = ' '
      line = ''
    
      if not text_fit?(text, width) and text.include? separator
        i = 0
        text.split(separator).each do |word|
          if i == 0
            tmp_line = line + word
          else
            tmp_line = line + separator + word
          end
    
          if text_fit?(tmp_line, width)
            unless i == 0
              line += separator
            end
            line += word
          else
            unless i == 0
              line +=  '\n'
            end
            line += word
          end
          i += 1
        end
        text = line
      end
      text
    end