static int sp_spiral_snappoints (SPItem *item, NRPointF *p, int size) { #if 0 /* fixme: (Lauris) */ SPSpiral *spiral; ArtPoint * p, p1, p2, p3; gdouble affine[6]; spiral = SP_SPIRAL(item); sp_spiral_get_xy (spiral, 0.0, &p1); sp_spiral_get_xy (spiral, spiral->t0, &p2); sp_spiral_get_xy (spiral, 1.0, &p3); sp_item_i2d_affine (item, affine); p = g_new (ArtPoint,1); art_affine_point (p, &p1, affine); points = g_slist_append (points, p); p = g_new (ArtPoint,1); art_affine_point (p, &p2, affine); points = g_slist_append (points, p); p = g_new (ArtPoint,1); art_affine_point (p, &p3, affine); points = g_slist_append (points, p); #else if (((SPItemClass *) parent_class)->snappoints) return ((SPItemClass *) parent_class)->snappoints (item, p, size); #endif return 0; }
static void textbox_flip (ItemData *data, gboolean horizontal, SheetPos *center) { double affine[6]; ArtPoint src, dst; Textbox *textbox; TextboxPriv *priv; SheetPos b1, b2; SheetPos textbox_center, delta; g_return_if_fail (data != NULL); g_return_if_fail (IS_TEXTBOX (data)); textbox = TEXTBOX (data); if (center) { item_data_get_absolute_bbox (ITEM_DATA (textbox), &b1, &b2); textbox_center.x = b1.x + (b2.x - b1.x) / 2; textbox_center.y = b1.y + (b2.y - b1.y) / 2; } priv = textbox->priv; if (horizontal) art_affine_scale (affine, -1, 1); else art_affine_scale (affine, 1, -1); /* * Let the views (canvas items) know about the rotation. */ g_signal_emit_by_name(G_OBJECT (textbox), "flipped", horizontal); if (center) { SheetPos textbox_pos; item_data_get_pos (ITEM_DATA (textbox), &textbox_pos); src.x = textbox_center.x - center->x; src.y = textbox_center.y - center->y; art_affine_point (&dst, &src, affine); delta.x = -src.x + dst.x; delta.y = -src.y + dst.y; item_data_move (ITEM_DATA (textbox), &delta); } }
/** * art_rgb_affine: Affine transform source RGB image and composite. * @dst: Destination image RGB buffer. * @x0: Left coordinate of destination rectangle. * @y0: Top coordinate of destination rectangle. * @x1: Right coordinate of destination rectangle. * @y1: Bottom coordinate of destination rectangle. * @dst_rowstride: Rowstride of @dst buffer. * @src: Source image RGB buffer. * @src_width: Width of source image. * @src_height: Height of source image. * @src_rowstride: Rowstride of @src buffer. * @affine: Affine transform. * @level: Filter level. * @alphagamma: #ArtAlphaGamma for gamma-correcting the compositing. * * Affine transform the source image stored in @src, compositing over * the area of destination image @dst specified by the rectangle * (@x0, @y0) - (@x1, @y1). As usual in libart, the left and top edges * of this rectangle are included, and the right and bottom edges are * excluded. * * The @alphagamma parameter specifies that the alpha compositing be done * in a gamma-corrected color space. Since the source image is opaque RGB, * this argument only affects the edges. In the current implementation, * it is ignored. * * The @level parameter specifies the speed/quality tradeoff of the * image interpolation. Currently, only ART_FILTER_NEAREST is * implemented. **/ void art_rgb_affine (art_u8 *dst, int x0, int y0, int x1, int y1, int dst_rowstride, const art_u8 *src, int src_width, int src_height, int src_rowstride, const double affine[6], ArtFilterLevel level, ArtAlphaGamma *alphagamma) { /* Note: this is a slow implementation, and is missing all filter levels other than NEAREST. It is here for clarity of presentation and to establish the interface. */ int x, y; double inv[6]; art_u8 *dst_p, *dst_linestart; const art_u8 *src_p; ArtPoint pt, src_pt; int src_x, src_y; int run_x0, run_x1; dst_linestart = dst; art_affine_invert (inv, affine); for (y = y0; y < y1; y++) { pt.y = y + 0.5; run_x0 = x0; run_x1 = x1; art_rgb_affine_run (&run_x0, &run_x1, y, src_width, src_height, inv); dst_p = dst_linestart + (run_x0 - x0) * 3; for (x = run_x0; x < run_x1; x++) { pt.x = x + 0.5; art_affine_point (&src_pt, &pt, inv); src_x = floor (src_pt.x); src_y = floor (src_pt.y); src_p = src + (src_y * src_rowstride) + src_x * 3; dst_p[0] = src_p[0]; dst_p[1] = src_p[1]; dst_p[2] = src_p[2]; dst_p += 3; } dst_linestart += dst_rowstride; } }
static double gnome_canvas_item_invoke_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) { #ifdef HACKISH_AFFINE double i2w[6], w2c[6], i2c[6], c2i[6]; ArtPoint c, i; #endif #ifdef HACKISH_AFFINE gnome_canvas_item_i2w_affine (item, i2w); gnome_canvas_w2c_affine (item->canvas, w2c); art_affine_multiply (i2c, i2w, w2c); art_affine_invert (c2i, i2c); c.x = cx; c.y = cy; art_affine_point (&i, &c, c2i); x = i.x; y = i.y; #endif return (* GNOME_CANVAS_ITEM_CLASS (GTK_OBJECT_GET_CLASS (item))->point) ( item, x, y, cx, cy, actual_item); }
static void test_affine (void) { double src[6]; double dst[6]; double src2[6]; char str[128]; int i; ArtPoint ps, pd, ptmp; for (i = 0; i < 6; i++) { src[i] = (rand () * 2.0 / RAND_MAX) - 1.0; src2[i] = (rand () * 2.0 / RAND_MAX) - 1.0; } #if 0 src[0] = 0.9999999; src[1] = -0.000001; src[2] = 0.000001; src[3] = 0.9999999; src[4] = 0; src[5] = 0; #if 1 src[0] = 0.98480775; src[1] = -0.17364818; src[2] = 0.17364818; src[3] = 0.98480775; #endif src2[0] = 0.98480775; src2[1] = -0.17364818; src2[2] = 0.17364818; src2[3] = 0.98480775; #endif ps.x = rand() * 100.0 / RAND_MAX; ps.y = rand() * 100.0 / RAND_MAX; art_affine_point (&pd, &ps, src); art_affine_invert (dst, src); art_affine_point (&ptmp, &pd, dst); art_affine_to_string (str, src); printf ("src = %s\n", str); art_affine_to_string (str, dst); printf ("dst = %s\n", str); printf ("point (%g, %g) -> (%g, %g) -> (%g, %g)\n", ps.x, ps.y, pd.x, pd.y, ptmp.x, ptmp.y); art_affine_point (&ptmp, &ps, src); art_affine_point (&pd, &ptmp, src2); art_affine_to_string (str, src2); printf ("src2 = %s\n", str); printf ("point (%g, %g) -> (%g, %g) -> (%g, %g)\n", ps.x, ps.y, ptmp.x, ptmp.y, pd.x, pd.y); art_affine_multiply (dst, src, src2); art_affine_to_string (str, dst); printf ("dst = %s\n", str); art_affine_point (&pd, &ps, dst); printf ("point (%g, %g) -> (%g, %g)\n", ps.x, ps.y, pd.x, pd.y); }
GnomePosGlyphList * gnome_pgl_from_gl (const GnomeGlyphList * gl, const gdouble * transform, guint flags) { static gdouble identity[] = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0}; GnomePosGlyphList * pgl; gboolean fontfound; gint allocated_strings; gint r; gint cg, cr; ArtPoint pos, pen; gboolean usemetrics; gint lastglyph; gboolean advance; ArtPoint letterspace; gdouble kerning; GnomeFont * font; guint32 color; gboolean needstring; gint currentstring; gint sptr; ArtPoint p; g_return_val_if_fail (gl != NULL, NULL); g_return_val_if_fail (GNOME_IS_GLYPHLIST (gl), NULL); if (!transform) transform = identity; /* Special case */ if (gl->g_length < 1) { pgl = g_new (GnomePosGlyphList, 1); pgl->glyphs = NULL; pgl->strings = NULL; pgl->num_strings = 0; return pgl; } /* We need font rule */ g_return_val_if_fail (gl->r_length > 0, NULL); g_return_val_if_fail (gl->rules[0].code == GGL_POSITION, NULL); g_return_val_if_fail (gl->rules[0].value.ival == 0, NULL); fontfound = FALSE; for (r = 1; (r < gl->r_length) && (gl->rules[r].code != GGL_POSITION); r++) { if (gl->rules[r].code == GGL_FONT) { g_return_val_if_fail (gl->rules[r].value.font != NULL, NULL); g_return_val_if_fail (GNOME_IS_FONT (gl->rules[r].value.font), NULL); fontfound = TRUE; break; } } g_return_val_if_fail (fontfound, NULL); /* Initialize pgl */ pgl = g_new (GnomePosGlyphList, 1); pgl->glyphs = g_new (GnomePosGlyph, gl->g_length); pgl->strings = g_new (GnomePosString, 1); pgl->num_strings = 0; allocated_strings = 1; /* State machine */ sptr = 0; pen.x = transform[4]; pen.y = transform[5]; usemetrics = FALSE; lastglyph = -1; advance = TRUE; letterspace.x = 0.0; letterspace.y = 0.0; kerning = 0.0; font = NULL; color = 0x000000ff; needstring = TRUE; currentstring = -1; cr = 0; for (cg = 0; cg < gl->g_length; cg++) { /* Collect rules */ while ((cr < gl->r_length) && ((gl->rules[cr].code != GGL_POSITION) || (gl->rules[cr].value.ival <= cg))) { switch (gl->rules[cr].code) { case GGL_MOVETOX: /* moveto is special case */ g_return_val_if_fail (cr + 1 < gl->r_length, NULL); g_return_val_if_fail (gl->rules[cr + 1].code == GGL_MOVETOY, NULL); pos.x = gl->rules[cr].value.dval; pos.y = gl->rules[cr + 1].value.dval; cr += 1; usemetrics = FALSE; art_affine_point (&pen, &pos, transform); break; case GGL_RMOVETOX: /* rmoveto is special case */ g_return_val_if_fail (cr + 1 < gl->r_length, NULL); g_return_val_if_fail (gl->rules[cr + 1].code == GGL_RMOVETOY, NULL); pos.x = gl->rules[cr].value.dval; pos.y = gl->rules[cr + 1].value.dval; cr += 1; usemetrics = FALSE; pen.x += pos.x * transform[0] + pos.y * transform[2]; pen.y += pos.x * transform[1] + pos.y * transform[3]; break; case GGL_ADVANCE: advance = gl->rules[cr].value.bval; break; case GGL_LETTERSPACE: p.x = gl->rules[cr].value.dval; p.y = 0.0; letterspace.x = p.x * transform[0] + p.y * transform[2]; letterspace.y = p.x * transform[1] + p.y * transform[3]; break; case GGL_KERNING: kerning = gl->rules[cr].value.dval; break; case GGL_FONT: font = gl->rules[cr].value.font; g_return_val_if_fail (font != NULL, NULL); g_return_val_if_fail (GNOME_IS_FONT (font), NULL); needstring = TRUE; break; case GGL_COLOR: color = gl->rules[cr].value.color; needstring = TRUE; break; } cr += 1; } if (needstring) { /* Add new string instance */ g_assert (GNOME_IS_FONT (font)); if (pgl->num_strings >= allocated_strings) { allocated_strings += 4; pgl->strings = g_renew (GnomePosString, pgl->strings, allocated_strings); } currentstring = pgl->num_strings; pgl->num_strings += 1; pgl->strings[currentstring].start = cg; pgl->strings[currentstring].length = 0; pgl->strings[currentstring].rfont = gnome_font_get_rfont (font, transform); pgl->strings[currentstring].color = color; needstring = FALSE; } /* Rules are parsed and currentstring points to active string */ /* Process glyph */ pgl->glyphs[cg].glyph = gl->glyphs[cg]; pgl->strings[currentstring].length += 1; if (usemetrics && (lastglyph > 0) && (pgl->glyphs[cg].glyph > 0)) { /* Need to add kerning */ if (gnome_rfont_get_glyph_stdkerning (pgl->strings[currentstring].rfont, lastglyph, pgl->glyphs[cg].glyph, &p)) { pen.x += p.x; pen.y += p.y; } pen.x += letterspace.x; pen.y += letterspace.y; } pgl->glyphs[cg].x = pen.x; pgl->glyphs[cg].y = pen.y; if (advance) { if (gnome_rfont_get_glyph_stdadvance (pgl->strings[currentstring].rfont, pgl->glyphs[cg].glyph, &p)) { pen.x += p.x; pen.y += p.y; } } usemetrics = TRUE; lastglyph = pgl->glyphs[cg].glyph; } return pgl; }
static void relation_arrow_draw (GnomeCanvasItem *item, GdkDrawable *drawable, gint x, gint y, gint width, gint height) { PlannerRelationArrow *arrow; PlannerRelationArrowPriv *priv; #ifdef USE_AFFINE gdouble i2c[6]; ArtPoint i1, i2, c1, c2; #else gdouble i2w_dx; gdouble i2w_dy; gdouble dx1, dy1, dx2, dy2; #endif gint cx1, cy1, cx2, cy2; GdkGC *gc; GdkPoint points[4]; gint i; arrow = PLANNER_RELATION_ARROW (item); priv = arrow->priv; gc = gdk_gc_new (drawable); gdk_gc_set_line_attributes (gc, 1, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); /* Silence warning. */ cx1 = 0; cy1 = 0; cx2 = 0; cy2 = 0; #ifdef USE_AFFINE /* Get item area in canvas coordinates. */ gnome_canvas_item_i2c_affine (item, i2c); #endif for (i = 0; i < priv->num_points - 1; i++) { #ifdef USE_AFFINE i1.x = priv->points[i].x; i1.y = priv->points[i].y; i2.x = priv->points[i+1].x; i2.y = priv->points[i+1].y; art_affine_point (&c1, &i1, i2c); art_affine_point (&c2, &i2, i2c); cx1 = floor (c1.x + 0.5) - x; cy1 = floor (c1.y + 0.5) - y; cx2 = floor (c2.x + 0.5) - x; cy2 = floor (c2.y + 0.5) - y; #else i2w_dx = 0.0; i2w_dy = 0.0; gnome_canvas_item_i2w (item, &i2w_dx, &i2w_dy); dx1 = priv->points[i].x; dy1 = priv->points[i].y; dx2 = priv->points[i+1].x; dy2 = priv->points[i+1].y; gnome_canvas_w2c (item->canvas, dx1 + i2w_dx, dy1 + i2w_dy, &cx1, &cy1); gnome_canvas_w2c (item->canvas, dx2 + i2w_dx, dy2 + i2w_dy, &cx2, &cy2); cx1 -= x; cy1 -= y; cx2 -= x; cy2 -= y; #endif gdk_draw_line (drawable, gc, cx1, cy1, cx2, cy2); } relation_arrow_setup_arrow (priv->arrow_dir, points, cx1, cy1, cx2, cy2); gdk_draw_polygon (drawable, gc, TRUE, (GdkPoint *) &points, 4); g_object_unref (gc); }