Commit 7be0d4fd authored by Michael Hölzl's avatar Michael Hölzl
Browse files

[feature] Not it is possible to invert the box-shadow or create a box-shadow with rounded corners.

parent 54d01369
......@@ -88,10 +88,10 @@ fn main() {
window.rect(200, 230, 80, 80, Color::rgba(100,100,100,100));
//Draw a blured box over window content
window.box_blur(170,100,150,150,10);
window.box_blur(170,100,100,150,10);
//Draw a shadow around a box
window.box_shadow(170,100,150,150,0,0,20, Color::rgba(0,0,0,255));
window.box_shadow(170,100,100,150,0,0,10,0, false, Color::rgba(0,0,0,255));
window.sync();
......
......@@ -26,6 +26,7 @@ pub mod event;
pub mod graphicspath;
pub mod renderer;
mod blur;
mod shadow;
#[derive(Clone, Copy, Debug)]
pub enum WindowFlag {
......
......@@ -9,6 +9,7 @@ use graphicspath::GraphicsPath;
use graphicspath::PointType;
use Mode;
use blur;
use shadow;
#[cfg(target_arch = "x86")]
#[inline(always)]
......@@ -338,44 +339,8 @@ pub trait Renderer {
}
}
fn box_shadow(&mut self, x: i32, y: i32, w: u32, h: u32, offset_x: i32, offset_y: i32, r: i32, color: Color) {
let renderer_w = self.width();
let renderer_h = self.height();
let start_y = cmp::max(0, cmp::min(renderer_h as i32 - 1, y - r));
let end_y = cmp::max(start_y, cmp::min(renderer_h as i32, y + h as i32 + r));
let start_x = cmp::max(0, cmp::min(renderer_w as i32 - 1, x - r));
let end_x = cmp::max(start_x, cmp::min(renderer_w as i32, x + w as i32 + r));
let mut blur_data: Vec<Color> = Vec::new();
for yb in start_y..end_y {
for xb in start_x..end_x {
if xb < x || yb < y || yb >= y + h as i32 || xb >= x + w as i32 {
blur_data.push(Color::rgb(255, 0, 255));
} else {
blur_data.push(Color::rgb(0, 0, 0));
}
}
}
let real_w = end_x - start_x;
let real_h = end_y - start_y;
blur::gauss_blur(&mut blur_data, real_w as u32, real_h as u32, r as f32 / 3.0);
let mut counter: u32 = 0;
for yb in start_y + offset_y..end_y + offset_y {
for xb in start_x + offset_x..end_x + offset_x {
if xb < x || yb < y || yb >= y + h as i32 || xb >= x + w as i32 {
let c = blur_data[counter as usize];
let mut alpha: u8 = if color.a() < 255 - c.r() { color.a() } else { 255 - c.r() };
let col = Color::rgba(color.r(), color.g(), color.b(), alpha);
self.pixel(xb , yb , col);
}
counter = counter + 1;
}
}
fn box_shadow(&mut self, x: i32, y: i32, w: u32, h: u32, offset_x: i32, offset_y: i32, blur_radius: u32, box_radius: u32, invert: bool, color: Color) {
shadow::box_shadow(self, x,y,w,h,offset_x,offset_y,blur_radius,box_radius,invert, color);
}
/// Display an image
......
use Renderer;
use Color;
use blur;
use Mode;
use std::cell::Cell;
#[allow(unused)]
pub fn box_shadow<T: Renderer + ?Sized>(renderer: &mut T, x: i32, y: i32, w: u32, h: u32, offset_x: i32, offset_y: i32, blur_radius: u32, box_radius: u32, invert: bool, color: Color) {
let real_w = w as i32 + (blur_radius * 2) as i32;
let real_h = h as i32 + (blur_radius * 2) as i32;
let mut image_mask = ImageMask::new(real_w as u32, real_h as u32);
image_mask.rounded_rect(blur_radius as i32,blur_radius as i32 ,w,h, box_radius as u32, true, Color::rgb(0,0,0));
let mut blur_data = image_mask.data.clone();
blur::gauss_blur(&mut blur_data, real_w as u32, real_h as u32, blur_radius as f32 / 3.0);
let mut real_start_y = y - blur_radius as i32 + offset_y;
let mut real_start_x = x - blur_radius as i32 + offset_x;
let real_end_y = y + h as i32 + blur_radius as i32 + offset_y;
let real_end_x = x + w as i32 + blur_radius as i32 + offset_x;
for yb in real_start_y .. real_end_y{
for xb in real_start_x .. real_end_x {
let real_x = xb - real_start_x;
let real_y = yb - real_start_y;
let mut draw = true;
if !(xb < x || yb < y || yb >= y + h as i32 || xb >= x + w as i32) {
let data_index = ((real_y + offset_y) * real_w + real_x + offset_x);
if data_index > 0 && data_index < image_mask.data.len() as i32 {
let mask_color = image_mask.data[data_index as usize];
if mask_color.r() == 0 {
draw = false;
}
}
}
if (invert) { draw = !draw; }
if draw {
let data_index = ((real_y) * real_w + real_x);
let c = blur_data[data_index as usize];
let mut alpha: u8 = if color.a() < 255 - c.r() { color.a() } else { 255 - c.r() };
if (invert) { alpha = if color.a() < c.r() { color.a() } else { c.r() }; }
let col = Color::rgba(color.r(), color.g(), color.b(), alpha);
renderer.pixel(xb, yb, col);
}
}
}
}
pub struct ImageMask {
pub width: u32,
pub height: u32,
pub data: Vec<Color>,
mode: Cell<Mode>,
}
impl ImageMask {
pub fn new(width: u32, height: u32) -> Self {
let size: u64 = (width * height) as u64;
ImageMask {
width: width,
height: height,
data: vec![Color::rgb(255,255,255); size as usize],
mode: Cell::new(Mode::Overwrite)
}
}
}
impl Renderer for ImageMask {
/// Get width
fn width(&self) -> u32 {
self.width
}
/// Get height
fn height(&self) -> u32 {
self.height
}
/// Access pixel buffer
fn data(&self) -> &[Color] {
&self.data
}
/// Access pixel buffer mutably
fn data_mut(&mut self) -> &mut [Color] {
&mut self.data
}
/// Flip the window buffer
fn sync(&mut self) -> bool {
true
}
/// Set/get mode
fn mode(&self) -> &Cell<Mode> {
&self.mode
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment