Module: Compass::Magick::Shapes
Overview
Drawing methods shared by Compass Magick commands.
All of the drawing is done using B/W pixels with varying alpha. These shapes are used to build masks which are then applied to fill Types to generate the final canvas.
Instance Method Summary collapse
-
#circle(radius, width, feather = 1.0) ⇒ Canvas
Draws a circle mask.
Instance Method Details
#circle(radius, width, feather = 1.0) ⇒ Canvas
Draws a circle mask.
Copyright © 2003 by Nils Haeck M.Sc. (Simdesign) www.simdesign.nl
> The [..] DrawDisk routines is optimized quite well but do not claim > to be the fastest solution :) It is a floating point precision > implementation. Further optimisation would be possible if an > integer approach was chosen (but that would also loose > functionality).
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/magick/shapes.rb', line 25 def circle(radius, width, feather = 1.0) mask = ChunkyPNG::Canvas.new(radius, radius, ChunkyPNG::Color.rgba(0, 0, 0, 0)) if radius <= width center = (radius - 1) / 2.0 rpf2 = (center + feather / 2.0) ** 2 rmf2 = (center - feather / 2.0) ** 2 lx = [(center - rpf2).floor, 0].max ly = [(center - rpf2).floor, 0].max rx = [(center + rpf2).ceil, radius - 1].min ry = [(center + rpf2).ceil, radius - 1].min sqx = Array.new(rx - lx + 1) for x in lx..rx sqx[x - lx] = (x - center) ** 2 end for y in ly..ry sqy = (y - center) ** 2 for x in lx..rx sqdist = sqy + sqx[x - lx] if sqdist < rmf2 mask.set_pixel(x, y, ChunkyPNG::Color::WHITE) else if sqdist < rpf2 fact = (((center - Math.sqrt(sqdist)) * 2.0 / feather) * 0.5 + 0.5) mask.set_pixel(x, y, ChunkyPNG::Color.rgba(255, 255, 255, (255 * [0, [fact, 1].min].max).to_i)) end end end end else center = (radius - 1) / 2.0 inrad = (center + feather / 2.0) - width ropf2 = (center + feather / 2.0) ** 2 romf2 = (center - feather / 2.0) ** 2 ripf2 = (inrad + feather / 2.0) ** 2 rimf2 = (inrad - feather / 2.0) ** 2 lx = [(center - ropf2).floor, 0].max ly = [(center - ropf2).floor, 0].max rx = [(center + ropf2).ceil, radius - 1].min ry = [(center + ropf2).ceil, radius - 1].min feather = width if feather > width sqx = Array.new(rx - lx + 1) for x in lx..rx sqx[x - lx] = (x - center) ** 2 end for y in ly..ry sqy = (y - center) ** 2 for x in lx..rx sqdist = sqy + sqx[x - lx] if sqdist >= rimf2 if sqdist < ropf2 if sqdist < romf2 if sqdist < ripf2 fact = (((Math.sqrt(sqdist) - inrad) * 2 / feather) * 0.5 + 0.5) mask.set_pixel(x, y, ChunkyPNG::Color.rgba(255, 255, 255, (255 * [0, [fact, 1].min].max).to_i)) else mask.set_pixel(x, y, ChunkyPNG::Color::WHITE) end else fact = (((center - Math.sqrt(sqdist)) * 2 / feather) * 0.5 + 0.5) mask.set_pixel(x, y, ChunkyPNG::Color.rgba(255, 255, 255, (255 * [0, [fact, 1].min].max).to_i)) end end end end end end mask end |