Logo Search packages:      
Sourcecode: inkscape version File versions

int objects_query_fillstroke ( GSList *  objects,
SPStyle style_res,
bool const   isfill 
)

Write to style_res the average fill or stroke of list of objects, if applicable.

Definition at line 421 of file desktop-style.cpp.

References SPIPaint::color, SPIPaint::colorSet, SPIEnum::computed, SPIPaint::currentcolor, SPStyle::fill, SPStyle::fill_opacity, SPStyle::fill_rule, SPStyle::getFillURI(), SPStyle::getStrokeURI(), SPColor::icc, SPIPaint::isColor(), SPIPaint::isPaintserver(), SPIPaint::isSameType(), paint(), SPIPaint::set, SPIPaint::setColor(), sp_color_get_rgb_floatv(), sp_gradient_get_vector(), SPStyle::stroke, SPStyle::stroke_opacity, SPIScale24::value, and SPIPaint::value.

Referenced by sp_desktop_query_style_from_list().

{
    if (g_slist_length(objects) == 0) {
        /* No objects, set empty */
        return QUERY_STYLE_NOTHING;
    }

    SPIPaint *paint_res = isfill? &style_res->fill : &style_res->stroke;
    bool paintImpossible = true;
    paint_res->set = TRUE;

    SVGICCColor* iccColor = 0;
    bool iccSeen = false;
    gfloat c[4];
    c[0] = c[1] = c[2] = c[3] = 0.0;
    gint num = 0;

    gfloat prev[3];
    prev[0] = prev[1] = prev[2] = 0.0;
    bool same_color = true;

    for (GSList const *i = objects; i != NULL; i = i->next) {
        SPObject *obj = SP_OBJECT (i->data);
        SPStyle *style = SP_OBJECT_STYLE (obj);
        if (!style) continue;

        SPIPaint *paint = isfill? &style->fill : &style->stroke;

        // We consider paint "effectively set" for anything within text hierarchy
        SPObject *parent = SP_OBJECT_PARENT (obj);
        bool paint_effectively_set =
            paint->set || (SP_IS_TEXT(parent) || SP_IS_TEXTPATH(parent) || SP_IS_TSPAN(parent)
            || SP_IS_FLOWTEXT(parent) || SP_IS_FLOWDIV(parent) || SP_IS_FLOWPARA(parent)
            || SP_IS_FLOWTSPAN(parent) || SP_IS_FLOWLINE(parent));

        // 1. Bail out with QUERY_STYLE_MULTIPLE_DIFFERENT if necessary

        if ((!paintImpossible) && (!paint->isSameType(*paint_res) || (paint_res->set != paint_effectively_set))) {
            return QUERY_STYLE_MULTIPLE_DIFFERENT;  // different types of paint
        }

        if (paint_res->set && paint->set && paint_res->isPaintserver()) {
            // both previous paint and this paint were a server, see if the servers are compatible

            SPPaintServer *server_res = isfill? SP_STYLE_FILL_SERVER (style_res) : SP_STYLE_STROKE_SERVER (style_res);
            SPPaintServer *server = isfill? SP_STYLE_FILL_SERVER (style) : SP_STYLE_STROKE_SERVER (style);

            if (SP_IS_LINEARGRADIENT (server_res)) {

                if (!SP_IS_LINEARGRADIENT(server))
                   return QUERY_STYLE_MULTIPLE_DIFFERENT;  // different kind of server

                SPGradient *vector = sp_gradient_get_vector ( SP_GRADIENT (server), FALSE );
                SPGradient *vector_res = sp_gradient_get_vector ( SP_GRADIENT (server_res), FALSE );
                if (vector_res != vector)
                   return QUERY_STYLE_MULTIPLE_DIFFERENT;  // different gradient vectors

            } else if (SP_IS_RADIALGRADIENT (server_res)) {

                if (!SP_IS_RADIALGRADIENT(server))
                   return QUERY_STYLE_MULTIPLE_DIFFERENT;  // different kind of server

                SPGradient *vector = sp_gradient_get_vector ( SP_GRADIENT (server), FALSE );
                SPGradient *vector_res = sp_gradient_get_vector ( SP_GRADIENT (server_res), FALSE );
                if (vector_res != vector)
                   return QUERY_STYLE_MULTIPLE_DIFFERENT;  // different gradient vectors

            } else if (SP_IS_PATTERN (server_res)) {

                if (!SP_IS_PATTERN(server))
                   return QUERY_STYLE_MULTIPLE_DIFFERENT;  // different kind of server

                SPPattern *pat = pattern_getroot (SP_PATTERN (server));
                SPPattern *pat_res = pattern_getroot (SP_PATTERN (server_res));
                if (pat_res != pat)
                   return QUERY_STYLE_MULTIPLE_DIFFERENT;  // different pattern roots
            }
        }

        // 2. Sum color, copy server from paint to paint_res

        if (paint_res->set && paint_effectively_set && paint->isColor()) {
            gfloat d[3];
            sp_color_get_rgb_floatv (&paint->value.color, d);

            // Check if this color is the same as previous
            if (paintImpossible) {
                prev[0] = d[0];
                prev[1] = d[1];
                prev[2] = d[2];
                paint_res->setColor(d[0], d[1], d[2]);
                iccColor = paint->value.color.icc;
                iccSeen = true;
            } else {
                if (same_color && (prev[0] != d[0] || prev[1] != d[1] || prev[2] != d[2]))
                    same_color = false;
                if ( iccSeen ) {
                    if(paint->value.color.icc) {
                        // TODO fix this
                        iccColor = 0;
                    }
                }
            }

            // average color
            c[0] += d[0];
            c[1] += d[1];
            c[2] += d[2];
            c[3] += SP_SCALE24_TO_FLOAT (isfill? style->fill_opacity.value : style->stroke_opacity.value);
            num ++;
        }

       paintImpossible = false;
       paint_res->colorSet = paint->colorSet;
       paint_res->currentcolor = paint->currentcolor;
       if (paint_res->set && paint_effectively_set && paint->isPaintserver()) { // copy the server
           if (isfill) {
               sp_style_set_to_uri_string (style_res, true, style->getFillURI());
           } else {
               sp_style_set_to_uri_string (style_res, false, style->getStrokeURI());
           }
       }
       paint_res->set = paint_effectively_set;
       style_res->fill_rule.computed = style->fill_rule.computed; // no averaging on this, just use the last one
    }

    // After all objects processed, divide the color if necessary and return
    if (paint_res->set && paint_res->isColor()) { // set the color
        g_assert (num >= 1);

        c[0] /= num;
        c[1] /= num;
        c[2] /= num;
        c[3] /= num;
        paint_res->setColor(c[0], c[1], c[2]);
        if (isfill) {
            style_res->fill_opacity.value = SP_SCALE24_FROM_FLOAT (c[3]);
        } else {
            style_res->stroke_opacity.value = SP_SCALE24_FROM_FLOAT (c[3]);
        }


        if ( iccSeen && iccColor ) {
            // TODO check for existing
            SVGICCColor* tmp = new SVGICCColor(*iccColor);
            paint_res->value.color.icc = tmp;
        }

        if (num > 1) {
            if (same_color)
                return QUERY_STYLE_MULTIPLE_SAME;
            else
                return QUERY_STYLE_MULTIPLE_AVERAGED;
        } else {
            return QUERY_STYLE_SINGLE;
        }
    }

    // Not color
    if (g_slist_length(objects) > 1) {
        return QUERY_STYLE_MULTIPLE_SAME;
    } else {
        return QUERY_STYLE_SINGLE;
    }
}


Generated by  Doxygen 1.6.0   Back to index