From 69c27607826558c3fa66850c1c86a1258f4208a0 Mon Sep 17 00:00:00 2001 From: Henry Wong Date: Sun, 5 Oct 2025 20:33:22 -0700 Subject: [PATCH] 3DBox: box3d-tool: Fix transforms when creating new 3dbox objects Set box3d->transform when first creating the 3dbox (drag) and call doWriteTransform when finished. Fixes https://gitlab.com/inkscape/inkscape/-/issues/5950 Also fix scaling of stroke width when resizing objects (both with and without /options/transform/stroke) * Call updateRepr() before adjusting stroke to work around SPStyle::read clearing the new stroke * ObjectSet::applyAffine: Explicitly pass transform to doWriteTransform so sp_item_transform_repr doesn't just cancel out the transform and break adjust_stroke compensation. --- src/object/box3d.cpp | 23 +++++++++++++++-------- src/object/sp-item.cpp | 6 +++++- src/preferences-skeleton.h | 2 +- src/selection-chemistry.cpp | 2 +- src/ui/tools/box3d-tool.cpp | 4 +++- 5 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/object/box3d.cpp b/src/object/box3d.cpp index 90222e010d..59b2493242 100644 --- a/src/object/box3d.cpp +++ b/src/object/box3d.cpp @@ -250,6 +250,18 @@ void SPBox3D::position_set() } } +static void set_transform_box3d_child_item(SPItem *childitem, Geom::Affine const &xform, gdouble scale) +{ + // Adjust stroke width. If stroke-width is unset, SPItem::adjust_stroke will create one (typically with value 1*scale) + childitem->adjust_stroke(scale); + + // Adjust pattern fill + childitem->adjust_pattern(xform); + + // Adjust gradient fill + childitem->adjust_gradient(xform); +} + Geom::Affine SPBox3D::set_transform(Geom::Affine const &xform) { // We don't apply the transform to the box directly but instead to its perspective (which is // done in sp_selection_apply_affine). Here we only adjust strokes, patterns, etc. @@ -257,20 +269,15 @@ Geom::Affine SPBox3D::set_transform(Geom::Affine const &xform) { Geom::Affine ret(Geom::Affine(xform).withoutTranslation()); gdouble const sw = hypot(ret[0], ret[1]); gdouble const sh = hypot(ret[2], ret[3]); + gdouble const scale = sqrt(fabs(sw * sh)); for (auto& child: children) { auto childitem = cast(&child); if (childitem) { - // Adjust stroke width - childitem->adjust_stroke(sqrt(fabs(sw * sh))); - - // Adjust pattern fill - childitem->adjust_pattern(xform); - - // Adjust gradient fill - childitem->adjust_gradient(xform); + set_transform_box3d_child_item(childitem, xform, scale); } } + set_transform_box3d_child_item(this, xform, scale); return Geom::identity(); } diff --git a/src/object/sp-item.cpp b/src/object/sp-item.cpp index 36e91b8383..22f30c8e5c 100644 --- a/src/object/sp-item.cpp +++ b/src/object/sp-item.cpp @@ -1482,10 +1482,14 @@ void SPItem::adjust_stroke( gdouble ex ) if (freeze_stroke_width) { return; } - SPStyle *style = this->style; if (style && !Geom::are_near(ex, 1.0, Geom::EPSILON) && !style->stroke_extensions.hairline) { + + // If there are any pending attribute updates, SPStyle::read overwrites the new stroke_width when + // updateRepr applies those other attributes. Write out any pending updates before adjusting stroke. + updateRepr(); + style->stroke_width.computed *= ex; style->stroke_width.set = TRUE; diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index b1914f38be..470c3f84d9 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -78,7 +78,7 @@ static char const preferences_skeleton[] = - + diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 2c7e432b13..36ac69704c 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -1808,7 +1808,7 @@ void ObjectSet::applyAffine(Geom::Affine const &affine, bool set_i2d, bool compe if (set_i2d) { item->set_i2d_affine(item->i2dt_affine() * (Geom::Affine)affine); } - item->doWriteTransform(item->transform, nullptr, compensate); + item->doWriteTransform(item->transform, &item->transform, compensate); } if (adjust_transf_center) { // The transformation center should not be touched in case of pasting or importing, which is allowed by this if clause diff --git a/src/ui/tools/box3d-tool.cpp b/src/ui/tools/box3d-tool.cpp index 2c9f2b4794..8f075c70f0 100644 --- a/src/ui/tools/box3d-tool.cpp +++ b/src/ui/tools/box3d-tool.cpp @@ -429,7 +429,7 @@ void Box3dTool::drag() // Create object auto newbox3d = SPBox3D::createBox3D(currentLayer()); - // Set style + // Set group style. This style isn't visible, since only the faces are visible. _desktop->applyCurrentOrToolStyle(newbox3d, "/tools/shapes/3dbox", false); box3d = newbox3d; @@ -455,6 +455,7 @@ void Box3dTool::drag() side->updateRepr(); // calls Box3DSide::write() and updates, e.g., the axes string description } + box3d->transform = currentLayer()->i2doc_affine().inverse(); box3d->set_z_orders(); box3d->updateRepr(); @@ -502,6 +503,7 @@ void Box3dTool::finishItem() box3d->orig_corner7 = drag_ptC_proj; box3d->updateRepr(); + box3d->doWriteTransform(box3d->transform, nullptr, true); box3d->relabel_corners(); -- GitLab