[librsvg] mask: move bit manipulation to the Pixel object



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]