Esempio n. 1
0
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);
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
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;
}
Esempio n. 6
0
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);
}