Sample rectangle-making code. Presented at The Dalvik Underground, April 7, 2014.
Questions? Get in touch.
Sample rectangle-making code. Presented at The Dalvik Underground, April 7, 2014.
Questions? Get in touch.
| #!/usr/bin/env ruby | |
| require 'rubygems' | |
| require 'chunky_png' | |
| # the resolutions we care about | |
| sizes = { | |
| mdpi: 1.0, | |
| hdpi: 1.5, | |
| xhdpi: 2.0, | |
| xxhdpi: 3.0 | |
| } | |
| # the colors we'll use | |
| PRESSED_HOLO_LIGHT = ChunkyPNG::Color.rgba(51, 181, 229, 153) | |
| TRANSPARENT = ChunkyPNG::Color::TRANSPARENT | |
| BLACK = ChunkyPNG::Color::BLACK | |
| WHITE = ChunkyPNG::Color::WHITE | |
| GREY = ChunkyPNG::Color.rgb(221, 221, 221) | |
| REDDISH = ChunkyPNG::Color.rgb(0xd5, 0x30, 0x49) | |
| def pressed(bg) | |
| ChunkyPNG::Color.compose_precise(PRESSED_HOLO_LIGHT, bg) | |
| end | |
| module CanvasExtras | |
| # like ChunkyPNG::Drawing::rect, but sets pixels instead of composing them. | |
| def force_rect(x0, y0, x1, y1, fill_color = ChunkyPNG::Color::TRANSPARENT) | |
| [x0, x1].min.upto([x0, x1].max) do |x| | |
| [y0, y1].min.upto([y0, y1].max) do |y| | |
| set_pixel(x, y, fill_color) | |
| end | |
| end | |
| end | |
| end | |
| ChunkyPNG::Canvas.send :include, CanvasExtras | |
| class Array | |
| def sum | |
| self.inject(0){ |a,b| a+b } | |
| end | |
| end | |
| shapes = { | |
| standalone: [ true, true ], | |
| top: [ true, false ], | |
| top_dark: [ true, false ], | |
| bottom: [ false, true ], | |
| middle: [ false, false ] | |
| } | |
| modes = { | |
| resting: WHITE, | |
| pressed: pressed(WHITE), | |
| focused: ChunkyPNG::Color.rgb(193, 232, 247) | |
| } | |
| sizes.each do |dpi, factor| | |
| shapes.each do |shape, args| | |
| draw_top = args[0] | |
| draw_bottom = args[1] | |
| # set up the bounds, working in dip | |
| left_to_right = [15, 1, 15, 4, 15, 1, 15] | |
| top_to_bottom = [8, 1, 8, 4, 8, 1, 8] | |
| unless draw_top | |
| top_to_bottom[0] = 0 | |
| top_to_bottom[1] = 0 | |
| end | |
| unless draw_bottom | |
| top_to_bottom[6] = 0 | |
| end | |
| # convert dip to px. 9-patch borders are always 1px. | |
| scaled_left_to_right = [1] + left_to_right.map{|n| (n*factor).round} + [1] | |
| scaled_top_to_bottom = [1] + top_to_bottom.map{|n| (n*factor).round} + [1] | |
| # hairlines are also always 1px. | |
| scaled_left_to_right[2] = scaled_left_to_right[6] = 1 | |
| scaled_top_to_bottom[6] = 1 unless shape == :top_dark | |
| scaled_top_to_bottom[2] = 1 if draw_top | |
| width = scaled_left_to_right.sum | |
| height = scaled_top_to_bottom.sum | |
| puts "#{dpi} #{shape}: #{width}x#{height}" | |
| modes.each do |mode, maincolor| | |
| colors = [TRANSPARENT, GREY, maincolor] | |
| png = ChunkyPNG::Image.new(width, height, TRANSPARENT) | |
| 0.upto(2) do |i| | |
| left = scaled_left_to_right[0..i].sum | |
| right = scaled_left_to_right[0..(7-i)].sum - 1 | |
| top = scaled_top_to_bottom[0..i].sum | |
| bottom = scaled_top_to_bottom[0..(7-i)].sum - 1 | |
| png.force_rect(left, top, right, bottom, colors[i]) | |
| end | |
| unless draw_bottom | |
| left = scaled_left_to_right[0..2].sum | |
| right = scaled_left_to_right[0..5].sum - 1 | |
| top = scaled_top_to_bottom[0..5].sum | |
| bottom = scaled_top_to_bottom[0..6].sum - 1 | |
| png.force_rect(left, top, right, bottom, WHITE) | |
| left = scaled_left_to_right[0..3].sum | |
| right = scaled_left_to_right[0..4].sum - 1 | |
| png.rect(left, top, right, bottom, (shape == :top_dark ? REDDISH : GREY)) | |
| end | |
| left = scaled_left_to_right[0..3].sum | |
| right = scaled_left_to_right[0..4].sum - 1 | |
| top = scaled_top_to_bottom[0..3].sum | |
| bottom = scaled_top_to_bottom[0..4].sum - 1 | |
| png.line(left, 0, right, 0, BLACK) | |
| png.line(left, height-1, right, height-1, BLACK) | |
| png.line(0, top, 0, bottom, BLACK) | |
| png.line(width-1, top, width-1, bottom, BLACK) | |
| fn = File.join(File.dirname(__FILE__), "..", "res", "drawable-#{dpi}", "venuepicker_#{shape}_#{mode}.9.png") | |
| png.save(fn) | |
| end | |
| end | |
| end |