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); }
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; }