mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-14 14:22:39 +00:00
Use shared IDML transparency settings model
This commit is contained in:
4 files changed
+47
-58
No files matched your search
Generated
+10
-10
@@ -1242,10 +1242,10 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-idml"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=1e5fdfdd2#1e5fdfdd2b5294d9781fa2257c3d6287af3cd2a2"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=598a1e5b9#598a1e5b92e03b19115bd3012cbd4dce98267e13"
|
||||
dependencies = [
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e5fdfdd2)",
|
||||
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e5fdfdd2)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=598a1e5b9)",
|
||||
"craft-zip 0.1.0 (git+https://github.com/storytold/craft-libs?rev=598a1e5b9)",
|
||||
"thiserror 2.0.21",
|
||||
]
|
||||
|
||||
@@ -1647,7 +1647,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-xml"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=1e5fdfdd2#1e5fdfdd2b5294d9781fa2257c3d6287af3cd2a2"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=40525913633942f84b06d4837a8d90534a55d63f#40525913633942f84b06d4837a8d90534a55d63f"
|
||||
dependencies = [
|
||||
"quick-xml 0.41.0",
|
||||
"thiserror 2.0.21",
|
||||
@@ -1656,7 +1656,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-xml"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=40525913633942f84b06d4837a8d90534a55d63f#40525913633942f84b06d4837a8d90534a55d63f"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=598a1e5b9#598a1e5b92e03b19115bd3012cbd4dce98267e13"
|
||||
dependencies = [
|
||||
"quick-xml 0.41.0",
|
||||
"thiserror 2.0.21",
|
||||
@@ -1730,7 +1730,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "craft-zip"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=1e5fdfdd2#1e5fdfdd2b5294d9781fa2257c3d6287af3cd2a2"
|
||||
source = "git+https://github.com/storytold/craft-libs?rev=598a1e5b9#598a1e5b92e03b19115bd3012cbd4dce98267e13"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"thiserror 2.0.21",
|
||||
@@ -2021,7 +2021,7 @@ dependencies = [
|
||||
"craft-prepress",
|
||||
"craft-print",
|
||||
"craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cc23ffd4d26f3074808e2187d332564817624f8f)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e5fdfdd2)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=598a1e5b9)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=f23b0f33f0d00b157476533a43cbbcfd901aa1f1)",
|
||||
"designcraft-color",
|
||||
"designcraft-compose",
|
||||
@@ -2103,9 +2103,9 @@ name = "designcraft-idml"
|
||||
version = "0.20.1"
|
||||
dependencies = [
|
||||
"craft-file-formats",
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e5fdfdd2)",
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=598a1e5b9)",
|
||||
"craft-svg 0.1.0 (git+https://github.com/storytold/craft-libs?rev=cc23ffd4d26f3074808e2187d332564817624f8f)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e5fdfdd2)",
|
||||
"craft-xml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=598a1e5b9)",
|
||||
"designcraft-color",
|
||||
"designcraft-compose",
|
||||
"designcraft-doc",
|
||||
@@ -2222,7 +2222,7 @@ version = "0.20.1"
|
||||
dependencies = [
|
||||
"craft-docx",
|
||||
"craft-file-formats",
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=1e5fdfdd2)",
|
||||
"craft-idml 0.1.0 (git+https://github.com/storytold/craft-libs?rev=598a1e5b9)",
|
||||
"craft-rtf",
|
||||
"craft-wordmodel",
|
||||
"craft-xlsx",
|
||||
|
||||
+2
-2
@@ -16,10 +16,10 @@ craft-pdf = { git = "https://github.com/storytold/craft-libs", rev = "4052591363
|
||||
craft-designcraft-format = { git = "https://github.com/storytold/craft-libs", rev = "19692b6190465671e41967c75d0cd4c439d0c84c", version = "=0.1.0" }
|
||||
craft-eps = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" }
|
||||
craft-epub = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" }
|
||||
craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "1e5fdfdd2", version = "=0.1.0" }
|
||||
craft-idml = { git = "https://github.com/storytold/craft-libs", rev = "598a1e5b9", version = "=0.1.0" }
|
||||
craft-indd = { git = "https://github.com/storytold/craft-libs", rev = "47bf5650b0d503b97bfb5e841746c4957897d11f", version = "=0.1.0" }
|
||||
craft-svg = { git = "https://github.com/storytold/craft-libs", rev = "cc23ffd4d26f3074808e2187d332564817624f8f", version = "=0.1.0", features = ["tree-render", "tree-text"] }
|
||||
craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "1e5fdfdd2", version = "=0.1.0" }
|
||||
craft-xml = { git = "https://github.com/storytold/craft-libs", rev = "598a1e5b9", version = "=0.1.0" }
|
||||
craft-xml-dtd = { package = "craft-xml", git = "https://github.com/storytold/craft-libs", rev = "f23b0f33f0d00b157476533a43cbbcfd901aa1f1", version = "=0.1.0" }
|
||||
craft-rtf = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" }
|
||||
craft-xlsx = { git = "https://github.com/storytold/craft-libs", rev = "ba24fe2435adb3c81ad6057faf36365fbba736cf", version = "=0.1.0" }
|
||||
|
||||
@@ -97,15 +97,14 @@ impl<'r> Importer<'r> {
|
||||
}
|
||||
// Transparency.
|
||||
if let Some(t) = self.with_style(e, "TransparencySetting") {
|
||||
if let Some(bs) = t.find("BlendingSetting") {
|
||||
if let Some(o) = bs.num("Opacity") {
|
||||
it.opacity = (o / 100.0).clamp(0.0, 1.0) as f32;
|
||||
}
|
||||
if let Some(m) = bs.get("BlendMode") {
|
||||
it.blend = names::blend_in(m);
|
||||
}
|
||||
let settings = craft_idml::model::TransparencySetting::from_el(&crate::xml::to_craft(&t));
|
||||
if let Some(o) = settings.opacity {
|
||||
it.opacity = (o / 100.0).clamp(0.0, 1.0) as f32;
|
||||
}
|
||||
self.effects_in(&t, &mut it.effects);
|
||||
if let Some(m) = settings.blend_mode.as_deref() {
|
||||
it.blend = names::blend_in(m);
|
||||
}
|
||||
self.effects_from_model(&settings, &mut it.effects);
|
||||
}
|
||||
// Text wrap.
|
||||
if let Some(w) = self.with_style(e, "TextWrapPreference") {
|
||||
|
||||
@@ -96,47 +96,44 @@ impl<'r> Importer<'r> {
|
||||
/// Reads the drop shadow, feather, gradient feather and directional feather of a
|
||||
/// `TransparencySetting` into `fx`.
|
||||
pub(super) fn effects_in(&mut self, t: &El, fx: &mut Effects) {
|
||||
if let Some(ds) = t.find("DropShadowSetting")
|
||||
&& ds.get("Mode") == Some("Drop")
|
||||
{
|
||||
let x = ds.num("XOffset").unwrap_or(4.95);
|
||||
let y = ds.num("YOffset").unwrap_or(4.95);
|
||||
let settings = craft_idml::model::TransparencySetting::from_el(&crate::xml::to_craft(t));
|
||||
self.effects_from_model(&settings, fx);
|
||||
}
|
||||
|
||||
pub(super) fn effects_from_model(&mut self, settings: &craft_idml::model::TransparencySetting, fx: &mut Effects) {
|
||||
if let Some(ds) = settings.drop_shadow.as_ref().filter(|ds| ds.mode.as_deref() == Some("Drop")) {
|
||||
let x = ds.x_offset.unwrap_or(4.95);
|
||||
let y = ds.y_offset.unwrap_or(4.95);
|
||||
let def = DropShadow::default();
|
||||
fx.drop_shadow = DropShadow {
|
||||
on: true,
|
||||
color: ds.get("EffectColor").map(|c| self.swatch_ref(c)).unwrap_or(def.color),
|
||||
opacity: ds.num("Opacity").map(|o| (o / 100.0) as f32).unwrap_or(def.opacity),
|
||||
color: ds.color.as_deref().map(|c| self.swatch_ref(c)).unwrap_or(def.color),
|
||||
opacity: ds.opacity.map(|o| (o / 100.0) as f32).unwrap_or(def.opacity),
|
||||
angle: names_angle(x, y),
|
||||
distance: x.hypot(y),
|
||||
size: ds.num("Size").unwrap_or(def.size),
|
||||
spread: ds.num("Spread").unwrap_or(def.spread),
|
||||
size: ds.size.unwrap_or(def.size),
|
||||
spread: ds.spread.unwrap_or(def.spread),
|
||||
global_light: false,
|
||||
// Without the attribute (earlier DesignCraft exports) the shadow stays Normal, as it
|
||||
// rendered then; a new shadow's default is Multiply.
|
||||
mode: ds.get("BlendMode").map_or(designcraft_color::BlendMode::Normal, names::blend_in),
|
||||
mode: ds.blend_mode.as_deref().map_or(designcraft_color::BlendMode::Normal, names::blend_in),
|
||||
};
|
||||
}
|
||||
if let Some(f) = t.find("FeatherSetting")
|
||||
&& f.get("Mode").is_some_and(|m| m != "None")
|
||||
{
|
||||
fx.feather = f.num("Width").unwrap_or(9.0);
|
||||
fx.feather_options.choke = finite(f.num("ChokeAmount")).unwrap_or(0.0).clamp(0.0, 100.0);
|
||||
fx.feather_options.corners = match f.get("CornerType") {
|
||||
if let Some(f) = settings.feather.as_ref().filter(|f| f.mode.as_deref().is_some_and(|m| m != "None")) {
|
||||
fx.feather = f.width.unwrap_or(9.0);
|
||||
fx.feather_options.choke = finite(f.choke_amount).unwrap_or(0.0).clamp(0.0, 100.0);
|
||||
fx.feather_options.corners = match f.corner_type.as_deref() {
|
||||
Some("Sharp") => designcraft_doc::FeatherCorners::Sharp,
|
||||
Some("Rounded") => designcraft_doc::FeatherCorners::Rounded,
|
||||
_ => designcraft_doc::FeatherCorners::Diffused,
|
||||
};
|
||||
}
|
||||
if let Some(g) = t.find("GradientFeatherSetting")
|
||||
&& g.boolean("Applied") == Some(true)
|
||||
{
|
||||
if let Some(g) = settings.gradient_feather.as_ref().filter(|g| g.applied) {
|
||||
fx.gradient_feather = gradient_feather_in(g);
|
||||
}
|
||||
if let Some(df) = t.find("DirectionalFeatherSetting")
|
||||
&& df.boolean("Applied") == Some(true)
|
||||
{
|
||||
let w = |k: &str| finite(df.num(k)).unwrap_or(0.0).max(0.0);
|
||||
fx.directional_feather = DirectionalFeather { on: true, widths: [w("TopWidth"), w("LeftWidth"), w("BottomWidth"), w("RightWidth")] };
|
||||
if let Some(df) = settings.directional_feather.as_ref().filter(|df| df.applied) {
|
||||
let w = |value| finite(value).unwrap_or(0.0).max(0.0);
|
||||
fx.directional_feather = DirectionalFeather { on: true, widths: df.widths.map(w) };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,33 +283,26 @@ fn overlay(base: &mut El, top: &El, depth: usize) {
|
||||
/// A `GradientFeatherSetting`. The model holds two opacity stops at the ends of the gradient: the
|
||||
/// first and last `OpacityGradientStop` give them; with a linear vector, their `Location`s move its
|
||||
/// ends.
|
||||
fn gradient_feather_in(g: &El) -> GradientFeather {
|
||||
fn gradient_feather_in(g: &craft_idml::model::GradientFeatherValues) -> GradientFeather {
|
||||
let def = GradientFeather::default();
|
||||
let angle = finite(g.num("Angle")).unwrap_or(0.0);
|
||||
let mut stops: Vec<(f64, f64)> = g
|
||||
.find_all("OpacityGradientStop")
|
||||
.filter_map(|s| Some((finite(s.num("Location"))?.clamp(0.0, 100.0) / 100.0, finite(s.num("Opacity"))?.clamp(0.0, 100.0) / 100.0)))
|
||||
.collect();
|
||||
let angle = finite(g.angle).unwrap_or(0.0);
|
||||
let mut stops: Vec<(f64, f64)> =
|
||||
g.stops.iter().filter_map(|s| Some((finite(s.location)?.clamp(0.0, 100.0) / 100.0, finite(s.opacity)?.clamp(0.0, 100.0) / 100.0))).collect();
|
||||
stops.sort_by(|a, b| a.0.total_cmp(&b.0));
|
||||
let (first, last) = match (stops.first(), stops.last()) {
|
||||
(Some(&a), Some(&b)) => (a, b),
|
||||
_ => ((0.0, def.start as f64), (1.0, def.end as f64)),
|
||||
};
|
||||
let start: Option<[f64; 2]> = g
|
||||
.prop("GradientStart")
|
||||
.and_then(|s| s.split_whitespace().map(|v| v.parse().ok().filter(|v: &f64| v.is_finite())).collect::<Option<Vec<f64>>>())
|
||||
.and_then(|v| v.try_into().ok());
|
||||
let radial = g.get("Type") == Some("Radial");
|
||||
let vector = match (start, finite(g.num("Length"))) {
|
||||
let vector = match (g.start, finite(g.length)) {
|
||||
(Some([x, y]), Some(len)) if len > 0.0 => {
|
||||
let a = angle.to_radians();
|
||||
let (dx, dy) = (len * a.cos(), -len * a.sin());
|
||||
let (l0, l1) = if !radial && last.0 > first.0 { (first.0, last.0) } else { (0.0, 1.0) };
|
||||
let (l0, l1) = if !g.radial && last.0 > first.0 { (first.0, last.0) } else { (0.0, 1.0) };
|
||||
Some([x + dx * l0, y + dy * l0, x + dx * l1, y + dy * l1])
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
GradientFeather { on: true, radial, angle, start: first.1 as f32, end: last.1 as f32, vector }
|
||||
GradientFeather { on: true, radial: g.radial, angle, start: first.1 as f32, end: last.1 as f32, vector }
|
||||
}
|
||||
|
||||
fn names_angle(x: f64, y: f64) -> f64 {
|
||||
|
||||
Reference in new issue
Block a user