lib/squib/graphics/image.rb in squib-0.18.0 vs lib/squib/graphics/image.rb in squib-0.19.0a

- old
+ new

@@ -1,123 +1,123 @@ -module Squib - - # Cache all pngs we've already loaded - # - # :nodoc: - # @api private - def cache_load_image(file) - @img_cache ||= {} - @img_cache[file] ||= open_png file - end - module_function :cache_load_image - - # Open a PNG file, checking magic bytes if it's a real PNG - # Magic bytes taken from: - # https://en.wikipedia.org/wiki/List_of_file_signatures - # :nodoc: - # @api private - PNG_MAGIC = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A] - def open_png(file) - if PNG_MAGIC == File.read(file, 8).bytes - return Cairo::ImageSurface.from_png(file) - else - raise ArgumentError.new("ERROR: #{file} is not a PNG file") - end - end - module_function :open_png - - class Card - - # :nodoc: - # @api private - def png(file, box, paint, trans) - Squib.logger.debug {"RENDERING PNG: \n file: #{file}\n box: #{box}\n paint: #{paint}\n trans: #{trans}"} - return if file.nil? or file.eql? '' - png = Squib.cache_load_image(file) - use_cairo do |cc| - cc.translate(box.x, box.y) - box.width = png.width.to_f if box.width == :native - box.height = png.height.to_f if box.height == :native - box.width = png.width.to_f * box.height.to_f / png.height.to_f if box.width == :scale - box.height = png.height.to_f * box.width.to_f / png.width.to_f if box.height == :scale - - scale_width = box.width.to_f / png.width.to_f - scale_height = box.height.to_f / png.height.to_f - warn_png_scale(file, scale_width, scale_height) - cc.scale(scale_width, scale_height) - - cc.rotate(trans.angle) - cc.flip(trans.flip_vertical, trans.flip_horizontal, box.width / 2, box.height / 2) - cc.translate(-box.x, -box.y) - - trans.crop_width = png.width.to_f if trans.crop_width == :native - trans.crop_height = png.height.to_f if trans.crop_height == :native - cc.rounded_rectangle(box.x, box.y, trans.crop_width, trans.crop_height, trans.crop_corner_x_radius, trans.crop_corner_y_radius) - cc.clip - cc.translate(-trans.crop_x, -trans.crop_y) - - - cc.set_source(png, box.x, box.y) - cc.operator = paint.blend unless paint.blend == :none - if paint.mask.empty? - cc.paint(paint.alpha) - else - cc.set_source_squibcolor(paint.mask) - cc.mask(png, box.x, box.y) - end - end - end - - # :nodoc: - # @api private - def warn_png_scale(file, scale_width, scale_height) - if @deck.conf.warn_png_scale? && (scale_width > 1.0 || scale_height > 1.0) - Squib.logger.warn "PNG is being upscaled - antialiasing could result: #{file}" - end - end - - # :nodoc: - # @api private - def svg(file, svg_args, box, paint, trans) - Squib.logger.debug {"Rendering: #{file}, id: #{id} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}, mask: #{mask}"} - Squib.logger.warn 'Both an SVG file and SVG data were specified' unless file.to_s.empty? || svg_args.data.to_s.empty? - return if (file.nil? or file.eql? '') and svg_args.data.nil? # nothing specified TODO Move this out to arg validator - svg_args.data = File.read(file) if svg_args.data.to_s.empty? - begin - svg = Rsvg::Handle.new_from_data(svg_args.data) - rescue Rsvg::Error::Failed - Squib.logger.error "Invalid SVG data. Is '#{file}' a valid svg file?" - return - end - box.width = svg.width if box.width == :native - box.height = svg.height if box.height == :native - box.width = svg.width.to_f * box.height.to_f / svg.height.to_f if box.width == :scale - box.height = svg.height.to_f * box.width.to_f / svg.width.to_f if box.height == :scale - scale_width = box.width.to_f / svg.width.to_f - scale_height = box.height.to_f / svg.height.to_f - use_cairo do |cc| - cc.translate(box.x, box.y) - cc.flip(trans.flip_vertical, trans.flip_horizontal, box.width / 2, box.height / 2) - cc.rotate(trans.angle) - cc.scale(scale_width, scale_height) - - trans.crop_width = box.width if trans.crop_width == :native - trans.crop_height = box.height if trans.crop_height == :native - cc.rounded_rectangle(0, 0, trans.crop_width / scale_width, trans.crop_height / scale_height, trans.crop_corner_x_radius, trans.crop_corner_y_radius) - cc.clip - cc.translate(-trans.crop_x, -trans.crop_y) - - cc.operator = paint.blend unless paint.blend == :none - if paint.mask.to_s.empty? - cc.render_rsvg_handle(svg, id: svg_args.id) - else - tmp = Cairo::ImageSurface.new(box.width / scale_width, box.height / scale_height) - tmp_cc = Cairo::Context.new(tmp) - tmp_cc.render_rsvg_handle(svg, id: svg_args.id) - cc.set_source_squibcolor(paint.mask) - cc.mask(tmp, 0, 0) - end - end - end - - end -end +module Squib + + # Cache all pngs we've already loaded + # + # :nodoc: + # @api private + def cache_load_image(file) + @img_cache ||= {} + @img_cache[file] ||= open_png file + end + module_function :cache_load_image + + # Open a PNG file, checking magic bytes if it's a real PNG + # Magic bytes taken from: + # https://en.wikipedia.org/wiki/List_of_file_signatures + # :nodoc: + # @api private + PNG_MAGIC = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A] + def open_png(file) + if PNG_MAGIC == File.read(file, 8).bytes + return Cairo::ImageSurface.from_png(file) + else + raise ArgumentError.new("ERROR: #{file} is not a PNG file") + end + end + module_function :open_png + + class Card + + # :nodoc: + # @api private + def png(file, box, paint, trans) + Squib.logger.debug {"RENDERING PNG: \n file: #{file}\n box: #{box}\n paint: #{paint}\n trans: #{trans}"} + return if file.nil? or file.eql? '' + png = Squib.cache_load_image(file) + use_cairo do |cc| + cc.translate(box.x, box.y) + box.width = png.width.to_f if box.width == :native + box.height = png.height.to_f if box.height == :native + box.width = png.width.to_f * box.height.to_f / png.height.to_f if box.width == :scale + box.height = png.height.to_f * box.width.to_f / png.width.to_f if box.height == :scale + + scale_width = box.width.to_f / png.width.to_f + scale_height = box.height.to_f / png.height.to_f + warn_png_scale(file, scale_width, scale_height) + cc.scale(scale_width, scale_height) + + cc.rotate(trans.angle) + cc.flip(trans.flip_vertical, trans.flip_horizontal, box.width / 2, box.height / 2) + cc.translate(-box.x, -box.y) + + trans.crop_width = png.width.to_f if trans.crop_width == :native + trans.crop_height = png.height.to_f if trans.crop_height == :native + cc.rounded_rectangle(box.x, box.y, trans.crop_width, trans.crop_height, trans.crop_corner_x_radius, trans.crop_corner_y_radius) + cc.clip + cc.translate(-trans.crop_x, -trans.crop_y) + + + cc.set_source(png, box.x, box.y) + cc.operator = paint.blend unless paint.blend == :none + if paint.mask.empty? + cc.paint(paint.alpha) + else + cc.set_source_squibcolor(paint.mask) + cc.mask(png, box.x, box.y) + end + end + end + + # :nodoc: + # @api private + def warn_png_scale(file, scale_width, scale_height) + if @deck.conf.warn_png_scale? && (scale_width > 1.0 || scale_height > 1.0) + Squib.logger.warn "PNG is being upscaled - antialiasing could result: #{file}" + end + end + + # :nodoc: + # @api private + def svg(file, svg_args, box, paint, trans) + Squib.logger.debug {"Rendering: #{file}, id: #{id} @#{x},#{y} #{width}x#{height}, alpha: #{alpha}, blend: #{blend}, angle: #{angle}, mask: #{mask}"} + Squib.logger.warn 'Both an SVG file and SVG data were specified' unless file.to_s.empty? || svg_args.data.to_s.empty? + return if (file.nil? or file.eql? '') and svg_args.data.nil? # nothing specified TODO Move this out to arg validator + svg_args.data = File.read(file) if svg_args.data.to_s.empty? + begin + svg = Rsvg::Handle.new_from_data(svg_args.data) + rescue Rsvg::Error::Failed + Squib.logger.error "Invalid SVG data. Is '#{file}' a valid svg file?" + return + end + box.width = svg.width if box.width == :native + box.height = svg.height if box.height == :native + box.width = svg.width.to_f * box.height.to_f / svg.height.to_f if box.width == :scale + box.height = svg.height.to_f * box.width.to_f / svg.width.to_f if box.height == :scale + scale_width = box.width.to_f / svg.width.to_f + scale_height = box.height.to_f / svg.height.to_f + use_cairo do |cc| + cc.translate(box.x, box.y) + cc.flip(trans.flip_vertical, trans.flip_horizontal, box.width / 2, box.height / 2) + cc.rotate(trans.angle) + cc.scale(scale_width, scale_height) + + trans.crop_width = box.width if trans.crop_width == :native + trans.crop_height = box.height if trans.crop_height == :native + cc.rounded_rectangle(0, 0, trans.crop_width / scale_width, trans.crop_height / scale_height, trans.crop_corner_x_radius, trans.crop_corner_y_radius) + cc.clip + cc.translate(-trans.crop_x, -trans.crop_y) + + cc.operator = paint.blend unless paint.blend == :none + if paint.mask.to_s.empty? + cc.render_rsvg_handle(svg, id: svg_args.id) + else + tmp = Cairo::ImageSurface.new(box.width / scale_width, box.height / scale_height) + tmp_cc = Cairo::Context.new(tmp) + tmp_cc.render_rsvg_handle(svg, id: svg_args.id) + cc.set_source_squibcolor(paint.mask) + cc.mask(tmp, 0, 0) + end + end + end + + end +end