synfig::Layer::Handle
XORPattern::hit_check(synfig::Context context, const synfig::Point &getpos)const
{
	// if we have a zero amount
	if(get_amount()==0.0)
		// then the click passes down to our context
		return context.hit_check(getpos);

	synfig::Layer::Handle tmp;
	// if we are behind the context, and the click hits something in the context
	if(get_blend_method()==Color::BLEND_BEHIND && (tmp=context.hit_check(getpos)))
		// then return the thing it hit in the context
		return tmp;

	// if we're using an 'onto' blend method and the click missed the context
	if(Color::is_onto(get_blend_method()) && !(tmp=context.hit_check(getpos)))
		// then it misses everything
		return 0;

	// otherwise the click hit us, since we're the size of the whole plane
	return const_cast<XORPattern*>(this);
}
Exemple #2
0
bool
LinearGradient::accelerated_cairorender(Context context, cairo_t *cr, int quality, const RendDesc &renddesc, ProgressCallback *cb)const
{
	bool loop=param_loop.get(bool());
	Point p1=param_p1.get(Point());
	Point p2=param_p2.get(Point());
	Gradient gradient=param_gradient.get(Gradient());

	cairo_save(cr);
	cairo_pattern_t* pattern=cairo_pattern_create_linear(p1[0], p1[1], p2[0], p2[1]);
	bool cpoints_all_opaque=compile_gradient(pattern, gradient);
	if(loop)
		cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
	if(quality>8) cairo_pattern_set_filter(pattern, CAIRO_FILTER_FAST);
	else if(quality>=4) cairo_pattern_set_filter(pattern, CAIRO_FILTER_GOOD);
	else cairo_pattern_set_filter(pattern, CAIRO_FILTER_BEST);
	if(
	   !
	   (is_solid_color() ||
		(cpoints_all_opaque && get_blend_method()==Color::BLEND_COMPOSITE && get_amount()==1.f))
	   )
	{
		// Initially render what's behind us
		if(!context.accelerated_cairorender(cr,quality,renddesc,cb))
		{
			if(cb)cb->error(strprintf(__FILE__"%d: Accelerated Cairo Renderer Failure",__LINE__));
			return false;
		}
	}
	cairo_set_source(cr, pattern);
	cairo_paint_with_alpha_operator(cr, get_amount(), get_blend_method());
	
	cairo_pattern_destroy(pattern); // Not needed more
	cairo_restore(cr);
	return true;
}
bool
CurveGradient::accelerated_cairorender(Context context, cairo_t *cr,int quality, const RendDesc &renddesc_, ProgressCallback *cb)const
{
    RendDesc	renddesc(renddesc_);

    // Untransform the render desc
    if(!cairo_renddesc_untransform(cr, renddesc))
        return false;

    Point pos;
    const Real pw(renddesc.get_pw()),ph(renddesc.get_ph());
    const Point tl(renddesc.get_tl());
    const int w(renddesc.get_w());
    const int h(renddesc.get_h());

    SuperCallback supercb(cb,0,9500,10000);

    if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
    {
        cairo_save(cr);
        cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
        cairo_paint(cr);
        cairo_restore(cr);
    }
    else
    {
        if(!context.accelerated_cairorender(cr,quality,renddesc,&supercb))
            return false;
        if(get_amount()==0)
            return true;
    }


    int x,y;
    cairo_surface_t *surface;

    surface=cairo_surface_create_similar(cairo_get_target(cr), CAIRO_CONTENT_COLOR_ALPHA, w, h);

    CairoSurface csurface(surface);
    if(!csurface.map_cairo_image())
    {
        synfig::warning("Curve Gradient: map cairo surface failed");
        return false;
    }
    for(y=0,pos[1]=tl[1]; y<h; y++,pos[1]+=ph)
        for(x=0,pos[0]=tl[0]; x<w; x++,pos[0]+=pw)
            csurface[y][x]=CairoColor(color_func(pos,calc_supersample(pos,pw,ph))).premult_alpha();
    csurface.unmap_cairo_image();

    // paint surface on cr
    cairo_save(cr);
    cairo_translate(cr, tl[0], tl[1]);
    cairo_scale(cr, pw, ph);
    cairo_set_source_surface(cr, surface, 0, 0);
    cairo_paint_with_alpha_operator(cr, get_amount(), get_blend_method());
    cairo_restore(cr);

    cairo_surface_destroy(surface);
    // Mark our progress as finished
    if(cb && !cb->amount_complete(10000,10000))
        return false;

    return true;

}
bool
LinearGradient::accelerated_render(Context context,Surface *surface,int quality, const RendDesc &renddesc, ProgressCallback *cb)const
{
	Params params;
	fill_params(params);

	if (!renddesc.get_transformation_matrix().is_identity())
	{
		Point origin = params.p1;
		Point axis_x = params.p2 - origin;
		Point axis_y = axis_x.perp();
		origin = renddesc.get_transformation_matrix().get_transformed(origin);
		axis_x = renddesc.get_transformation_matrix().get_transformed(axis_x, false);
		axis_y = renddesc.get_transformation_matrix().get_transformed(axis_y, false);

		Point valid_axis_x = -axis_y.perp();
		Real mag_squared = valid_axis_x.mag_squared();
		if (mag_squared > 0.0)
			valid_axis_x *= (valid_axis_x * axis_x)/mag_squared;
		else
			valid_axis_x = axis_x;

		params.p1 = origin;
		params.p2 = origin + valid_axis_x;
		params.calc_diff();
	}

	SuperCallback supercb(cb,0,9500,10000);

	if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
	{
		surface->set_wh(renddesc.get_w(),renddesc.get_h());
	}
	else
	{
		if(!context.accelerated_render(surface,quality,renddesc,&supercb))
			return false;
		if(get_amount()==0)
			return true;
	}


	int x,y;

	Surface::pen pen(surface->begin());
	const Real pw(renddesc.get_pw()),ph(renddesc.get_ph());
	Point pos;
	Point tl(renddesc.get_tl());
	const int w(surface->get_w());
	const int h(surface->get_h());
	synfig::Real supersample = calc_supersample(params, pw, ph);

	if(get_amount()==1.0 && get_blend_method()==Color::BLEND_STRAIGHT)
	{
		for(y=0,pos[1]=tl[1];y<h;y++,pen.inc_y(),pen.dec_x(x),pos[1]+=ph)
			for(x=0,pos[0]=tl[0];x<w;x++,pen.inc_x(),pos[0]+=pw)
				pen.put_value(color_func(params,pos,supersample));
	}
	else
	{
		for(y=0,pos[1]=tl[1];y<h;y++,pen.inc_y(),pen.dec_x(x),pos[1]+=ph)
			for(x=0,pos[0]=tl[0];x<w;x++,pen.inc_x(),pos[0]+=pw)
				pen.put_value(Color::blend(color_func(params,pos,supersample),pen.get_value(),get_amount(),get_blend_method()));
	}

	// Mark our progress as finished
	if(cb && !cb->amount_complete(10000,10000))
		return false;

	return true;
}