require 'rvg/rvg' include Magick class Saucy def Saucy.render_text text, attrs, font_store font_size = attrs[:size] || 10 font = attrs[:font] || 'arial.ttf' b_color = attrs[:background] || "transparent" color = attrs[:color] || 'black' if attrs[:outline] stroke_color = attrs[:outline][:color] || 'black' stroke_width = attrs[:outline][:width] || 0 stroke_inside = attrs[:outline][:inside] || 0 else stroke_width = 0 stroke_inside = 0 stroke_color = 'black' end #rvg = RVG.new(5000,5000) do |canvas| rvg = RVG.new(font_size*text.length*2 + stroke_width*2, font_size*2+ stroke_width*2) do |canvas| if(b_color != 'transparent') canvas.background_fill = b_color end if FileTest.exists?(File.join(font_store, font)) font_file = File.join(font_store, font) else font_file = File.join(font_store, '/arial.ttf') end sw = stroke_width if sw == 0 canvas.text(0+sw,font_size+sw, text).styles(:font => '"' + font_file + '"', :font_size=>font_size, :fill=>color) else canvas.text(0+sw,font_size+sw, text).styles(:font => '"' + font_file + '"', :font_size=>font_size, :fill=>color, :stroke => stroke_color, :stroke_width => stroke_width) end if stroke_inside > 0 canvas.text(0+sw,font_size+sw, text).styles(:font => '"' + font_file +'"', :font_size => font_size, :fill=> color, :stroke_width => stroke_inside, :stroke => color ) end end img = rvg.draw #img.trim end def Saucy.render_gradient attrs, texture_store direction = attrs[:direction] || 'x' bg_start_color = attrs[:background][:color] || 'white' bg_end_color = attrs[:background][:color_end] || attrs[:background][:color] texture_start_color = attrs[:texture][:color] || attrs[:background][:color] texture_end_color = attrs[:texture][:color_end] || attrs[:texture][:color] texture_opacity = ((attrs[:texture][:opacity] || 1.0).to_f * 255).to_i opacity_start = ((attrs[:background][:opacity] || 1.0).to_f * 255).to_i opacity_end = ((attrs[:background][:opacity_end] || attrs[:background][:opacity]).to_f * 255).to_i size = attrs[:size] || 100 texture_tile = attrs[:texture][:tile] texture_img = Image.read(texture_store + texture_tile).first if texture_tile if(direction == 'x') width = size height = ( texture_tile ? texture_img.rows : 10 ) bg = GradientFill.new(0, 0, 0, width, bg_start_color, bg_end_color) texture = GradientFill.new(0, 0, 0, width, texture_start_color, texture_end_color) elsif(direction == 'y') height = size width = texture_tile ? texture_img.columns : 10 bg = GradientFill.new(0, 0, height, 0, bg_start_color, bg_end_color) texture = GradientFill.new(0, 0, height, 0, texture_start_color, texture_end_color) end img_bg = Image.new(width, height, bg) img_texture = Image.new(width, height, texture) unless texture_tile == nil mask = ImageList.new mask_fill = TextureFill.new(texture_img) mask.new_image(width, height) gc = Draw.new gc.pattern('mask', 0, 0, texture_img.columns, texture_img.rows) { gc.composite(0,0,texture_img.columns,texture_img.rows,texture_img) } gc.fill('mask') gc.rectangle(0,0,width,height) gc.draw(mask) mask = mask.negate mask.matte=false opacity_color = "rgb(#{texture_opacity},#{texture_opacity},#{texture_opacity})" mask_trans = Image.new(width, height) {self.background_color = opacity_color} mask_trans.matte=true mask_trans.composite!(mask,0,0, CopyOpacityCompositeOp) mask_trans2 = Image.new(width, height) {self.background_color = '#000'} mask_trans2.composite!(mask_trans,0,0, OverCompositeOp) mask_trans2.matte=false img_texture.matte=true img_texture.composite!(mask_trans2,0,0, CopyOpacityCompositeOp) img_texture.matte=true img_bg.composite!(img_texture,0,0, OverCompositeOp) end if (opacity_start && opacity_end) os = (255*opacity_start.to_f).floor oe = (255*opacity_end.to_f).floor if direction == 'x' h,w=0,width else h,w=height,0 end opacity_gradient = GradientFill.new(0, 0, h, w,"rgb(#{os},#{os},#{os})", "rgb(#{oe},#{oe},#{oe})") img_bg.matte=true opacity_mask = Image.new(width, height, opacity_gradient) opacity_mask.matte=false img_bg.composite!(opacity_mask, 0,0, CopyOpacityCompositeOp) end img_bg end def Saucy.render_shadow input, attrs # matte = (attrs['psm'] || 'transparent') shadow_color = attrs[:color] || '#888' shadow_opacity = 255 - ((attrs[:opacity] || 0.7) * 255).to_i shadow_top = attrs[:top] || 3 shadow_left = attrs[:left] || 3 blur_radius = attrs[:radius] || 2.0 w=input.columns+ blur_radius*4+shadow_left.abs*2 h=input.rows+ blur_radius*4+shadow_top.abs*2 input.matte = true opacity_color = "rgb(#{shadow_opacity},#{shadow_opacity},#{shadow_opacity})" input_colorized= input.copy.colorize(1.0, 1.0, 1.0, opacity_color) shadow_mask = Image.new(w,h ){self.background_color = '#fff'} zero=[shadow_left.abs+blur_radius,shadow_top.abs+blur_radius] shadow_mask.composite!(input_colorized, blur_radius, blur_radius, OverCompositeOp) shadow_mask.matte=true shadow_mask = shadow_mask.blur_image(blur_radius,blur_radius) output = Image.new(w,h){self.background_color = shadow_color} inverse_shadow_mask = shadow_mask.negate inverse_shadow_mask.matte = false output.matte = true output.composite!(inverse_shadow_mask, zero[0]+shadow_left,zero[1]+shadow_top, CopyOpacityCompositeOp) output.composite!(input, zero[0]+blur_radius,zero[1]+blur_radius, OverCompositeOp) output.trim end =begin def curve_render attrs r = attrs['r'].to_i sw = attrs['sw'].to_i oc = attrs['oc'].gsub('H','#') sc = attrs['sc'].gsub('H','#') ic = attrs['ic'].gsub('H','#') w = attrs['w'].to_i h = attrs['h'].to_i b = attrs['b'] tAdd = (b[0..0] == '0') ? 1 : 0 rAdd = (b[1..1] == '0') ? 1 : 0 bAdd = (b[2..2] == '0') ? 1 : 0 lAdd = (b[3..3] == '0') ? 1 : 0 img = ImageList.new img.new_image(w,h) { self.background_color = 'transparent'} gc = Draw.new if(ic != 'transparent') gc.fill_opacity(255) gc.fill(ic) else gc.fill_opacity(0) end if oc != 'transparent' gc.stroke(oc) gc.stroke_width(r-1) a = 1 rad = r *3/2 left = -r/2 + 0 - r*(lAdd) top = -r/2 + 0 - r*(tAdd) width = w+r/2 - a + r*(rAdd) height = h+r/2 - a + r*(bAdd) # gc.roundrectangle(-r/2 + a,-r/2 + a,w+r/2 - a,h+r/2 - a, r*3/2,r*3/2) gc.roundrectangle(left, top, width, height, rad,rad ) end if sc != 'transparent' gc.stroke(sc) gc.stroke_width(sw) # Draw rounded rectangle a = 1 rad = r-sw/2 left = sw/2+0 - r*(lAdd) top = sw/2+0 - r*(tAdd) width = w-sw/2-a + r*(rAdd) height = h-sw/2-a + r*(bAdd) gc.roundrectangle(left, top, width, height, rad,rad ) #gc.roundrectangle(bw/2+a,bw/2+a, w-bw/2-a,h-bw/2-a,r-bw/2,r-bw/2) end gc.draw(img) img end def liquid_curve_render attrs root2 = 1.4142135623730950488016887242097 r = attrs['r'].to_i bw = attrs['bw'].to_i ir = r - bw oc = attrs['oc'].gsub('H','#').gsub('H','#') bc = attrs['bc'].gsub('H','#').gsub('H','#') ic = attrs['ic'].gsub('H','#').gsub('H','#') img = ImageList.new img.new_image(r, r) { self.background_color = 'transparent'} gc = Draw.new #BL big = r * root2 gc.fill_opacity(0) if oc != 'transparent' gc.stroke(oc).stroke_width((big-ir)*2) gc.arc(-big,-big,big,big,0,270) end inner2 = bw*0.5 + ir - 0.5 if bc != 'transparent' if(ic != 'transparent') gc.fill_opacity(255) gc.fill(ic) end gc.stroke(bc).stroke_width(bw) gc.arc(-inner2,-inner2,inner2,inner2,0,270) end gc.draw(img) img.write(img_prefix + 'br' + img_postfix) border_img = img.crop(0,0,1,r) img.write(img_prefix + 'br' + img_postfix) img.rotate(90).write(img_prefix + 'bl' + img_postfix) img.rotate(180).write(img_prefix + 'tl' + img_postfix) img.rotate(270).write(img_prefix + 'tr' + img_postfix) border_img.write(img_prefix + 'b' + img_postfix) border_img.rotate(90).write(img_prefix + 'l' + img_postfix) border_img.rotate(180).write(img_prefix + 't' + img_postfix) border_img.rotate(270).write(img_prefix + 'r' + img_postfix) end def rotate_render input, attrs angle=attrs['pr'].to_i input.matte = true input.rotate!(angle) input end def guassian_blur_render input, attrs blur_radius = (attrs['pg'] || '10').to_f w=input.columns#+ blur_radius*2 h=input.rows#+ blur_radius*2 output = Image.new(w,h) {self.background_color = 'transparent'} blur = input.blur_image(blur_radius/2,blur_radius/2) output.composite!(blur, 0,0, OverCompositeOp) output end def post_render input, attrs input = rotate_render input, attrs if attrs['pr'] input = shadow_render input, attrs if attrs['ps'] input = guassian_blur_render input, attrs if attrs['pg'] # background render if (attrs['pb'] != 'transparent') bg = Image.new(input.columns, input.rows) {self.background_color = attrs['pb'].gsub('H','#')} input = bg.composite(input,0,0,OverCompositeOp) end input end #if :use_cache => false, saucy will render the image every time, useful for debugging saucy the lib def initialize attrs @use_cache=attrs[:use_cache] || true @image_store = attrs[:image_store] @font_store = attrs[:font_store] @texture_store = attrs[:texture_store] end =end =begin def render filename render_type = filename.slice(0..0) name = filename.slice(0...filename.length-4) #.gsub(/HX/,'#') output_path = @image_store + filename if !@use_cache || !(FileTest.exists? output_path) img_attrs = name.slice(2...name.length) #cut off the first attrs = {} img_attrs.split('~').each do |param| k=param.split('-') attrs[k[0]] = CGI.unescape(k[1]) end case render_type when 't' pre = ttf_render(attrs) when 'c' pre = curve_render(attrs) when 'g' pre = gradient_render(attrs) else raise('no such type') end end output_path end =end end