Logo Search packages:      
Sourcecode: inkscape version File versions

void sp_item_write_transform ( SPItem item,
Inkscape::XML::Node repr,
NR::Matrix const &  transform,
NR::Matrix const *  adv,
bool  compensate 
)

Set a new transform on an object.

Compensate for stroke scaling and gradient/pattern fill transform, if necessary. Call the object's set_transform method if transforms are stored optimized. Send _transformed_signal. Invoke _write method so that the repr is updated with the new transform.

Todo:
FIXME: add the same else branch as for gradients below, to convert patterns to userSpaceOnUse as well recursively compensate gradient fill if it's not to be transformed

Definition at line 1272 of file sp-item.cpp.

References SPItem::_transformed_signal, SPItem::clip_ref, NR::identity(), NR::Matrix::inverse(), NR::Matrix::is_translation(), SPItem::mask_ref, sp_item_adjust_paint_recursive(), sp_item_adjust_rects_recursive(), sp_item_adjust_stroke_width_recursive(), sp_item_set_item_transform(), and sp_item_transform_repr().

{
    g_return_if_fail(item != NULL);
    g_return_if_fail(SP_IS_ITEM(item));
    g_return_if_fail(repr != NULL);

    // calculate the relative transform, if not given by the adv attribute
    NR::Matrix advertized_transform;
    if (adv != NULL) {
        advertized_transform = *adv;
    } else {
        advertized_transform = sp_item_transform_repr (item).inverse() * transform;
    }

    if (compensate) {

         // recursively compensate for stroke scaling, depending on user preference
        if (prefs_get_int_attribute("options.transform", "stroke", 1) == 0) {
            double const expansion = 1. / NR::expansion(advertized_transform);
            sp_item_adjust_stroke_width_recursive(item, expansion);
        }

        // recursively compensate rx/ry of a rect if requested
        if (prefs_get_int_attribute("options.transform", "rectcorners", 1) == 0) {
            sp_item_adjust_rects_recursive(item, advertized_transform);
        }

        // recursively compensate pattern fill if it's not to be transformed
        if (prefs_get_int_attribute("options.transform", "pattern", 1) == 0) {
            sp_item_adjust_paint_recursive (item, advertized_transform.inverse(), NR::identity(), true);
        }
        /// \todo FIXME: add the same else branch as for gradients below, to convert patterns to userSpaceOnUse as well
        /// recursively compensate gradient fill if it's not to be transformed
        if (prefs_get_int_attribute("options.transform", "gradient", 1) == 0) {
            sp_item_adjust_paint_recursive (item, advertized_transform.inverse(), NR::identity(), false);
        } else {
            // this converts the gradient/pattern fill/stroke, if any, to userSpaceOnUse; we need to do
            // it here _before_ the new transform is set, so as to use the pre-transform bbox
            sp_item_adjust_paint_recursive (item, NR::identity(), NR::identity(), false);
        }

    } // endif(compensate)

    gint preserve = prefs_get_int_attribute("options.preservetransform", "value", 0);
    NR::Matrix transform_attr (transform);
    if ( // run the object's set_transform (i.e. embed transform) only if:
         ((SPItemClass *) G_OBJECT_GET_CLASS(item))->set_transform && // it does have a set_transform method
             !preserve && // user did not chose to preserve all transforms
             !item->clip_ref->getObject() && // the object does not have a clippath
             !item->mask_ref->getObject() && // the object does not have a mask
         !(!transform.is_translation() && SP_OBJECT_STYLE(item) && SP_OBJECT_STYLE(item)->getFilter())
             // the object does not have a filter, or the transform is translation (which is supposed to not affect filters)
        ) {
        transform_attr = ((SPItemClass *) G_OBJECT_GET_CLASS(item))->set_transform(item, transform);
    }
    sp_item_set_item_transform(item, transform_attr);

    // Note: updateRepr comes before emitting the transformed signal since
    // it causes clone SPUse's copy of the original object to brought up to
    // date with the original.  Otherwise, sp_use_bbox returns incorrect
    // values if called in code handling the transformed signal.
    SP_OBJECT(item)->updateRepr();

    // send the relative transform with a _transformed_signal
    item->_transformed_signal.emit(&advertized_transform, item);
}


Generated by  Doxygen 1.6.0   Back to index