Logo Search packages:      
Sourcecode: inkscape version File versions

void sp_style_merge_from_parent ( SPStyle *const   style,
SPStyle const *const   parent 
)

Sets computed values in style, which may involve inheriting from (or in some other way calculating from) corresponding computed values of parent.

References: http://www.w3.org/TR/SVG11/propidx.html shows what properties inherit by default. http://www.w3.org/TR/SVG11/styling.html#Inheritance gives general rules as to what it means to inherit a value. http://www.w3.org/TR/REC-CSS2/cascade.html#computed-value is more precise about what the computed value is (not obvious for lengths).

Precondition:
parent's computed values are already up-to-date.

Todo:
fixme: Check for existing callers that might pass null parent. This should probably be g_return_if_fail, or else we should make a best attempt to set computed values correctly without having a parent (i.e., by assuming parent has initial values).

Todo:
fixme: This is unconditional, i.e., happens even if parent not present.

Todo:
This code looks wrong. Why does the logic differ from the above properties? Similarly dashoffset below.

Definition at line 1320 of file style.cpp.

References SPITextDecoration::blink, SPStyle::block_progression, SPStyle::color, SPIFontSize::computed, SPILengthOrNormal::computed, SPILength::computed, SPIEnum::computed, SPIPaint::currentcolor, NRVpathDash::dash, SPStyle::direction, SPStyle::enable_background, SPStyle::fill, SPStyle::fill_opacity, SPStyle::fill_rule, SPStyle::filter, SPTextStyle::font_family, SPStyle::font_size, SPTextStyle::font_specification, SPStyle::font_stretch, SPStyle::font_style, SPStyle::font_variant, SPStyle::font_weight, SPIFilter::inherit, SPIString::inherit, SPIFloat::inherit, SPIPaint::inherit, SPIScale24::inherit, SPILengthOrNormal::inherit, SPITextDecoration::inherit, SPILength::inherit, SPIEnum::inherit, SPStyle::letter_spacing, SPStyle::line_height, SPITextDecoration::line_through, SPStyle::marker, NRVpathDash::n_dash, SPILengthOrNormal::normal, NRVpathDash::offset, SPStyle::opacity, SPITextDecoration::overline, SPIString::set, SPIFloat::set, SPIScale24::set, SPIPaint::set, SPILengthOrNormal::set, SPITextDecoration::set, SPILength::set, SPIEnum::set, sp_style_merge_font_size_from_parent(), sp_style_merge_ifilter(), SPStyle::stroke, SPStyle::stroke_dash, SPStyle::stroke_dasharray_set, SPStyle::stroke_dashoffset_set, SPStyle::stroke_linecap, SPStyle::stroke_linejoin, SPStyle::stroke_miterlimit, SPStyle::stroke_opacity, SPStyle::stroke_width, SPStyle::text, SPStyle::text_align, SPStyle::text_anchor, SPStyle::text_decoration, SPStyle::text_indent, SPStyle::text_transform, SPITextDecoration::underline, SPILength::unit, SPIString::value, SPIFloat::value, SPILength::value, SPIScale24::value, SPIEnum::value, SPStyle::word_spacing, and SPStyle::writing_mode.

Referenced by sp_style_read(), sp_tref_convert_to_tspan(), and SPObject::updateDisplay().

