static void
sp_gradient_simplify(SPGradientContext *rc, double tolerance)
{
    SPDocument *doc = NULL;
    GrDrag *drag = rc->_grdrag;

    GSList *these_stops = NULL;
    GSList *next_stops = NULL;

    std::vector<Geom::Point> coords = sp_gradient_context_get_stop_intervals (drag, &these_stops, &next_stops);

    GSList *todel = NULL;

    GSList *i = these_stops;
    GSList *j = next_stops;
    for (; i != NULL && j != NULL; i = i->next, j = j->next) {
        SPStop *stop0 = (SPStop *) i->data;
        SPStop *stop1 = (SPStop *) j->data;

        gint i1 = g_slist_index(these_stops, stop1);
        if (i1 != -1) {
            GSList *next_next = g_slist_nth (next_stops, i1);
            if (next_next) {
                SPStop *stop2 = (SPStop *) next_next->data;

                if (g_slist_find(todel, stop0) || g_slist_find(todel, stop2))
                    continue;

                guint32 const c0 = sp_stop_get_rgba32(stop0);
                guint32 const c2 = sp_stop_get_rgba32(stop2);
                guint32 const c1r = sp_stop_get_rgba32(stop1);
                guint32 c1 = average_color (c0, c2, 
                       (stop1->offset - stop0->offset) / (stop2->offset - stop0->offset));

                double diff = 
                    sqr(SP_RGBA32_R_F(c1) - SP_RGBA32_R_F(c1r)) +
                    sqr(SP_RGBA32_G_F(c1) - SP_RGBA32_G_F(c1r)) +
                    sqr(SP_RGBA32_B_F(c1) - SP_RGBA32_B_F(c1r)) +
                    sqr(SP_RGBA32_A_F(c1) - SP_RGBA32_A_F(c1r));

                if (diff < tolerance)
                    todel = g_slist_prepend (todel, stop1);
            }
        }
    }

    for (i = todel; i != NULL; i = i->next) {
        SPStop *stop = (SPStop*) i->data;
        doc = SP_OBJECT_DOCUMENT (stop);
        Inkscape::XML::Node * parent = SP_OBJECT_REPR(stop)->parent();
        parent->removeChild(SP_OBJECT_REPR(stop));
    }

    if (g_slist_length(todel) > 0) {
        sp_document_done (doc, SP_VERB_CONTEXT_GRADIENT, _("Simplify gradient"));
        drag->local_change = true;
        drag->updateDraggers();
        drag->selectByCoords(coords);
    }

    g_slist_free (todel);
    g_slist_free (these_stops);
    g_slist_free (next_stops);
}
Exemple #2
0
bool Plasma::do_plasma(int x1, int y1, int x2, int y2, int depth, int scale_depth)
{
	Color tl, ml, bl, tm, mm, bm, tr, mr, br;
	
	int xm = ( x1 + x2 )/ 2;
	int ym = ( y1 + y2 )/ 2;
	
	if(depth == -1)
	{
		random_rbg(tl);
		random_rbg(ml);
		random_rbg(bl);
		random_rbg(tm);
		random_rbg(mm);
		random_rbg(bm);
		random_rbg(tr);
		random_rbg(mr);
		random_rbg(br);
		
		set_pixel(m_pSurface, x1, y1, tl);
		set_pixel(m_pSurface, x1, ym, ml);
		set_pixel(m_pSurface, x1, y2, bl);
		set_pixel(m_pSurface, xm, y1, tm);
		set_pixel(m_pSurface, xm, ym, mm);
		set_pixel(m_pSurface, xm, y2, bm);
		set_pixel(m_pSurface, x2, y1, tr);
		set_pixel(m_pSurface, x2, ym, mr);
		set_pixel(m_pSurface, x2, y2, br);
		
		return false;
	}
	
	if(depth == 0)
	{
		if(x1 == x2 && y1 == y2)
			return false;
		
		get_pixel(m_pSurface, x1, y1, tl);
		get_pixel(m_pSurface, x1, y2, bl);
		get_pixel(m_pSurface, x2, y1, tr);
		get_pixel(m_pSurface, x2, y2, br);
		
		
		int ran = (int)((256.0 / (2 * scale_depth)) * m_fTurbulance);
		if (xm != x1 || xm != x2)
		{
			// Left
			ml = average_color(tl, bl);
			add_random(ml, ran);
			set_pixel(m_pSurface, x1, ym, ml);

			if (x1 != x2)
			{
				// Right 
				mr  = average_color(tr, br);
				add_random(mr, ran);
				set_pixel(m_pSurface, x2, ym, mr);
			}
		}

		if (ym != y1 || ym != y2)
		{
			if (x1 != xm || ym != y2)
			{
				// Bottom
				Color mb  = average_color(bl, br);
				add_random(mb, ran);
				set_pixel(m_pSurface, xm, y2, mb);
			}

			if (y1 != y2)
			{
				// Top
				Color mt  = average_color(tl, tr);
				add_random(mt, ran);
				set_pixel(m_pSurface, xm, y1, mt);
			}
		}

		if (y1 != y2 || x1 != x2)
		{
			// Middle pixel
			Color tmp;
			mm  = average_color(tl, br);
			tmp = average_color(bl, tr);
			mm  = average_color(mm, tmp);

			add_random(mm, ran);
			set_pixel(m_pSurface, xm, ym, mm);
		}
		
		return x2 - x1 < 3 && y2 - y1 < 3;
	} //depth == 0
	
	if (x1 < x2 || y1 < y2)
	{
		// Top left.
		do_plasma (x1, y1, xm, ym, depth - 1, scale_depth + 1);
		/* Bottom left. */
		do_plasma (x1, ym, xm, y2, depth - 1, scale_depth + 1);
		/* Top right. */
		do_plasma (xm, y1, x2, ym, depth - 1, scale_depth + 1);
		/* Bottom right. */
		return do_plasma (xm, ym, x2, y2, depth - 1, scale_depth + 1);
	}
	
	return true;	
}