[librsvg] mask: move bit manipulation to the Pixel object
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] mask: move bit manipulation to the Pixel object
- Date: Mon, 31 Dec 2018 23:54:50 +0000 (UTC)
commit 1036f2575fc92b01caf360c2c460edb159b77b62
Author: Paolo Borelli <pborelli gnome org>
Date: Mon Dec 31 18:28:27 2018 +0100
mask: move bit manipulation to the Pixel object
Pixel already encapsulates (un)premultiply etc, so let's keep
all the the bit fiddling in one place.
rsvg_internals/src/mask.rs | 44 ++++-----------------------------
rsvg_internals/src/surface_utils/mod.rs | 33 +++++++++++++++++++++++++
2 files changed, 38 insertions(+), 39 deletions(-)
---
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index aaf04382..7b70b9f2 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -17,8 +17,8 @@ use surface_utils::{
shared_surface::SharedImageSurface,
shared_surface::SurfaceType,
ImageSurfaceDataExt,
- Pixel,
};
+use unit_interval::UnitInterval;
coord_units!(MaskUnits, CoordUnits::ObjectBoundingBox);
coord_units!(MaskContentUnits, CoordUnits::UserSpaceOnUse);
@@ -147,10 +147,7 @@ impl NodeMask {
}
}?;
- let opacity = {
- let Opacity(o) = values.opacity;
- u8::from(o)
- };
+ let Opacity(opacity) = values.opacity;
let mask_surface = compute_luminance_to_alpha(surface, opacity)?;
@@ -173,7 +170,7 @@ impl NodeMask {
// This is to get a mask suitable for use with cairo_mask_surface().
fn compute_luminance_to_alpha(
surface: cairo::ImageSurface,
- opacity: u8,
+ opacity: UnitInterval,
) -> Result<cairo::ImageSurface, cairo::Status> {
let surface = SharedImageSurface::new(surface, SurfaceType::SRgb)?;
@@ -187,46 +184,15 @@ fn compute_luminance_to_alpha(
y1: height,
};
- let opacity = opacity as u32;
-
+ let opacity = u8::from(opacity);
let mut output = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?;
-
let output_stride = output.get_stride() as usize;
{
let mut output_data = output.get_data().unwrap();
for (x, y, pixel) in Pixels::new(&surface, bounds) {
- // Assuming, the pixel is linear RGB (not sRGB)
- // y = luminance
- // Y = 0.2126 R + 0.7152 G + 0.0722 B
- // 1.0 opacity = 255
- //
- // When Y = 1.0, pixel for mask should be 0xFFFFFFFF
- // (you get 1.0 luminance from 255 from R, G and B)
- //
- // r_mult = 0xFFFFFFFF / (255.0 * 255.0) * .2126 = 14042.45 ~= 14042
- // g_mult = 0xFFFFFFFF / (255.0 * 255.0) * .7152 = 47239.69 ~= 47240
- // b_mult = 0xFFFFFFFF / (255.0 * 255.0) * .0722 = 4768.88 ~= 4769
- //
- // This allows for the following expected behaviour:
- // (we only care about the most sig byte)
- // if pixel = 0x00FFFFFF, pixel' = 0xFF......
- // if pixel = 0x00020202, pixel' = 0x02......
- // if pixel = 0x00000000, pixel' = 0x00......
-
- let r = pixel.r as u32;
- let g = pixel.g as u32;
- let b = pixel.b as u32;
-
- let output_pixel = Pixel {
- r: 0,
- g: 0,
- b: 0,
- a: (((r * 14042 + g * 47240 + b * 4769) * opacity) >> 24) as u8,
- };
-
- output_data.set_pixel(output_stride, output_pixel, x, y);
+ output_data.set_pixel(output_stride, pixel.to_mask(opacity), x, y);
}
}
diff --git a/rsvg_internals/src/surface_utils/mod.rs b/rsvg_internals/src/surface_utils/mod.rs
index 06d54a47..00a58306 100644
--- a/rsvg_internals/src/surface_utils/mod.rs
+++ b/rsvg_internals/src/surface_utils/mod.rs
@@ -92,6 +92,39 @@ impl Pixel {
a: ((x >> 24) & 0xFF) as u8,
}
}
+
+ /// Returns a 'mask' pixel with only the alpha channel
+ ///
+ /// Assuming, the pixel is linear RGB (not sRGB)
+ /// y = luminance
+ /// Y = 0.2126 R + 0.7152 G + 0.0722 B
+ /// 1.0 opacity = 255
+ ///
+ /// When Y = 1.0, pixel for mask should be 0xFFFFFFFF
+ /// (you get 1.0 luminance from 255 from R, G and B)
+ ///
+ /// r_mult = 0xFFFFFFFF / (255.0 * 255.0) * .2126 = 14042.45 ~= 14042
+ /// g_mult = 0xFFFFFFFF / (255.0 * 255.0) * .7152 = 47239.69 ~= 47240
+ /// b_mult = 0xFFFFFFFF / (255.0 * 255.0) * .0722 = 4768.88 ~= 4769
+ ///
+ /// This allows for the following expected behaviour:
+ /// (we only care about the most sig byte)
+ /// if pixel = 0x00FFFFFF, pixel' = 0xFF......
+ /// if pixel = 0x00020202, pixel' = 0x02......
+ /// if pixel = 0x00000000, pixel' = 0x00......
+ pub fn to_mask(self, opacity: u8) -> Self {
+ let r = self.r as u32;
+ let g = self.g as u32;
+ let b = self.b as u32;
+ let o = opacity as u32;
+
+ Self {
+ r: 0,
+ g: 0,
+ b: 0,
+ a: (((r * 14042 + g * 47240 + b * 4769) * o) >> 24) as u8,
+ }
+ }
}
impl<'a> ImageSurfaceDataExt for cairo::ImageSurfaceData<'a> {}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]