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 |