| 1 |
extern crate cairo;
|
| 2 |
extern crate palette;
|
| 3 |
extern crate rand;
|
| 4 |
|
| 5 |
use rand::Rng;
|
| 6 |
use cairo::Gradient;
|
| 7 |
|
| 8 |
const WIDTH: i32 = 3840;
|
| 9 |
const HEIGHT: i32 = 2160;
|
| 10 |
|
| 11 |
fn cloud(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
|
| 12 |
let x_scale = rng.gen::<f64>() * 2.0 + 1.0;
|
| 13 |
let x = (rng.gen::<f64>() * WIDTH as f64) / x_scale;
|
| 14 |
let y = rng.gen::<f64>() * HEIGHT as f64;
|
| 15 |
let num_circles = 2 + (rng.gen::<isize>() % 2);
|
| 16 |
let vec: Vec<(f64, f64)> = (0..num_circles).map(|_| {
|
| 17 |
let width = 60.0 + rng.gen::<f64>() * 200.0;
|
| 18 |
let dist = 30.0 + rng.gen::<f64>() * 30.0;
|
| 19 |
(width, dist)
|
| 20 |
}).collect();
|
| 21 |
|
| 22 |
let surf = cairo::Context::new(&ctx.get_target().create_similar(cairo::Content::Alpha, WIDTH, HEIGHT));
|
| 23 |
|
| 24 |
surf.save();
|
| 25 |
let mut max_y = 0.0;
|
| 26 |
let mut offset = x;
|
| 27 |
surf.scale(x_scale, 1.0);
|
| 28 |
surf.set_source_rgba(1.0, 1.0, 1.0, 1.0);
|
| 29 |
for (width, dist) in vec {
|
| 30 |
surf.arc(offset, y, width, 0.0, 3.14159 * 2.0);
|
| 31 |
surf.fill();
|
| 32 |
offset = offset + width + dist;
|
| 33 |
max_y = if width > max_y { width } else { max_y };
|
| 34 |
}
|
| 35 |
surf.set_source_rgba(0.0, 0.0, 0.0, 0.0);
|
| 36 |
surf.set_operator(cairo::Operator::Source);
|
| 37 |
surf.rectangle(x - 260.0, y, offset + 260.0, max_y);
|
| 38 |
surf.fill();
|
| 39 |
surf.restore();
|
| 40 |
|
| 41 |
surf.set_source_rgba(1.0, 1.0, 1.0, 0.8);
|
| 42 |
ctx.mask(&cairo::SurfacePattern::create(&surf.get_target()));
|
| 43 |
}
|
| 44 |
|
| 45 |
fn shinedies(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
|
| 46 |
let r = rng.gen::<f64>();
|
| 47 |
for _ in 0..20 {
|
| 48 |
let surf = cairo::Context::new(&ctx.get_target().create_similar(cairo::Content::Alpha, WIDTH, HEIGHT));
|
| 49 |
|
| 50 |
surf.save();
|
| 51 |
surf.scale(0.5, 0.5);
|
| 52 |
surf.translate(rng.gen::<f64>() * WIDTH as f64 * 2.0, rng.gen::<f64>() * HEIGHT as f64 * 2.0);
|
| 53 |
surf.rotate(r);
|
| 54 |
surf.set_source_rgba(1.0, 1.0, 1.0, 1.0);
|
| 55 |
let w = 300.0 + rng.gen::<f64>() * 1200.0;
|
| 56 |
let r = rng.gen::<f64>() * 300.0;
|
| 57 |
surf.arc(0.0, 0.0, r, 0.0, 3.14159 * 2.0);
|
| 58 |
surf.fill();
|
| 59 |
surf.arc(w, 0.0, r, 0.0, 3.14159 * 2.0);
|
| 60 |
surf.fill();
|
| 61 |
surf.rectangle(0.0, -r, w, r * 2.0);
|
| 62 |
surf.fill();
|
| 63 |
surf.restore();
|
| 64 |
|
| 65 |
ctx.set_source_rgba(1.0, 1.0, 1.0, 0.3);
|
| 66 |
ctx.mask(&cairo::SurfacePattern::create(&surf.get_target()));
|
| 67 |
}
|
| 68 |
}
|
| 69 |
|
| 70 |
fn stars(ctx: &cairo::Context, rng: &mut rand::ThreadRng) {
|
| 71 |
ctx.set_source_rgba(1.0, 1.0, 1.0, 0.8);
|
| 72 |
for _ in 0..200 {
|
| 73 |
let x = rng.gen::<f64>() * WIDTH as f64;
|
| 74 |
let y = rng.gen::<f64>() * HEIGHT as f64;
|
| 75 |
let s = 4.0 + rng.gen::<f64>() * 6.0 as f64;
|
| 76 |
ctx.arc(x, y, s, 0.0, 3.14159 * 2.0);
|
| 77 |
ctx.fill();
|
| 78 |
}
|
| 79 |
}
|
| 80 |
|
| 81 |
fn get_sky_colors(rng: &mut rand::ThreadRng) -> (palette::Rgb, palette::Rgb) {
|
| 82 |
use palette::{RgbHue, Hsv, Hue};
|
| 83 |
let default_dark: Hsv = Hsv::from(palette::Rgb::new(0.188, 0.333, 0.51));
|
| 84 |
let default_light: Hsv = Hsv::from(palette::Rgb::new(0.482, 0.749, 0.839));
|
| 85 |
let shift = RgbHue::from_radians(rng.gen::<f32>() * 3.14159 * 2.0);
|
| 86 |
(default_dark.shift_hue(shift).into(), default_light.shift_hue(shift).into())
|
| 87 |
}
|
| 88 |
|
| 89 |
fn main() {
|
| 90 |
let surf = cairo::ImageSurface::create(
|
| 91 |
cairo::Format::Rgb24,
|
| 92 |
WIDTH,
|
| 93 |
HEIGHT
|
| 94 |
).unwrap();
|
| 95 |
|
| 96 |
let mut rng = rand::thread_rng();
|
| 97 |
let ctx = cairo::Context::new(&surf);
|
| 98 |
let w = rng.gen::<u8>() % 3;
|
| 99 |
ctx.set_source_rgb(
|
| 100 |
if w == 0 { 0.4 } else { 0.2 },
|
| 101 |
if w == 1 { 0.4 } else { 0.2 },
|
| 102 |
if w == 2 { 0.4 } else { 0.2 },
|
| 103 |
);
|
| 104 |
ctx.paint();
|
| 105 |
|
| 106 |
let g = cairo::LinearGradient::new(
|
| 107 |
0.0, 0.0, 0.0, HEIGHT as f64
|
| 108 |
);
|
| 109 |
let (dark, light) = get_sky_colors(&mut rng);
|
| 110 |
g.add_color_stop_rgb(0.0, dark.red as f64, dark.green as f64, dark.blue as f64);
|
| 111 |
g.add_color_stop_rgb(1.0, light.red as f64, light.green as f64, light.blue as f64);
|
| 112 |
ctx.set_source(&g);
|
| 113 |
ctx.paint();
|
| 114 |
|
| 115 |
stars(&ctx, &mut rng);
|
| 116 |
for _ in 0..10 {
|
| 117 |
cloud(&ctx, &mut rng);
|
| 118 |
}
|
| 119 |
shinedies(&ctx, &mut rng);
|
| 120 |
|
| 121 |
{
|
| 122 |
let mut f = std::fs::File::create("image.png").unwrap();
|
| 123 |
surf.write_to_png(&mut f).unwrap();
|
| 124 |
}
|
| 125 |
}
|