From 24dc00068cd48903bdaf7a4202c95daccc3fcb93 Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Mon, 25 Feb 2019 22:45:16 -0600 Subject: [PATCH] Bug 1505871. Implement yaml reader/writer for component transfer. r=jrmuizel --- gfx/wr/wrench/src/yaml_frame_reader.rs | 2 + gfx/wr/wrench/src/yaml_frame_writer.rs | 46 ++++++++++++++++++ gfx/wr/wrench/src/yaml_helper.rs | 64 ++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/gfx/wr/wrench/src/yaml_frame_reader.rs b/gfx/wr/wrench/src/yaml_frame_reader.rs index 0320cb1f01ba..82084dc7a057 100644 --- a/gfx/wr/wrench/src/yaml_frame_reader.rs +++ b/gfx/wr/wrench/src/yaml_frame_reader.rs @@ -1825,6 +1825,7 @@ impl YamlFrameReader { } let filters = yaml["filters"].as_vec_filter_op().unwrap_or(vec![]); + let filter_datas = yaml["filter-datas"].as_vec_filter_data().unwrap_or(vec![]); info.rect = bounds; info.clip_rect = bounds; @@ -1836,6 +1837,7 @@ impl YamlFrameReader { transform_style, mix_blend_mode, &filters, + &filter_datas, raster_space, cache_tiles, ); diff --git a/gfx/wr/wrench/src/yaml_frame_writer.rs b/gfx/wr/wrench/src/yaml_frame_writer.rs index 054a13ed86f7..e164737c6d2d 100644 --- a/gfx/wr/wrench/src/yaml_frame_writer.rs +++ b/gfx/wr/wrench/src/yaml_frame_writer.rs @@ -217,6 +217,8 @@ fn write_stacking_context( sc: &StackingContext, properties: &SceneProperties, filter_iter: AuxIter, + filter_data_iter: &[TempFilterData], + display_list: &BuiltDisplayList, ) { enum_node(parent, "transform-style", sc.transform_style); @@ -266,10 +268,50 @@ fn write_stacking_context( FilterOp::LinearToSrgb => { filters.push(Yaml::String("linear-to-srgb".to_string())) } + FilterOp::ComponentTransfer => { + filters.push(Yaml::String("component-transfer".to_string())) + } } } yaml_node(parent, "filters", Yaml::Array(filters)); + + // filter datas + let mut filter_datas = vec![]; + for filter_data in filter_data_iter { + let func_types = display_list.get(filter_data.func_types).map(|func_type| { + match func_type { + ComponentTransferFuncType::Identity => { Yaml::String("Identity".to_string()) } + ComponentTransferFuncType::Table => { Yaml::String("Table".to_string()) } + ComponentTransferFuncType::Discrete => { Yaml::String("Discrete".to_string()) } + ComponentTransferFuncType::Linear => { Yaml::String("Linear".to_string()) } + ComponentTransferFuncType::Gamma => { Yaml::String("Gamma".to_string()) } + } + }).collect(); + let r_values = display_list.get(filter_data.r_values).map(|value| { + Yaml::String(format!("{}", value)) + }).collect(); + let g_values = display_list.get(filter_data.g_values).map(|value| { + Yaml::String(format!("{}", value)) + }).collect(); + let b_values = display_list.get(filter_data.b_values).map(|value| { + Yaml::String(format!("{}", value)) + }).collect(); + let a_values = display_list.get(filter_data.a_values).map(|value| { + Yaml::String(format!("{}", value)) + }).collect(); + + let avec: Vec = [ + Yaml::Array(func_types), + Yaml::Array(r_values), + Yaml::Array(g_values), + Yaml::Array(b_values), + Yaml::Array(a_values), + ].to_vec(); + filter_datas.push(Yaml::Array(avec)); + } + + yaml_node(parent, "filter-datas", Yaml::Array(filter_datas)); } #[cfg(target_os = "macos")] @@ -1034,6 +1076,8 @@ impl YamlFrameWriter { &item.stacking_context, &scene.properties, filters, + base.filter_datas(), + display_list, ); let mut sub_iter = base.sub_iter(); @@ -1152,6 +1196,8 @@ impl YamlFrameWriter { } Sdi::SetGradientStops => panic!("dummy item yielded?"), + Sdi::SetFilterOps => panic!("dummy item yielded?"), + Sdi::SetFilterData => panic!("dummy item yielded?"), Sdi::PushShadow(shadow) => { str_node(&mut v, "type", "shadow"); vector_node(&mut v, "offset", &shadow.offset); diff --git a/gfx/wr/wrench/src/yaml_helper.rs b/gfx/wr/wrench/src/yaml_helper.rs index e94628abcd43..c42010333078 100644 --- a/gfx/wr/wrench/src/yaml_helper.rs +++ b/gfx/wr/wrench/src/yaml_helper.rs @@ -36,6 +36,8 @@ pub trait YamlHelper { fn as_mix_blend_mode(&self) -> Option; fn as_filter_op(&self) -> Option; fn as_vec_filter_op(&self) -> Option>; + fn as_filter_data(&self) -> Option; + fn as_vec_filter_data(&self) -> Option>; } fn string_to_color(color: &str) -> Option { @@ -139,6 +141,17 @@ define_string_enum!( define_string_enum!(ClipMode, [Clip = "clip", ClipOut = "clip-out"]); +define_string_enum!( + ComponentTransferFuncType, + [ + Identity = "Identity", + Table = "Table", + Discrete = "Discrete", + Linear = "Linear", + Gamma = "Gamma" + ] +); + // Rotate around `axis` by `degrees` angle fn make_rotation( origin: &LayoutPoint, @@ -548,6 +561,9 @@ impl YamlHelper for Yaml { ("identity", _, _) => { Some(FilterOp::Identity) } + ("component-transfer", _, _) => { + Some(FilterOp::ComponentTransfer) + } ("blur", ref args, _) if args.len() == 1 => { Some(FilterOp::Blur(args[0].parse().unwrap())) } @@ -606,4 +622,52 @@ impl YamlHelper for Yaml { self.as_filter_op().map(|op| vec![op]) } } + + fn as_filter_data(&self) -> Option { + // Parse an array with five entries. First entry is an array of func types (4). + // The remaining entries are arrays of floats. + if let Yaml::Array(ref array) = *self { + if array.len() != 5 { + panic!("Invalid filter data specified, base array doesn't have five entries: {:?}", self); + } + if let Some(func_types_p) = array[0].as_vec_string() { + if func_types_p.len() != 4 { + panic!("Invalid filter data specified, func type array doesn't have five entries: {:?}", self); + } + let func_types: Vec = + func_types_p.into_iter().map(|x| { match StringEnum::from_str(&x) { + Some(y) => y, + None => panic!("Invalid filter data specified, invalid func type name: {:?}", self), + }}).collect(); + if let Some(r_values_p) = array[1].as_vec_f32() { + if let Some(g_values_p) = array[2].as_vec_f32() { + if let Some(b_values_p) = array[3].as_vec_f32() { + if let Some(a_values_p) = array[4].as_vec_f32() { + let filter_data = FilterData { + func_r_type: func_types[0], + r_values: r_values_p, + func_g_type: func_types[1], + g_values: g_values_p, + func_b_type: func_types[2], + b_values: b_values_p, + func_a_type: func_types[3], + a_values: a_values_p, + }; + return Some(filter_data) + } + } + } + } + } + } + None + } + + fn as_vec_filter_data(&self) -> Option> { + if let Some(v) = self.as_vec() { + Some(v.iter().map(|x| x.as_filter_data().unwrap()).collect()) + } else { + self.as_filter_data().map(|data| vec![data]) + } + } }