static void sp_ctrlline_render (SPCanvasItem *item, SPCanvasBuf *buf) { SPCtrlLine *cl = SP_CTRLLINE (item); if (!buf->ct) return; if (cl->s == cl->e) return; sp_canvas_prepare_buffer (buf); guint32 rgba = cl->rgba; cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_R_F(rgba), SP_RGBA32_A_F(rgba)); cairo_set_line_width(buf->ct, 1); cairo_new_path(buf->ct); Geom::Point s = cl->s * cl->affine; Geom::Point e = cl->e * cl->affine; cairo_move_to (buf->ct, s[Geom::X] - buf->rect.x0, s[Geom::Y] - buf->rect.y0); cairo_line_to (buf->ct, e[Geom::X] - buf->rect.x0, e[Geom::Y] - buf->rect.y0); cairo_stroke(buf->ct); }
static void sp_ctrlquadr_render (SPCanvasItem *item, SPCanvasBuf *buf) { SPCtrlQuadr *cq = SP_CTRLQUADR (item); if (!buf->ct) return; // RGB / BGR cairo_new_path(buf->ct); Geom::Point min = buf->rect.min(); Geom::Point p1 = (cq->p1 * cq->affine) - min; Geom::Point p2 = (cq->p2 * cq->affine) - min; Geom::Point p3 = (cq->p3 * cq->affine) - min; Geom::Point p4 = (cq->p4 * cq->affine) - min; cairo_move_to(buf->ct, p1[Geom::X], p1[Geom::Y]); cairo_line_to(buf->ct, p2[Geom::X], p2[Geom::Y]); cairo_line_to(buf->ct, p3[Geom::X], p3[Geom::Y]); cairo_line_to(buf->ct, p4[Geom::X], p4[Geom::Y]); cairo_line_to(buf->ct, p1[Geom::X], p1[Geom::Y]); // FIXME: this is supposed to draw inverse but cairo apparently is unable of this trick :( //cairo_set_operator (buf->ct, CAIRO_OPERATOR_XOR); cairo_set_source_rgba(buf->ct, SP_RGBA32_B_F(cq->rgba), SP_RGBA32_G_F(cq->rgba), SP_RGBA32_R_F(cq->rgba), SP_RGBA32_A_F(cq->rgba)); cairo_fill(buf->ct); }
void CairoContext::set_source_rgba32(guint32 color) { double red = SP_RGBA32_R_F(color); double gre = SP_RGBA32_G_F(color); double blu = SP_RGBA32_B_F(color); double alp = SP_RGBA32_A_F(color); cairo_set_source_rgba(cobj(), red, gre, blu, alp); }
void FilterFlood::render_cairo(FilterSlot &slot) { cairo_surface_t *input = slot.getcairo(_input); double r = SP_RGBA32_R_F(color); double g = SP_RGBA32_G_F(color); double b = SP_RGBA32_B_F(color); double a = opacity; #if defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2) if (icc) { guchar ru, gu, bu; icc_color_to_sRGB(icc, &ru, &gu, &bu); r = SP_COLOR_U_TO_F(ru); g = SP_COLOR_U_TO_F(gu); b = SP_COLOR_U_TO_F(bu); } #endif cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA); // Get filter primitive area in user units Geom::Rect fp = filter_primitive_area( slot.get_units() ); // Convert to Cairo units Geom::Rect fp_cairo = fp * slot.get_units().get_matrix_user2pb(); // Get area in slot (tile to fill) Geom::Rect sa = slot.get_slot_area(); // Get overlap Geom::OptRect optoverlap = intersect( fp_cairo, sa ); if( optoverlap ) { Geom::Rect overlap = *optoverlap; double dx = fp_cairo.min()[Geom::X] - sa.min()[Geom::X]; double dy = fp_cairo.min()[Geom::Y] - sa.min()[Geom::Y]; if( dx < 0.0 ) dx = 0.0; if( dy < 0.0 ) dy = 0.0; cairo_t *ct = cairo_create(out); cairo_set_source_rgba(ct, r, g, b, a); cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE); cairo_rectangle(ct, dx, dy, overlap.width(), overlap.height() ); cairo_fill(ct); cairo_destroy(ct); } slot.set(_output, out); cairo_surface_destroy(out); }
static gint sp_dropper_context_root_handler(SPEventContext *event_context, GdkEvent *event) { SPDropperContext *dc = (SPDropperContext *) event_context; int ret = FALSE; SPDesktop *desktop = event_context->desktop; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int pick = prefs->getInt("/tools/dropper/pick", SP_DROPPER_PICK_VISIBLE); bool setalpha = prefs->getBool("/tools/dropper/setalpha", true); switch (event->type) { case GDK_BUTTON_PRESS: if (event->button.button == 1 && !event_context->space_panning) { dc->centre = Geom::Point(event->button.x, event->button.y); dc->dragging = TRUE; ret = TRUE; } break; case GDK_MOTION_NOTIFY: if (event->motion.state & GDK_BUTTON2_MASK) { // pass on middle-drag ret = FALSE; break; } else if (!event_context->space_panning) { // otherwise, constantly calculate color no matter is any button pressed or not double rw = 0.0; double W(0), R(0), G(0), B(0), A(0); if (dc->dragging) { // calculate average // radius rw = std::min(Geom::L2(Geom::Point(event->button.x, event->button.y) - dc->centre), 400.0); if (rw == 0) { // happens sometimes, little idea why... break; } Geom::Point const cd = desktop->w2d(dc->centre); Geom::Matrix const w2dt = desktop->w2d(); const double scale = rw * w2dt.descrim(); Geom::Matrix const sm( Geom::Scale(scale, scale) * Geom::Translate(cd) ); sp_canvas_item_affine_absolute(dc->area, sm); sp_canvas_item_show(dc->area); /* Get buffer */ const int x0 = (int) floor(dc->centre[Geom::X] - rw); const int y0 = (int) floor(dc->centre[Geom::Y] - rw); const int x1 = (int) ceil(dc->centre[Geom::X] + rw); const int y1 = (int) ceil(dc->centre[Geom::Y] + rw); if ((x1 > x0) && (y1 > y0)) { NRPixBlock pb; nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x0, y0, x1, y1, TRUE); /* fixme: (Lauris) */ sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), &pb); for (int y = y0; y < y1; y++) { const unsigned char *s = NR_PIXBLOCK_PX(&pb) + (y - y0) * pb.rs; for (int x = x0; x < x1; x++) { const double dx = x - dc->centre[Geom::X]; const double dy = y - dc->centre[Geom::Y]; const double w = exp(-((dx * dx) + (dy * dy)) / (rw * rw)); W += w; R += w * s[0]; G += w * s[1]; B += w * s[2]; A += w * s[3]; s += 4; } } nr_pixblock_release(&pb); R = (R + 0.001) / (255.0 * W); G = (G + 0.001) / (255.0 * W); B = (B + 0.001) / (255.0 * W); A = (A + 0.001) / (255.0 * W); R = CLAMP(R, 0.0, 1.0); G = CLAMP(G, 0.0, 1.0); B = CLAMP(B, 0.0, 1.0); A = CLAMP(A, 0.0, 1.0); } } else { // pick single pixel NRPixBlock pb; int x = (int) floor(event->button.x); int y = (int) floor(event->button.y); nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x, y, x+1, y+1, TRUE); sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(desktop)), &pb); const unsigned char *s = NR_PIXBLOCK_PX(&pb); R = s[0] / 255.0; G = s[1] / 255.0; B = s[2] / 255.0; A = s[3] / 255.0; } if (pick == SP_DROPPER_PICK_VISIBLE) { // compose with page color guint32 bg = sp_desktop_namedview(desktop)->pagecolor; R = R + (SP_RGBA32_R_F(bg)) * (1 - A); G = G + (SP_RGBA32_G_F(bg)) * (1 - A); B = B + (SP_RGBA32_B_F(bg)) * (1 - A); A = 1.0; } else { // un-premultiply color channels if (A > 0) { R /= A; G /= A; B /= A; } } if (fabs(A) < 1e-4) { A = 0; // suppress exponentials, CSS does not allow that } // remember color dc->R = R; dc->G = G; dc->B = B; dc->alpha = A; // status message double alpha_to_set = setalpha? dc->alpha : 1.0; guint32 c32 = SP_RGBA32_F_COMPOSE(R, G, B, alpha_to_set); gchar c[64]; sp_svg_write_color(c, sizeof(c), c32); // alpha of color under cursor, to show in the statusbar // locale-sensitive printf is OK, since this goes to the UI, not into SVG gchar *alpha = g_strdup_printf(_(" alpha %.3g"), alpha_to_set); // where the color is picked, to show in the statusbar gchar *where = dc->dragging ? g_strdup_printf(_(", averaged with radius %d"), (int) rw) : g_strdup_printf(_(" under cursor")); // message, to show in the statusbar const gchar *message = dc->dragging ? _("<b>Release mouse</b> to set color.") : _("<b>Click</b> to set fill, <b>Shift+click</b> to set stroke; <b>drag</b> to average color in area; with <b>Alt</b> to pick inverse color; <b>Ctrl+C</b> to copy the color under mouse to clipboard"); event_context->defaultMessageContext()->setF( Inkscape::NORMAL_MESSAGE, "<b>%s%s</b>%s. %s", c, (pick == SP_DROPPER_PICK_VISIBLE)? "" : alpha, where, message ); g_free(where); g_free(alpha); ret = TRUE; } break; case GDK_BUTTON_RELEASE: if (event->button.button == 1 && !event_context->space_panning) { sp_canvas_item_hide(dc->area); dc->dragging = FALSE; double alpha_to_set = setalpha? dc->alpha : 1.0; // do the actual color setting sp_desktop_set_color(desktop, (event->button.state & GDK_MOD1_MASK)? ColorRGBA(1 - dc->R, 1 - dc->G, 1 - dc->B, alpha_to_set) : ColorRGBA(dc->R, dc->G, dc->B, alpha_to_set), false, !(event->button.state & GDK_SHIFT_MASK)); // REJON: set aux. toolbar input to hex color! if (!(sp_desktop_selection(desktop)->isEmpty())) { sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_DROPPER, _("Set picked color")); } ret = TRUE; } break; case GDK_KEY_PRESS: switch (get_group0_keyval(&event->key)) { case GDK_Up: case GDK_Down: case GDK_KP_Up: case GDK_KP_Down: // prevent the zoom field from activation if (!MOD__CTRL_ONLY) { ret = TRUE; } break; case GDK_Escape: sp_desktop_selection(desktop)->clear(); default: break; } break; default: break; } if (!ret) { if (((SPEventContextClass *) parent_class)->root_handler) { ret = ((SPEventContextClass *) parent_class)->root_handler(event_context, event); } } return ret; }
void ink_cairo_set_source_rgba32(cairo_t *ct, guint32 rgba) { cairo_set_source_rgba(ct, SP_RGBA32_R_F(rgba), SP_RGBA32_G_F(rgba), SP_RGBA32_B_F(rgba), SP_RGBA32_A_F(rgba)); }
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); }