[librsvg: 1/4] compute_luminance_to_alpha(): Take ownership of the surface; return it again
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/4] compute_luminance_to_alpha(): Take ownership of the surface; return it again
- Date: Thu, 30 Aug 2018 17:41:59 +0000 (UTC)
commit 7f64d49f22f0db2e8b4e2f9f273c280303b8d5e3
Author: Federico Mena Quintero <federico gnome org>
Date: Thu Aug 30 09:44:51 2018 -0500
compute_luminance_to_alpha(): Take ownership of the surface; return it again
rsvg_internals/src/mask.rs | 84 +++++++++++++++++++++++++++-------------------
1 file changed, 49 insertions(+), 35 deletions(-)
---
diff --git a/rsvg_internals/src/mask.rs b/rsvg_internals/src/mask.rs
index cb5ab7e8..42182f2b 100644
--- a/rsvg_internals/src/mask.rs
+++ b/rsvg_internals/src/mask.rs
@@ -70,7 +70,7 @@ impl NodeMask {
let width = draw_ctx.get_width() as i32;
let height = draw_ctx.get_height() as i32;
- let mut surface = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?;
+ let surface = cairo::ImageSurface::create(cairo::Format::ARgb32, width, height)?;
let mask_units = CoordUnits::from(self.units.get());
let content_units = CoordUnits::from(self.content_units.get());
@@ -148,52 +148,66 @@ impl NodeMask {
res
}?;
- {
- let rowstride = surface.get_stride() as usize;
- let mut pixels = surface.get_data().unwrap();
- let opacity = {
- let Opacity(o) = values.opacity;
- u8::from(o)
- };
+ let opacity = {
+ let Opacity(o) = values.opacity;
+ u8::from(o)
+ };
- for row in pixels.chunks_mut(rowstride) {
- for p in row[..4 * width as usize].chunks_mut(4) {
- // 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......
- //
- // NOTE: the following assumes little-endian
- let (r, g, b, o) = (p[2] as u32, p[1] as u32, p[0] as u32, opacity as u32);
- p[3] = (((r * 14042 + g * 47240 + b * 4769) * o) >> 24) as u8;
- }
- }
- }
+ let mask_surface = compute_luminance_to_alpha(surface, opacity);
let cr = draw_ctx.get_cairo_context();
cr.identity_matrix();
let (xofs, yofs) = draw_ctx.get_offset();
- cairo_mask_surface(&cr, &surface, xofs, yofs);
+ cairo_mask_surface(&cr, &mask_surface, xofs, yofs);
Ok(())
}
}
+// Takes a surface and overwrites the alpha channel of each pixel
+// with the luminance of that pixel's RGB values.
+fn compute_luminance_to_alpha(
+ mut surface: cairo::ImageSurface,
+ opacity: u8,
+) -> cairo::ImageSurface {
+ let width = surface.get_width();
+ let rowstride = surface.get_stride() as usize;
+
+ {
+ let mut pixels = surface.get_data().unwrap();
+
+ for row in pixels.chunks_mut(rowstride) {
+ for p in row[..4 * width as usize].chunks_mut(4) {
+ // 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......
+ //
+ // NOTE: the following assumes little-endian
+ let (r, g, b, o) = (p[2] as u32, p[1] as u32, p[0] as u32, opacity as u32);
+ p[3] = (((r * 14042 + g * 47240 + b * 4769) * o) >> 24) as u8;
+ }
+ }
+ }
+
+ surface
+}
+
impl NodeTrait for NodeMask {
fn set_atts(&self, _: &RsvgNode, _: *const RsvgHandle, pbag: &PropertyBag) -> NodeResult {
for (_key, attr, value) in pbag.iter() {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]