{
    g_return_if_fail(style != NULL);

    /** \todo
     * fixme: Check for existing callers that might pass null parent.
     * This should probably be g_return_if_fail, or else we should make a
     * best attempt to set computed values correctly without having a parent
     * (i.e., by assuming parent has initial values).
     */
    if (!parent)
        return;

    /* CSS2 */
    /* Font */
    sp_style_merge_font_size_from_parent(style->font_size, parent->font_size);

    /* 'font-style' */
    if (!style->font_style.set || style->font_style.inherit) {
        style->font_style.computed = parent->font_style.computed;
    }

    /* 'font-variant' */
    if (!style->font_variant.set || style->font_variant.inherit) {
        style->font_variant.computed = parent->font_variant.computed;
    }

    /* 'font-weight' */
    if (!style->font_weight.set || style->font_weight.inherit) {
        style->font_weight.computed = parent->font_weight.computed;
    } else if (style->font_weight.value == SP_CSS_FONT_WEIGHT_NORMAL) {
        /** \todo
         * fixme: This is unconditional, i.e., happens even if parent not
         * present.
         */
        style->font_weight.computed = SP_CSS_FONT_WEIGHT_400;
    } else if (style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLD) {
        style->font_weight.computed = SP_CSS_FONT_WEIGHT_700;
    } else if (style->font_weight.value == SP_CSS_FONT_WEIGHT_LIGHTER) {
        unsigned const parent_val = parent->font_weight.computed;
        g_assert(SP_CSS_FONT_WEIGHT_100 == 0);
        // strictly, 'bolder' and 'lighter' should go to the next weight
        // expressible in the current font family, but that's difficult to
        // find out, so jumping by 3 seems an appropriate approximation
        style->font_weight.computed = (parent_val <= SP_CSS_FONT_WEIGHT_100 + 3
                                       ? (unsigned)SP_CSS_FONT_WEIGHT_100
                                       : parent_val - 3);
        g_assert(style->font_weight.computed <= (unsigned) SP_CSS_FONT_WEIGHT_900);
    } else if (style->font_weight.value == SP_CSS_FONT_WEIGHT_BOLDER) {
        unsigned const parent_val = parent->font_weight.computed;
        g_assert(parent_val <= SP_CSS_FONT_WEIGHT_900);
        style->font_weight.computed = (parent_val >= SP_CSS_FONT_WEIGHT_900 - 3
                                       ? (unsigned)SP_CSS_FONT_WEIGHT_900
                                       : parent_val + 3);
        g_assert(style->font_weight.computed <= (unsigned) SP_CSS_FONT_WEIGHT_900);
    }

    /* 'font-stretch' */
    if (!style->font_stretch.set || style->font_stretch.inherit) {
        style->font_stretch.computed = parent->font_stretch.computed;
    } else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_NARROWER) {
        unsigned const parent_val = parent->font_stretch.computed;
        style->font_stretch.computed = (parent_val == SP_CSS_FONT_STRETCH_ULTRA_CONDENSED
                                        ? parent_val
                                        : parent_val - 1);
        g_assert(style->font_stretch.computed <= (unsigned) SP_CSS_FONT_STRETCH_ULTRA_EXPANDED);
    } else if (style->font_stretch.value == SP_CSS_FONT_STRETCH_WIDER) {
        unsigned const parent_val = parent->font_stretch.computed;
        g_assert(parent_val <= SP_CSS_FONT_STRETCH_ULTRA_EXPANDED);
        style->font_stretch.computed = (parent_val == SP_CSS_FONT_STRETCH_ULTRA_EXPANDED
                                        ? parent_val
                                        : parent_val + 1);
        g_assert(style->font_stretch.computed <= (unsigned) SP_CSS_FONT_STRETCH_ULTRA_EXPANDED);
    }

    /* text (css2) */
    if (!style->text_indent.set || style->text_indent.inherit) {
        style->text_indent.computed = parent->text_indent.computed;
    }

    if (!style->text_align.set || style->text_align.inherit) {
        style->text_align.computed = parent->text_align.computed;
    }

    if (!style->text_decoration.set || style->text_decoration.inherit) {
        style->text_decoration.underline = parent->text_decoration.underline;
        style->text_decoration.overline = parent->text_decoration.overline;
        style->text_decoration.line_through = parent->text_decoration.line_through;
        style->text_decoration.blink = parent->text_decoration.blink;
    }

    if (!style->line_height.set || style->line_height.inherit) {
        style->line_height.computed = parent->line_height.computed;
        style->line_height.normal = parent->line_height.normal;
    }

    if (!style->letter_spacing.set || style->letter_spacing.inherit) {
        style->letter_spacing.computed = parent->letter_spacing.computed;
        style->letter_spacing.normal = parent->letter_spacing.normal;
    }

    if (!style->word_spacing.set || style->word_spacing.inherit) {
        style->word_spacing.computed = parent->word_spacing.computed;
        style->word_spacing.normal = parent->word_spacing.normal;
    }

    if (!style->text_transform.set || style->text_transform.inherit) {
        style->text_transform.computed = parent->text_transform.computed;
    }

    if (!style->direction.set || style->direction.inherit) {
        style->direction.computed = parent->direction.computed;
    }

    if (!style->block_progression.set || style->block_progression.inherit) {
        style->block_progression.computed = parent->block_progression.computed;
    }

    if (!style->writing_mode.set || style->writing_mode.inherit) {
        style->writing_mode.computed = parent->writing_mode.computed;
    }

    if (!style->text_anchor.set || style->text_anchor.inherit) {
        style->text_anchor.computed = parent->text_anchor.computed;
    }

    if (style->opacity.inherit) {
        style->opacity.value = parent->opacity.value;
    }

    /* Color */
    if (!style->color.set || style->color.inherit) {
        sp_style_merge_ipaint(style, &style->color, &parent->color);
    }

    /* Fill */
    if (!style->fill.set || style->fill.inherit || style->fill.currentcolor) {
        sp_style_merge_ipaint(style, &style->fill, &parent->fill);
    }

    if (!style->fill_opacity.set || style->fill_opacity.inherit) {
        style->fill_opacity.value = parent->fill_opacity.value;
    }

    if (!style->fill_rule.set || style->fill_rule.inherit) {
        style->fill_rule.computed = parent->fill_rule.computed;
    }

    /* Stroke */
    if (!style->stroke.set || style->stroke.inherit || style->stroke.currentcolor) {
        sp_style_merge_ipaint(style, &style->stroke, &parent->stroke);
    }

    if (!style->stroke_width.set || style->stroke_width.inherit) {
        style->stroke_width.computed = parent->stroke_width.computed;
    } else {
        /* Update computed value for any change in font inherited from parent. */
        double const em = style->font_size.computed;
        if (style->stroke_width.unit == SP_CSS_UNIT_EM) {
            style->stroke_width.computed = style->stroke_width.value * em;
        } else if (style->stroke_width.unit == SP_CSS_UNIT_EX) {
            double const ex = em * 0.5;  // fixme: Get x height from libnrtype or pango.
            style->stroke_width.computed = style->stroke_width.value * ex;
        }
    }

    if (!style->stroke_linecap.set || style->stroke_linecap.inherit) {
        style->stroke_linecap.computed = parent->stroke_linecap.computed;
    }

    if (!style->stroke_linejoin.set || style->stroke_linejoin.inherit) {
        style->stroke_linejoin.computed = parent->stroke_linejoin.computed;
    }

    if (!style->stroke_miterlimit.set || style->stroke_miterlimit.inherit) {
        style->stroke_miterlimit.value = parent->stroke_miterlimit.value;
    }

    if (!style->stroke_dasharray_set && parent->stroke_dasharray_set) {
        /** \todo
         * This code looks wrong.  Why does the logic differ from the
         * above properties? Similarly dashoffset below.
         */
        style->stroke_dash.n_dash = parent->stroke_dash.n_dash;
        if (style->stroke_dash.n_dash > 0) {
            style->stroke_dash.dash = g_new(gdouble, style->stroke_dash.n_dash);
            memcpy(style->stroke_dash.dash, parent->stroke_dash.dash, style->stroke_dash.n_dash * sizeof(gdouble));
        }
    }

    if (!style->stroke_dashoffset_set && parent->stroke_dashoffset_set) {
        style->stroke_dash.offset = parent->stroke_dash.offset;
    }

    if (!style->stroke_opacity.set || style->stroke_opacity.inherit) {
        style->stroke_opacity.value = parent->stroke_opacity.value;
    }

    if (style->text && parent->text) {
        if (!style->text->font_family.set || style->text->font_family.inherit) {
            g_free(style->text->font_family.value);
            style->text->font_family.value = g_strdup(parent->text->font_family.value);
        }
    }

    if (style->text && parent->text) {
        if (!style->text->font_specification.set || style->text->font_specification.inherit) {
            g_free(style->text->font_specification.value);
            style->text->font_specification.value = g_strdup(parent->text->font_specification.value);
        }
    }

    /* Markers - Free the old value and make copy of the new */
    for (unsigned i = SP_MARKER_LOC; i < SP_MARKER_LOC_QTY; i++) {
        if (!style->marker[i].set || style->marker[i].inherit) {
            g_free(style->marker[i].value);
            style->marker[i].value = g_strdup(parent->marker[i].value);
        }
    }

    /* Filter effects */
    if (style->filter.inherit) {
        sp_style_merge_ifilter(style, &parent->filter);
    }

    if(style->enable_background.inherit) {
        style->enable_background.value = parent->enable_background.value;
    }
}


Generated by  Doxygen 1.6.0   Back to index