Esempio n. 1
0
static void
draw_text (cairo_t *cr)
{
    cairo_matrix_t tm;

    /* skew */
    cairo_matrix_init (&tm, 1, 0,
                       -0.25, 1,
                       0, 0);
    cairo_matrix_scale (&tm, FONT_SIZE, FONT_SIZE);
    cairo_set_font_matrix (cr, &tm);

    cairo_new_path (cr);
    cairo_move_to (cr, 50, SIZE-PAD);
    cairo_show_text (cr, "A");

    /* rotate and scale */
    cairo_matrix_init_rotate (&tm, M_PI / 2);
    cairo_matrix_scale (&tm, FONT_SIZE, FONT_SIZE * 2.0);
    cairo_set_font_matrix (cr, &tm);

    cairo_new_path (cr);
    cairo_move_to (cr, PAD, PAD + 25);
    cairo_show_text (cr, "A");

    cairo_matrix_init_rotate (&tm, M_PI / 2);
    cairo_matrix_scale (&tm, FONT_SIZE * 2.0, FONT_SIZE);
    cairo_set_font_matrix (cr, &tm);

    cairo_new_path (cr);
    cairo_move_to (cr, PAD, PAD + 50);
    cairo_show_text (cr, "A");
}
Esempio n. 2
0
static int m_cairo_matrix_init_rotate(lua_State * L)
{
	cairo_matrix_t * matrix = luaL_checkudata(L, 1, MT_NAME_CAIRO_MATRIX);
	double radians = luaL_checknumber(L, 2);
	cairo_matrix_init_rotate(matrix, radians);
	return 0;
}
Esempio n. 3
0
int renderTruetypeSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol,
                              symbolStyleObj *s)
{
  int unicode;
  cairo_glyph_t glyph;
  cairo_text_extents_t extents;

  cairo_matrix_t trans;
  double ox,oy;
  cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img);
  cairo_renderer *r = CAIRO_RENDERER(img);
  faceCacheObj *face = getFontFace(cache,symbol->full_font_path);

  if(!face) return MS_FAILURE;

  cairo_save(r->cr);
  cairo_set_font_face(r->cr,face->face);
  cairo_set_font_size(r->cr,s->scale*96/72.0);


  msUTF8ToUniChar(symbol->character, &unicode);

  if (face->ftface->charmap &&
    face->ftface->charmap->encoding == FT_ENCODING_MS_SYMBOL)
    unicode |= 0xf000;

  glyph.index = FT_Get_Char_Index(face->ftface, unicode);
  glyph.x=0;
  glyph.y=0;
  cairo_glyph_extents(r->cr,&glyph,1,&extents);
  ox=extents.x_bearing+extents.width/2.;
  oy=extents.y_bearing+extents.height/2.;



  cairo_matrix_init_rotate(&trans,-s->rotation);

  cairo_matrix_transform_point(&trans,&ox,&oy);
  /* cairo_translate(cr,-extents.width/2,-extents.height/2); */

  cairo_translate(r->cr,x-ox,y-oy);
  cairo_rotate(r->cr, -s->rotation);

  cairo_glyph_path(r->cr,&glyph,1);

  if (s->outlinewidth) {
    msCairoSetSourceColor(r->cr, s->outlinecolor);
    cairo_set_line_width(r->cr, s->outlinewidth + 1);
    cairo_stroke_preserve(r->cr);
  }
  if(s->color) {
    msCairoSetSourceColor(r->cr, s->color);
    cairo_fill_preserve(r->cr);
  }
  cairo_new_path(r->cr);
  cairo_restore(r->cr);
  return MS_SUCCESS;
}
Esempio n. 4
0
/**
 * cairo_matrix_rotate:
 * @matrix: a #cairo_matrix_t
 * @radians: angle of rotation, in radians. The direction of rotation
 * is defined such that positive angles rotate in the direction from
 * the positive X axis toward the positive Y axis. With the default
 * axis orientation of cairo, positive angles rotate in a clockwise
 * direction.
 *
 * Applies rotation by @radians to the transformation in
 * @matrix. The effect of the new transformation is to first rotate the
 * coordinates by @radians, then apply the original transformation
 * to the coordinates.
 **/
void
cairo_matrix_rotate (cairo_matrix_t *matrix, double radians)
{
    cairo_matrix_t tmp;

    cairo_matrix_init_rotate (&tmp, radians);

    cairo_matrix_multiply (matrix, &tmp, matrix);
}
Esempio n. 5
0
static PyObject *
matrix_init_rotate (PyTypeObject *type, PyObject *args) {
  cairo_matrix_t matrix;
  double radians;

  if (!PyArg_ParseTuple(args, "d:Matrix.init_rotate", &radians))
    return NULL;

  cairo_matrix_init_rotate (&matrix, radians);
  return PycairoMatrix_FromMatrix (&matrix);
}
Esempio n. 6
0
/*!
 * \brief Scale in the coordinate system of the shape, afterwards rotate
 * @param m matrix
 * @param a angle in radians
 * @param sx horizontal scale
 * @param sy vertical scale
 * \extends _DiaMatrix
 */
void 
dia_matrix_set_angle_and_scales (DiaMatrix *m,
                                 real       a,
				 real       sx,
				 real       sy)
{
  real dx = m->x0;
  real dy = m->y0;
  cairo_matrix_init_rotate ((cairo_matrix_t *)m, a);
  cairo_matrix_scale ((cairo_matrix_t *)m, sx, sy);
  m->x0 = dx;
  m->y0 = dy;
}
Esempio n. 7
0
void Drawer::Rotation(double aAngle)
{
    mAngle = aAngle * M_PI / 180;

    double CentreX = 0.0;
    double CentreY = 0.0;
    cairo_matrix_t MatriceTranslate;
    cairo_matrix_t MatriceRotate;

    cairo_get_current_point(mCairoDC, &CentreX, &CentreY);

    cairo_matrix_init_translate(&MatriceTranslate,CentreX,CentreY);
    cairo_transform (mCairoDC, &MatriceTranslate);
    cairo_matrix_init_rotate(&MatriceRotate, mAngle);
    cairo_transform (mCairoDC, &MatriceRotate);
}
Esempio n. 8
0
static void
schgui_cairo_text_rotate(SchGUICairoDrawItem *item, double dt)
{
    SchGUICairoTextPrivate *privat = SCHGUI_CAIRO_TEXT_GET_PRIVATE(item);

    if (privat != NULL)
    {
        cairo_matrix_t transform;

        cairo_matrix_init_rotate(&transform, dt);

        cairo_matrix_transform_point(&transform, &(privat->x), &(privat->y));

        privat->angle += dt;
    }
}
void
_pango_cairo_font_private_initialize (PangoCairoFontPrivate      *cf_priv,
				      PangoCairoFont             *cfont,
				      PangoGravity                gravity,
				      const cairo_font_options_t *font_options,
				      const PangoMatrix          *pango_ctm,
				      const cairo_matrix_t       *font_matrix)
{
  cairo_matrix_t gravity_matrix;

  cf_priv->cfont = cfont;
  cf_priv->gravity = gravity;

  cf_priv->data = _pango_cairo_font_private_scaled_font_data_create (); 

  /* first apply gravity rotation, then font_matrix, such that
   * vertical italic text comes out "correct".  we don't do anything
   * like baseline adjustment etc though.  should be specially
   * handled when we support italic correction. */
  cairo_matrix_init_rotate(&gravity_matrix,
			   pango_gravity_to_rotation (cf_priv->gravity));
  cairo_matrix_multiply (&cf_priv->data->font_matrix,
			 font_matrix,
			 &gravity_matrix);

  if (pango_ctm)
    cairo_matrix_init (&cf_priv->data->ctm,
		       pango_ctm->xx,
		       pango_ctm->yx,
		       pango_ctm->xy,
		       pango_ctm->yy,
		       0., 0.);
  else
    cairo_matrix_init_identity (&cf_priv->data->ctm);

  cf_priv->data->options = cairo_font_options_copy (font_options);
  cf_priv->is_hinted = cairo_font_options_get_hint_metrics (font_options) != CAIRO_HINT_METRICS_OFF;

  cf_priv->scaled_font = NULL;
  cf_priv->hbi = NULL;
  cf_priv->glyph_extents_cache = NULL;
  cf_priv->metrics_by_lang = NULL;
}
Esempio n. 10
0
static SeedValue
seed_cairo_matrix_init_rotate (SeedContext ctx,
				  SeedObject function,
				  SeedObject this_object,
				  gsize argument_count,
				  const SeedValue arguments[],
				  SeedException *exception)
{
  gdouble angle;
  cairo_matrix_t m;

  if (argument_count != 1)
    {
      EXPECTED_EXCEPTION("init_rotate", "1 arguments");
    }

  angle = seed_value_to_double (ctx, arguments[0], exception);
  cairo_matrix_init_rotate (&m, angle);

  return seed_value_from_cairo_matrix (ctx, &m, exception);
}
Esempio n. 11
0
/**
 * whenever the model changes, this one gets called to update the view representation
 * @attention this recalculates the matrix every time, this makes sure no errors stack up
 * @attention further reading on matrix manipulations
 * @attention http://www.cairographics.org/matrix_transform/
 * @param data the model item, a bare C struct derived from ItemData
 * @param sheet_item the view item, derived from goo_canvas_group/item
 */
static void
part_changed_callback (ItemData *data, SheetItem *sheet_item)
{
	//TODO add static vars in order to skip the redraw if nothing changed
	//TODO may happen once in a while and the check is really cheap
	GSList *iter;
	GooCanvasAnchorType anchor;
	GooCanvasGroup *group;
	GooCanvasItem *canvas_item;
	PartItem *item;
	PartItemPriv *priv;
	Part *part;
	int index = 0;
	Coords pos;
	double scale_h, scale_v;


	// states
	int rotation;
	IDFlip flip;

	g_return_if_fail (sheet_item != NULL);
	g_return_if_fail (IS_PART_ITEM (sheet_item));

	item = PART_ITEM (sheet_item);
	group = GOO_CANVAS_GROUP (item);
	part = PART (data);

	priv = item->priv;

	// init the states

	flip = part_get_flip (part);
	rotation = part_get_rotation (part);

	DEGSANITY (rotation);

	scale_h = (flip & ID_FLIP_HORIZ) ? -1. : 1.;
	scale_v = (flip & ID_FLIP_VERT) ? -1. : 1.;


	item_data_get_pos (data, &pos);
	// Move the canvas item and invalidate the bbox cache.
	goo_canvas_item_set_simple_transform (GOO_CANVAS_ITEM (sheet_item),
	                                      pos.x,
	                                      pos.y,
	                                      1.0,
	                                      0.0);

	cairo_matrix_t morph, inv;
	cairo_status_t done;

	cairo_matrix_init_rotate (&morph, DEG2RAD (rotation));
	cairo_matrix_scale (&morph, scale_h, scale_v);

	inv = morph;
	done = cairo_matrix_invert (&inv);
	if (done != CAIRO_STATUS_SUCCESS) {
		g_warning ("Failed to invert matrix. This should never happen. Never!");
		return;
	}

	// rotate all items in the canvas group
	for (index = 0; index < group->items->len; index++) {
		canvas_item = GOO_CANVAS_ITEM (group->items->pdata[index]);
		goo_canvas_item_set_transform (GOO_CANVAS_ITEM (canvas_item), &morph);
	}

	// revert the rotation of all labels and change their anchor to not overlap too badly
	// this assures that the text is always horizontal and properly aligned
	anchor = angle_to_anchor (rotation);

	for (iter = priv->label_items; iter; iter = iter->next) {
		g_object_set (iter->data,
		              "anchor", anchor,
		              NULL);

		goo_canvas_item_set_transform (iter->data, &inv);

	}
	// same for label nodes
	for (iter = priv->label_nodes; iter; iter = iter->next) {
		g_object_set (iter->data,
		              "anchor", anchor, 
		              NULL);

		goo_canvas_item_set_transform (iter->data, &inv);
	}


	// Invalidate the bounding box cache.
	priv->cache_valid = FALSE;
}
Esempio n. 12
0
void Matrix::initRotate( double radians )
{
	cairo_matrix_init_rotate( &getCairoMatrix(), radians );
}
Esempio n. 13
0
void
rsvg_marker_render (RsvgMarker * self, gdouble x, gdouble y, gdouble orient, gdouble linewidth,
		    RsvgDrawingCtx * ctx)
{
    cairo_matrix_t affine, taffine;
    unsigned int i;
    gdouble rotation;
    RsvgState *state = rsvg_current_state (ctx);

    cairo_matrix_init_translate (&taffine, x, y);
    cairo_matrix_multiply (&affine, &taffine, &state->affine);

    if (self->orientAuto)
        rotation = orient;
    else
        rotation = self->orient * M_PI / 180.;

    cairo_matrix_init_rotate (&taffine, rotation);
    cairo_matrix_multiply (&affine, &taffine, &affine);

    if (self->bbox) {
        cairo_matrix_init_scale (&taffine, linewidth, linewidth);
        cairo_matrix_multiply (&affine, &taffine, &affine);
    }

    if (self->vbox.active) {

        double w, h, x, y;
        w = _rsvg_css_normalize_length (&self->width, ctx, 'h');
        h = _rsvg_css_normalize_length (&self->height, ctx, 'v');
        x = 0;
        y = 0;

        rsvg_preserve_aspect_ratio (self->preserve_aspect_ratio,
                                    self->vbox.rect.width,
                                    self->vbox.rect.height,
                                    &w, &h, &x, &y);

        x = -self->vbox.rect.x * w / self->vbox.rect.width;
        y = -self->vbox.rect.y * h / self->vbox.rect.height;

        cairo_matrix_init (&taffine,
                           w / self->vbox.rect.width,
                           0,
                           0,
                           h / self->vbox.rect.height,
                           x,
                           y);
        cairo_matrix_multiply (&affine, &taffine, &affine);
        _rsvg_push_view_box (ctx, self->vbox.rect.width, self->vbox.rect.height);
    }

    cairo_matrix_init_translate (&taffine,
                                 -_rsvg_css_normalize_length (&self->refX, ctx, 'h'),
                                 -_rsvg_css_normalize_length (&self->refY, ctx, 'v'));
    cairo_matrix_multiply (&affine, &taffine, &affine);

    rsvg_state_push (ctx);
    state = rsvg_current_state (ctx);

    rsvg_state_reinit (state);

    rsvg_state_reconstruct (state, &self->super);

    state->affine = affine;

    rsvg_push_discrete_layer (ctx);

    state = rsvg_current_state (ctx);

    if (!state->overflow) {
        if (self->vbox.active)
            rsvg_add_clipping_rect (ctx, self->vbox.rect.x, self->vbox.rect.y,
                                    self->vbox.rect.width, self->vbox.rect.height);
        else
            rsvg_add_clipping_rect (ctx, 0, 0,
                                    _rsvg_css_normalize_length (&self->width, ctx, 'h'),
                                    _rsvg_css_normalize_length (&self->height, ctx, 'v'));
    }

    for (i = 0; i < self->super.children->len; i++) {
        rsvg_state_push (ctx);

        rsvg_node_draw (g_ptr_array_index (self->super.children, i), ctx, 0);

        rsvg_state_pop (ctx);
    }
    rsvg_pop_discrete_layer (ctx);

    rsvg_state_pop (ctx);
    if (self->vbox.active)
        _rsvg_pop_view_box (ctx);
}
Esempio n. 14
0
/**
 * \brief rotate an item by an @angle increment (may be negative)
 *
 * @angle the increment the item will be rotated (usually 90° steps)
 * @center_pos if rotated as part of a group, this is the center to rotate
 *around
 */
static void part_rotate (ItemData *data, int angle, Coords *center_pos)
{
	g_return_if_fail (data);
	g_return_if_fail (IS_PART (data));

	cairo_matrix_t morph, morph_rot, local_rot;
	Part *part;
	PartPriv *priv;
	gboolean handler_connected;
	// Coords b1, b2;

	part = PART (data);

	priv = part->priv;

	// FIXME store vanilla coords, apply the morph
	// FIXME to these and store the result in the
	// FIXME instance then everything will be fine
	// XXX also prevents rounding yiggle up downs

	angle /= 90;
	angle *= 90;

	cairo_matrix_init_rotate (&local_rot, (double)angle * M_PI / 180.);

	cairo_matrix_multiply (item_data_get_rotate (data), item_data_get_rotate (data), &local_rot);

	morph_rot = *(item_data_get_rotate (data));

	cairo_matrix_multiply (&morph, &morph_rot, item_data_get_translate (data));

	Coords delta_to_center, delta_to_center_transformed;
	Coords delta_to_apply, delta_bbox;
	Coords bbox_center, bbox_center_transformed;
	Coords item_pos;

// get bbox
#if 0 // this causes #115 to reappear
	item_data_get_relative_bbox (ITEM_DATA (part), &b1, &b2);
	bbox_center = coords_average (&b1, &b2);
#endif
	item_data_get_pos (ITEM_DATA (part), &item_pos);

	Coords rotation_center;

	if (center_pos == NULL) {
		rotation_center = coords_sum (&bbox_center, &item_pos);
	} else {
		rotation_center = *center_pos;
	}

	delta_to_center_transformed = delta_to_center = coords_sub (&rotation_center, &item_pos);
	cairo_matrix_transform_point (&local_rot, &(delta_to_center_transformed.x),
	                              &(delta_to_center_transformed.y));

	delta_to_apply = coords_sub (&delta_to_center, &delta_to_center_transformed);

#define DEBUG_THIS 0
	// use the cairo matrix funcs to transform the pin
	// positions relative to the item center
	// this is only indirectly related to displayin
	// HINT: we need to modify the actual pins to make the
	// pin tests work being used to detect connections

	gint i;
	gdouble x, y;
	// Rotate the pins.
	for (i = 0; i < priv->num_pins; i++) {
		x = priv->pins_orig[i].offset.x;
		y = priv->pins_orig[i].offset.y;
		cairo_matrix_transform_point (&morph_rot, &x, &y);

		if (fabs (x) < 1e-2)
			x = 0.0;
		if (fabs (y) < 1e-2)
			y = 0.0;

		priv->pins[i].offset.x = x;
		priv->pins[i].offset.y = y;
	}

	item_data_move (data, &delta_to_apply);

	handler_connected = g_signal_handler_is_connected (G_OBJECT (data), data->changed_handler_id);
	if (handler_connected) {
		g_signal_emit_by_name (G_OBJECT (data), "changed");
	} else {
		NG_DEBUG ("handler not yet registerd.");
	}
	NG_DEBUG ("\n\n");
}
Esempio n. 15
0
static void
xviewer_print_draw_page (GtkPrintOperation *operation,
                         GtkPrintContext   *context,
                         gint               page_nr,
                         gpointer           user_data)
{
    cairo_t *cr;
    gdouble dpi_x, dpi_y;
    gdouble x0, y0;
    gdouble scale_factor;
    gdouble p_width, p_height;
    gint width, height;
    XviewerPrintData *data;
    GtkPageSetup *page_setup;

    xviewer_debug (DEBUG_PRINTING);

    data = (XviewerPrintData *) user_data;

    scale_factor = data->scale_factor/100;

    dpi_x = gtk_print_context_get_dpi_x (context);
    dpi_y = gtk_print_context_get_dpi_y (context);

    switch (data->unit) {
    case GTK_UNIT_INCH:
        x0 = data->left_margin * dpi_x;
        y0 = data->top_margin  * dpi_y;
        break;
    case GTK_UNIT_MM:
        x0 = data->left_margin * dpi_x/25.4;
        y0 = data->top_margin  * dpi_y/25.4;
        break;
    default:
        g_assert_not_reached ();
    }

    cr = gtk_print_context_get_cairo_context (context);

    cairo_translate (cr, x0, y0);

    page_setup = gtk_print_context_get_page_setup (context);
    p_width =  gtk_page_setup_get_page_width (page_setup, GTK_UNIT_POINTS);
    p_height = gtk_page_setup_get_page_height (page_setup, GTK_UNIT_POINTS);

    xviewer_image_get_size (data->image, &width, &height);

    /* this is both a workaround for a bug in cairo's PDF backend, and
       a way to ensure we are not printing outside the page margins */
    cairo_rectangle (cr, 0, 0, MIN (width*scale_factor, p_width), MIN (height*scale_factor, p_height));
    cairo_clip (cr);

    cairo_scale (cr, scale_factor, scale_factor);

#ifdef HAVE_RSVG
    if (xviewer_image_is_svg (data->image))
    {
        RsvgHandle *svg = xviewer_image_get_svg (data->image);

        rsvg_handle_render_cairo (svg, cr);
        return;
    } else
#endif
        /* JPEGs can be attached to the cairo surface which simply embeds the JPEG file into the
         * destination PDF skipping (PNG-)recompression. This should reduce PDF sizes enormously. */
        if (xviewer_image_is_jpeg (data->image) && _cairo_ctx_supports_jpg_metadata (cr))
        {
            GFile *file;
            char *img_data;
            gsize data_len;
            cairo_surface_t *surface = NULL;

            xviewer_debug_message (DEBUG_PRINTING, "Attaching image to cairo surface");

            file = xviewer_image_get_file (data->image);
            if (g_file_load_contents (file, NULL, &img_data, &data_len, NULL, NULL))
            {
                XviewerTransform *tf = xviewer_image_get_transform (data->image);
                XviewerTransform *auto_tf = xviewer_image_get_autorotate_transform (data->image);
                cairo_matrix_t mx, mx2;

                if (!tf && auto_tf) {
                    /* If only autorotation data present,
                     * make it the normal rotation. */
                    tf = auto_tf;
                    auto_tf = NULL;
                }

                /* Care must be taken with height and width values. They are not the original
                 * values but were affected by the transformation. As the surface needs to be
                 * generated using the original dimensions they might need to be flipped. */
                if (tf) {
                    if (auto_tf) {
                        /* If we have an autorotation apply
                         * it before the others */
                        tf = xviewer_transform_compose (auto_tf, tf);
                    }

                    switch (xviewer_transform_get_transform_type (tf)) {
                    case XVIEWER_TRANSFORM_ROT_90:
                        surface = cairo_image_surface_create (
                                      CAIRO_FORMAT_RGB24, height, width);
                        cairo_rotate (cr, 90.0 * (G_PI/180.0));
                        cairo_translate (cr, 0.0, -width);
                        break;
                    case XVIEWER_TRANSFORM_ROT_180:
                        surface = cairo_image_surface_create (
                                      CAIRO_FORMAT_RGB24, width, height);
                        cairo_rotate (cr, 180.0 * (G_PI/180.0));
                        cairo_translate (cr, -width, -height);
                        break;
                    case XVIEWER_TRANSFORM_ROT_270:
                        surface = cairo_image_surface_create (
                                      CAIRO_FORMAT_RGB24, height, width);
                        cairo_rotate (cr, 270.0 * (G_PI/180.0));
                        cairo_translate (cr, -height, 0.0);
                        break;
                    case XVIEWER_TRANSFORM_FLIP_HORIZONTAL:
                        surface = cairo_image_surface_create (
                                      CAIRO_FORMAT_RGB24, width, height);
                        cairo_matrix_init_identity (&mx);
                        _xviewer_cairo_matrix_flip (&mx2, &mx, TRUE, FALSE);
                        cairo_transform (cr, &mx2);
                        cairo_translate (cr, -width, 0.0);
                        break;
                    case XVIEWER_TRANSFORM_FLIP_VERTICAL:
                        surface = cairo_image_surface_create (
                                      CAIRO_FORMAT_RGB24, width, height);
                        cairo_matrix_init_identity (&mx);
                        _xviewer_cairo_matrix_flip (&mx2, &mx, FALSE, TRUE);
                        cairo_transform (cr, &mx2);
                        cairo_translate (cr, 0.0, -height);
                        break;
                    case XVIEWER_TRANSFORM_TRANSPOSE:
                        surface = cairo_image_surface_create (
                                      CAIRO_FORMAT_RGB24, height, width);
                        cairo_matrix_init_rotate (&mx, 90.0 * (G_PI/180.0));
                        cairo_matrix_init_identity (&mx2);
                        _xviewer_cairo_matrix_flip (&mx2, &mx2, TRUE, FALSE);
                        cairo_matrix_multiply (&mx2, &mx, &mx2);
                        cairo_transform (cr, &mx2);
                        break;
                    case XVIEWER_TRANSFORM_TRANSVERSE:
                        surface = cairo_image_surface_create (
                                      CAIRO_FORMAT_RGB24, height, width);
                        cairo_matrix_init_rotate (&mx, 90.0 * (G_PI/180.0));
                        cairo_matrix_init_identity (&mx2);
                        _xviewer_cairo_matrix_flip (&mx2, &mx2, FALSE, TRUE);
                        cairo_matrix_multiply (&mx2, &mx, &mx2);
                        cairo_transform (cr, &mx2);
                        cairo_translate (cr, -height , -width);
                        break;
                    case XVIEWER_TRANSFORM_NONE:
                    default:
                        surface = cairo_image_surface_create (
                                      CAIRO_FORMAT_RGB24, width, height);
                        break;
                    }
                }

                if (!surface)
                    surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
                                                          width, height);
                cairo_surface_set_mime_data (surface,
                                             CAIRO_MIME_TYPE_JPEG,
                                             (unsigned char*)img_data, data_len,
                                             g_free, img_data);
                cairo_set_source_surface (cr, surface, 0, 0);
                cairo_paint (cr);
                cairo_surface_destroy (surface);
                g_object_unref (file);
                return;
            }
            g_object_unref (file);

        }

    {
        GdkPixbuf *pixbuf;

        pixbuf = xviewer_image_get_pixbuf (data->image);
        gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
        cairo_paint (cr);
        g_object_unref (pixbuf);
    }
}
Esempio n. 16
0
/**
 * rotate an item by an @angle increment (may be negative)
 * @angle the increment the item will be rotated (usually 90° steps)
 * @center_pos if rotated as part of a group, this is the center to rotate around
 * FIXME XXX TODO an issue arises as the center changes with part_rotate
 * FIXME XXX TODO the view callback needs to compensate this somehow
 */
static void
part_rotate (ItemData *data, int angle, Coords *center_pos)
{
	cairo_matrix_t affine;
	double x, y;
	Part *part;
	PartPriv *priv;
	int i, tot_rotation;
	Coords b1, b2;
	Coords part_center_before, part_center_after, delta;
	Coords delta_cp_before, delta_cp_after;
	gboolean handler_connected;

	g_return_if_fail (data);
	g_return_if_fail (IS_PART (data));

	if (angle == 0)
		return;

	part = PART (data);

	priv = part->priv;

	tot_rotation = (priv->rotation + angle + 360) % 360;

	NG_DEBUG ("rotation: angle=%i tot_rotation=%i", angle, tot_rotation);

	// use the cairo matrix funcs to transform the pin
	// positions relative to the item center
	// this is only indirectly related to displaying
	cairo_matrix_init_rotate (&affine, (double)angle * M_PI / 180.);

	if (center_pos) {
		delta_cp_before = coords_sub (&part_center_before, center_pos);
		delta_cp_after = delta_cp_before;
		cairo_matrix_transform_point (&affine, &delta_cp_after.x, &delta_cp_after.y);
	}

	priv->rotation = tot_rotation;
	angle = tot_rotation;

	// Rotate the pins.
	for (i = 0; i < priv->num_pins; i++) {
		x = priv->pins[i].offset.x;
		y = priv->pins[i].offset.y;
		cairo_matrix_transform_point (&affine, &x, &y);

		if (fabs (x) < 1e-2)
			x = 0.0;
		if (fabs (y) < 1e-2)
			y = 0.0;

		priv->pins[i].offset.x = x;
		priv->pins[i].offset.y = y;
	}

	// Rotate the bounding box, recenter to old center
	item_data_get_relative_bbox (ITEM_DATA (part), &b1, &b2);
	part_center_before = coords_average (&b1, &b2);

	cairo_matrix_transform_point (&affine, &b1.x, &b1.y);
	cairo_matrix_transform_point (&affine, &b2.x, &b2.y);

	item_data_set_relative_bbox (ITEM_DATA (part), &b1, &b2);
	part_center_after = coords_average (&b1, &b2);

	delta = coords_sub (&part_center_before, &part_center_after);
	if (center_pos) {
		Coords diff = coords_sub (&delta_cp_after, &delta_cp_before);
		coords_add (&delta, &diff);
	}
	item_data_move (data, &delta);
	item_data_snap (data);

	handler_connected = g_signal_handler_is_connected (G_OBJECT (part),
	                                   ITEM_DATA (part)->rotated_handler_id);
	if (handler_connected) {
		g_signal_emit_by_name (G_OBJECT (part),
		                       "rotated", tot_rotation);
	}

	handler_connected = g_signal_handler_is_connected (G_OBJECT (part),
	                                   ITEM_DATA (part)->changed_handler_id);
	if (handler_connected) {
		g_signal_emit_by_name (G_OBJECT (part),
		                       "changed");
	}
}
Esempio n. 17
0
void Drawer::DrawCurve(const Point& aPrevPoint, const Point& aStartPoint, const Point& aEndPoint, const Point& aNextPoint, double& aCoef)
{
    if (aCoef < 0.0)
        aCoef = 0.0;
    else if (aCoef > 1.0)
        aCoef = 1.0;

    double AngleRadianR0toR1 = 0.0;
    cairo_matrix_t TranslateMatrixR0toR1;
    cairo_matrix_t RotateMatrixR0toR1;
    Point StartPointInR1 = aStartPoint;
    Point EndPointInR1 = aEndPoint;

    double AngleRadianR0toR2 = 0.0;
    cairo_matrix_t TranslateMatrixR0toR2;
    cairo_matrix_t RotateMatrixR0toR2;
    Point StartPointInR2 = aStartPoint;
    Point EndPointInR2 = aEndPoint;

    double DistTanStart  = 0.0;
    double DistTanEnd    = 0.0;

    Point StartTanPoint(0.0,0.0);
    Point StartTanPointInR1(0,0);
    Point EndTanPoint(0.0,0.0);
    Point EndTanPointInR2(0,0);

    // Il faut que 'aPrevPoint' et 'aStartPoint' soit non confondu et 'aEndPoint' et 'aNextPoint' aussi
    if ((aPrevPoint != aStartPoint) && (aEndPoint != aNextPoint))
    {
        // Calcul de l'angle de rotation du nouveau repère R1 (aPrevPoint/aStartPoint)
        AngleRadianR0toR1 = atan2 (aStartPoint.Y - aPrevPoint.Y, aStartPoint.X - aPrevPoint.X);

        // Translation du repère au point 'aPrevPoint'
        cairo_matrix_init_translate(&TranslateMatrixR0toR1, aPrevPoint.X, aPrevPoint.Y);
        // Rotation du repère d'angle 'AngleRadianR1'
        cairo_matrix_init_rotate(&RotateMatrixR0toR1, AngleRadianR0toR1);

        // Calcul des coordonnées des points aStartPoint, aEndPoint, TanStartPointLocal dans le repère R1
        // Point B et C R0 => Point B et C R1
        cairo_matrix_invert(&TranslateMatrixR0toR1);
        cairo_matrix_transform_point(&TranslateMatrixR0toR1, &EndPointInR1.X, &EndPointInR1.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR1, &StartPointInR1.X, &StartPointInR1.Y);
        cairo_matrix_invert(&RotateMatrixR0toR1);
        cairo_matrix_transform_point(&RotateMatrixR0toR1, &EndPointInR1.X, &EndPointInR1.Y);
        cairo_matrix_transform_point(&RotateMatrixR0toR1, &StartPointInR1.X, &StartPointInR1.Y);

        // Coordonnées de StartPointTan dans le repère R1
        StartTanPointInR1.X = EndPointInR1.X;
        StartTanPointInR1.Y = 0.0;

        // Sauvegarde de la distance du point pour le tracer de la tangente
        DistTanStart = abs(StartTanPointInR1.X - StartPointInR1.X);

        /////////////

        // Calcul de l'angle de rotation du nouveau repère R1 (aPrevPoint/aStartPoint)
        AngleRadianR0toR2 = atan2 (aEndPoint.Y - aNextPoint.Y, aEndPoint.X - aNextPoint.X);

        // Translation du repère au point 'aNextPoint'
        cairo_matrix_init_translate(&TranslateMatrixR0toR2, aNextPoint.X, aNextPoint.Y);
        // Rotation du repère d'angle 'AngleRadianR0toR2'
        cairo_matrix_init_rotate(&RotateMatrixR0toR2, AngleRadianR0toR2);

        // Calcul des coordonnées du Point aStartPoint dans le repère R2
        // Point B et C R0 => Point B et C R2
        cairo_matrix_invert(&TranslateMatrixR0toR2);
        cairo_matrix_transform_point(&TranslateMatrixR0toR2, &StartPointInR2.X, &StartPointInR2.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR2, &EndPointInR2.X, &EndPointInR2.Y);
        cairo_matrix_invert(&RotateMatrixR0toR2);
        cairo_matrix_transform_point(&RotateMatrixR0toR2, &StartPointInR2.X, &StartPointInR2.Y);
        cairo_matrix_transform_point(&RotateMatrixR0toR2, &EndPointInR2.X, &EndPointInR2.Y);

        // Coordonnées de EndPointTan dans le repère R2
        EndTanPointInR2.X = StartPointInR2.X;
        EndTanPointInR2.Y = 0.0;

        // Sauvegarde de la distance du point pour le tracer de la tangente
        DistTanEnd = abs(EndTanPointInR2.X - EndPointInR2.X);

        // Cas : (12) <=> DistTan12 / 2 et (34) <=> DistTan34 / 2
        // Coordonnées de TanStartPoint dans le repère R1
        StartTanPoint.X = StartPointInR1.X + DistTanStart * 0.5 * aCoef;
        StartTanPoint.Y = 0.0;
        cairo_matrix_invert(&RotateMatrixR0toR1);
        cairo_matrix_transform_point(&RotateMatrixR0toR1, &StartTanPoint.X, &StartTanPoint.Y);
        cairo_matrix_invert(&TranslateMatrixR0toR1);
        cairo_matrix_transform_point(&TranslateMatrixR0toR1, &StartTanPoint.X, &StartTanPoint.Y);
        // Coordonnées de TanEndPoint dans le repère R1
        EndTanPoint.X = EndPointInR2.X + DistTanEnd * 0.5 * aCoef;
        EndTanPoint.Y = 0.0;
        cairo_matrix_invert(&RotateMatrixR0toR2);
        cairo_matrix_transform_point(&RotateMatrixR0toR2, &EndTanPoint.X, &EndTanPoint.Y);
        cairo_matrix_invert(&TranslateMatrixR0toR2);
        cairo_matrix_transform_point(&TranslateMatrixR0toR2, &EndTanPoint.X, &EndTanPoint.Y);


        cairo_move_to(mCairoDC, aStartPoint.X, aStartPoint.Y);
        cairo_curve_to(mCairoDC, StartTanPoint.X,StartTanPoint.Y, EndTanPoint.X, EndTanPoint.Y, aEndPoint.X, aEndPoint.Y);
        cairo_set_line_width(mCairoDC, 3);
        cairo_stroke(mCairoDC);
    }
}
Esempio n. 18
0
static void wire_rotate (ItemData *data, int angle, Coords *center_pos)
{
    cairo_matrix_t affine;
    double x, y;
    Wire *wire;
    WirePriv *priv;
    Coords b1, b2;
    Coords wire_center_before, wire_center_after, delta;
    Coords delta_cp_before, delta_cp_after;

    g_return_if_fail (data != NULL);
    g_return_if_fail (IS_WIRE (data));

    if (angle == 0)
        return;

    wire = WIRE (data);

    item_data_get_absolute_bbox (ITEM_DATA (wire), &b1, &b2);
    wire_center_before = coords_average (&b1, &b2);

    priv = wire->priv;

    if (priv->direction == WIRE_DIR_VERT) {
        priv->direction = WIRE_DIR_HORIZ;
    } else if (priv->direction == WIRE_DIR_HORIZ) {
        priv->direction = WIRE_DIR_VERT;
    }

    cairo_matrix_init_rotate (&affine, (double)angle * M_PI / 180.0);

    // Rotate the wire's end point.
    x = priv->length.x;
    y = priv->length.y;

    cairo_matrix_transform_point (&affine, &x, &y);

    if (fabs (x) < 1e-2)
        x = 0.0;
    if (fabs (y) < 1e-2)
        y = 0.0;

    priv->length.x = x;
    priv->length.y = y;

    if (center_pos) {
        delta_cp_before = coords_sub (&wire_center_before, center_pos);
        delta_cp_after = delta_cp_before;
        cairo_matrix_transform_point (&affine, &delta_cp_after.x, &delta_cp_after.y);
    }

    // Update bounding box.
    wire_update_bbox (wire);

    item_data_get_absolute_bbox (ITEM_DATA (wire), &b1, &b2);
    wire_center_after = coords_average (&b1, &b2);

    delta = coords_sub (&wire_center_before, &wire_center_after);
    if (center_pos) {
        Coords diff = coords_sub (&delta_cp_after, &delta_cp_before);
        coords_add (&delta, &diff);
    }
    item_data_move (ITEM_DATA (wire), &delta);
    //	item_data_snap (ITEM_DATA (wire), NULL); //FIXME XXX

    // Let the views (canvas items) know about the rotation.
    g_signal_emit_by_name (G_OBJECT (wire), "rotated", angle); // legacy
    g_signal_emit_by_name (G_OBJECT (wire), "changed");
}
Esempio n. 19
0
void Drawer::DrawCurveDebug(const Point& aPrevPoint, const Point& aStartPoint, const Point& aEndPoint, const Point& aNextPoint, double& aCoef)
{
    if (aCoef < 0.0)
        aCoef = 0.0;
    else if (aCoef > 1.0)
        aCoef = 1.0;

    Point PrevPointLocal = aPrevPoint;
    Point StartPointLocal = aStartPoint;
    Point EndPointLocal = aEndPoint;
    Point NextPointLocal = aNextPoint;

    Point TanStartPointLocalCas1(0.0,0.0);
    Point TanStartPointLocalCas1R1(0.0,0.0);
    Point TanEndPointLocalCas1(0.0,0.0);
    Point TanEndPointLocalCas1R2(0.0,0.0);

    Point TanStartPointLocalCas2(0.0,0.0);
    Point TanStartPointLocalCas2R1(0.0,0.0);
    Point TanEndPointLocalCas2(0.0,0.0);
    Point TanEndPointLocalCas2R2(0.0,0.0);

    Point TanStartPointLocalCas3(0.0,0.0);
    Point TanStartPointLocalCas3R1(0.0,0.0);
    Point TanEndPointLocalCas3(0.0,0.0);
    Point TanEndPointLocalCas3R2(0.0,0.0);

    Point TanStartPointLocalCas4(0.0,0.0);
    Point TanEndPointLocalCas4(0.0,0.0);
    /* DEBUG
    std::cout << "PrevPointLocal  = (" << PrevPointLocal.X << "," << PrevPointLocal.Y << ")" << std::endl;
    std::cout << "StartPointLocal = (" << StartPointLocal.X << "," << StartPointLocal.Y << ")" << std::endl;
    std::cout << "EndPointLocal   = (" << EndPointLocal.X << "," << EndPointLocal.Y << ")" << std::endl;
    std::cout << "NextPointLocal  = (" << NextPointLocal.X << "," << NextPointLocal.Y << ")" << std::endl << std::endl; */

    Point StartPointTan(0,0);
    Point EndPointTan(0,0);

    double DistTan12  = 0.0;
    double DistTan34  = 0.0;
    double MinDistTan = 0.0;

    double AngleRadianR1 = 0.0;
    cairo_matrix_t TranslateMatrixR0toR1;
    cairo_matrix_t RotateMatrixR0toR1;
    Point StartPointLocalR1 = StartPointLocal;
    Point EndPointR1(0,0);
    Point StartPointTanR1(0,0);

    double AngleRadianR2 = 0.0;
    cairo_matrix_t TranslateMatrixR0toR2;
    cairo_matrix_t RotateMatrixR0toR2;
    Point StartPointLocalR2(0,0);
    Point EndPointR2 = EndPointLocal;
    Point EndPointTanR2(0,0);

    // Il faut que 'aPrevPoint' et 'aStartPoint' soit non confondu et 'aEndPoint' et 'aNextPoint' aussi
    if ((PrevPointLocal != StartPointLocal) && (EndPointLocal != NextPointLocal))
    {
        // Calcul de l'angle de rotation du nouveau repère R1 (aPrevPoint/aStartPoint)
        AngleRadianR1 = atan2 (StartPointLocal.Y - PrevPointLocal.Y, StartPointLocal.X - PrevPointLocal.X);

        /* DEBUG
        std::cout << "AngleRadianR1 = " << AngleRadianR1 << std::endl << std::endl;*/
        SetColor(0,0,0);
        MoveTo(PrevPointLocal);
        DrawLine(StartPointLocal,1);
        //DrawArc (PrevPointLocal,30, AngleRadianR1,1);

        // Translation du repère au point 'aPrevPoint'
        cairo_matrix_init_translate(&TranslateMatrixR0toR1, PrevPointLocal.X, PrevPointLocal.Y);
//      cairo_transform(mCairoDC, &TranslateMatrixR1);

        // Rotation du repère d'angle 'AngleRadianR1'
        cairo_matrix_init_rotate(&RotateMatrixR0toR1, AngleRadianR1);
//      cairo_transform(mCairoDC, &RotateMatrixR1);

        // Calcul des coordonnées des points StartPointLocal, EndPointLocal, TanStartPointLocal dans le repère R1
        // Point B et C R0 => Point B et C R1
        cairo_matrix_invert(&TranslateMatrixR0toR1);
        cairo_matrix_transform_point(&TranslateMatrixR0toR1, &EndPointLocal.X, &EndPointLocal.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR1, &StartPointLocalR1.X, &StartPointLocalR1.Y);
        cairo_matrix_invert(&RotateMatrixR0toR1);
        cairo_matrix_transform_point(&RotateMatrixR0toR1, &EndPointLocal.X, &EndPointLocal.Y);
        cairo_matrix_transform_point(&RotateMatrixR0toR1, &StartPointLocalR1.X, &StartPointLocalR1.Y);
        EndPointR1 = EndPointLocal;
        // Reset du EndPointLocal
        EndPointLocal = aEndPoint;

        /* DEBUG
        std::cout << "EndPointR1     = (" << EndPointR1.X << "," << EndPointR1.Y << ")" << std::endl;*/
//      DrawRepere(0.0,0.0,0.6);

        // Coordonnées de StartPointTan dans le repère R1
        StartPointTanR1.X = EndPointR1.X;
        StartPointTanR1.Y = 0.0;

        // Sauvegarde de la distance du point pour le tracer de la tangente
        DistTan12 = abs(StartPointTanR1.X - StartPointLocalR1.X);
        MinDistTan = DistTan12;

        /* DEBUG
        std::cout << "StartPointTanR1= (" << StartPointTanR1.X << "," << StartPointTanR1.Y << ")" << std::endl << std::endl;*/
//      MoveTo(StartPointTanR1);
//      DrawLine(EndPointR1,1);

        // Calcul des coordonnées de StartPointTan dans le repère R0 (Origine)
//      StartPointTan = StartPointTanR1;
//      cairo_matrix_invert(&RotateMatrixR1);
//      cairo_matrix_transform_point(&RotateMatrixR1, &StartPointTan.X, &StartPointTan.Y);
//      cairo_matrix_invert(&TranslateMatrixR1);
//      cairo_matrix_transform_point(&TranslateMatrixR1, &StartPointTan.X, &StartPointTan.Y);

//      cairo_identity_matrix(mCairoDC);

        /* DEBUG
        std::cout << "StartPointTan = (" << StartPointTan.X << "," << StartPointTan.Y << ")" << std::endl << std::endl << std::endl;*/
//      SetColor(0,0,0);
//      DrawPoint(StartPointTan,3);

        /////////////

        // Calcul de l'angle de rotation du nouveau repère R1 (aPrevPoint/aStartPoint)
        AngleRadianR2 = atan2 (EndPointLocal.Y - NextPointLocal.Y, EndPointLocal.X - NextPointLocal.X);

        /* DEBUG
        std::cout << "AngleRadianR1 = " << AngleRadianR1 << std::endl << std::endl;*/
//      SetColor(0,0,0);
//      MoveTo(NextPointLocal);
//      DrawLine(EndPointLocal,1);
        //DrawArc (NextPointLocal,30, AngleRadianR2,1);

        // Translation du repère au point 'aNextPoint'
        cairo_matrix_init_translate(&TranslateMatrixR0toR2, NextPointLocal.X, NextPointLocal.Y);
//      cairo_transform(mCairoDC, &TranslateMatrixR2);

        // Rotation du repère d'angle 'AngleRadianR2'
        cairo_matrix_init_rotate(&RotateMatrixR0toR2, AngleRadianR2);
//      cairo_transform(mCairoDC, &RotateMatrixR2);

        // Calcul des coordonnées du Point StartPointLocal dans le repère R2
        // Point B et C R0 => Point B et C R2
        cairo_matrix_invert(&TranslateMatrixR0toR2);
        cairo_matrix_transform_point(&TranslateMatrixR0toR2, &StartPointLocal.X, &StartPointLocal.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR2, &EndPointR2.X, &EndPointR2.Y);
        cairo_matrix_invert(&RotateMatrixR0toR2);
        cairo_matrix_transform_point(&RotateMatrixR0toR2, &StartPointLocal.X, &StartPointLocal.Y);
        cairo_matrix_transform_point(&RotateMatrixR0toR2, &EndPointR2.X, &EndPointR2.Y);
        StartPointLocalR2 = StartPointLocal;
        // Reset du StartPointLocal
        StartPointLocal = aStartPoint;

        /* DEBUG
        std::cout << "StartPointLocalR2 = (" << StartPointLocalR2.X << "," << StartPointLocalR2.Y << ")" << std::endl;*/
//      DrawRepere(0.0,0.0,0.6);

        // Coordonnées de EndPointTan dans le repère R2
        EndPointTanR2.X = StartPointLocalR2.X;
        EndPointTanR2.Y = 0.0;

        // Sauvegarde de la distance du point pour le tracer de la tangente
        DistTan34 = abs(EndPointTanR2.X - EndPointR2.X);
        if(DistTan34 < MinDistTan)
            MinDistTan = DistTan34;

        /* DEBUG
        std::cout << "EndPointTanR2     = (" << EndPointTanR2.X << "," << EndPointTanR2.Y << ")" << std::endl << std::endl;*/
//      MoveTo(EndPointTanR2);
//      DrawLine(StartPointLocalR2,1);

        // Calcul des coordonnées de EndPointTan dans le repère R0 (Origine)
//      EndPointTan = EndPointTanR2;
//      cairo_matrix_invert(&RotateMatrixR2);
//      cairo_matrix_transform_point(&RotateMatrixR2, &EndPointTan.X, &EndPointTan.Y);
//      cairo_matrix_invert(&TranslateMatrixR2);
//      cairo_matrix_transform_point(&TranslateMatrixR2, &EndPointTan.X, &EndPointTan.Y);

//      cairo_identity_matrix(mCairoDC);

        /* DEBUG
        std::cout << "EndPointTan = (" << EndPointTan.X << "," << EndPointTan.Y << ")" << std::endl;
        std::cout << "MinDistTan = " << MinDistTan << std::endl << std::endl << std::endl;*/
//      DrawPoint(EndPointTan,3);

        /* DEBUG
        std::cout << "Valeurs : " << std::endl;
        std::cout << "DistTan (1->2) = " << DistTan12 << std::endl;
        std::cout << "DistTan (3->4) = " << DistTan34 << std::endl;
        std::cout << "MinDistTan     = " << MinDistTan << std::endl << std::endl;*/

        cairo_matrix_invert(&RotateMatrixR0toR1);
        cairo_matrix_invert(&TranslateMatrixR0toR1);
        cairo_matrix_invert(&RotateMatrixR0toR2);
        cairo_matrix_invert(&TranslateMatrixR0toR2);

// 1er cas : (12) <=> DistTan12 et (34) <=> DistTan34
        // Coordonnées de TanStartPointLocal dans le repère R1
        TanStartPointLocalCas1R1.X = StartPointLocalR1.X + DistTan12 * aCoef;
        TanStartPointLocalCas1R1.Y = 0.0;
        TanStartPointLocalCas1 = TanStartPointLocalCas1R1;
        cairo_matrix_transform_point(&RotateMatrixR0toR1, &TanStartPointLocalCas1.X, &TanStartPointLocalCas1.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR1, &TanStartPointLocalCas1.X, &TanStartPointLocalCas1.Y);
        // Coordonnées de TanEndPointLocal dans le repère R1
        TanEndPointLocalCas1R2.X = EndPointR2.X + DistTan34 * aCoef;
        TanEndPointLocalCas1R2.Y = 0.0;
        TanEndPointLocalCas1 = TanEndPointLocalCas1R2;
        cairo_matrix_transform_point(&RotateMatrixR0toR2, &TanEndPointLocalCas1.X, &TanEndPointLocalCas1.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR2, &TanEndPointLocalCas1.X, &TanEndPointLocalCas1.Y);

        SetColor(1,0,0);
        DrawPoint(TanStartPointLocalCas1,3);
        DrawPoint(TanEndPointLocalCas1,3);

        cairo_move_to(mCairoDC, aStartPoint.X, aStartPoint.Y);
        cairo_curve_to(mCairoDC, TanStartPointLocalCas1.X,TanStartPointLocalCas1.Y, TanEndPointLocalCas1.X, TanEndPointLocalCas1.Y, aEndPoint.X, aEndPoint.Y);
        cairo_set_line_width(mCairoDC, 3);
        cairo_stroke(mCairoDC);

// 2eme cas : (12) <=> DistTan12 / 2 et (34) <=> DistTan34 / 2
        // Coordonnées de TanStartPointLocal dans le repère R1
        TanStartPointLocalCas2R1.X = StartPointLocalR1.X + DistTan12 * 0.5 * aCoef;
        TanStartPointLocalCas2R1.Y = 0.0;
        TanStartPointLocalCas2 = TanStartPointLocalCas2R1;
        cairo_matrix_transform_point(&RotateMatrixR0toR1, &TanStartPointLocalCas2.X, &TanStartPointLocalCas2.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR1, &TanStartPointLocalCas2.X, &TanStartPointLocalCas2.Y);
        // Coordonnées de TanEndPointLocal dans le repère R1
        TanEndPointLocalCas2R2.X = EndPointR2.X + DistTan34 * 0.5 * aCoef;
        TanEndPointLocalCas2R2.Y = 0.0;
        TanEndPointLocalCas2 = TanEndPointLocalCas2R2;
        cairo_matrix_transform_point(&RotateMatrixR0toR2, &TanEndPointLocalCas2.X, &TanEndPointLocalCas2.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR2, &TanEndPointLocalCas2.X, &TanEndPointLocalCas2.Y);

        SetColor(0,1,0);
        DrawPoint(TanStartPointLocalCas2,3);
        DrawPoint(TanEndPointLocalCas2,3);

        cairo_move_to(mCairoDC, aStartPoint.X, aStartPoint.Y);
        cairo_curve_to(mCairoDC, TanStartPointLocalCas2.X,TanStartPointLocalCas2.Y, TanEndPointLocalCas2.X, TanEndPointLocalCas2.Y, aEndPoint.X, aEndPoint.Y);
        cairo_set_line_width(mCairoDC, 3);
        cairo_stroke(mCairoDC);



// 3ème cas : (12) <=> MinDistTan et (34) <=> MinDistTan
        // Coordonnées de TanStartPointLocal dans le repère R1
        TanStartPointLocalCas3.X = StartPointLocalR1.X + MinDistTan * aCoef;
        TanStartPointLocalCas3.Y = 0.0;
        cairo_matrix_transform_point(&RotateMatrixR0toR1, &TanStartPointLocalCas3.X, &TanStartPointLocalCas3.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR1, &TanStartPointLocalCas3.X, &TanStartPointLocalCas3.Y);
        // Coordonnées de TanEndPointLocal dans le repère R1
        TanEndPointLocalCas3.X = EndPointR2.X + MinDistTan * aCoef;
        TanEndPointLocalCas3.Y = 0.0;
        cairo_matrix_transform_point(&RotateMatrixR0toR2, &TanEndPointLocalCas3.X, &TanEndPointLocalCas3.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR2, &TanEndPointLocalCas3.X, &TanEndPointLocalCas3.Y);

        SetColor(0,0,1);
        DrawPoint(TanStartPointLocalCas3,3);
        DrawPoint(TanEndPointLocalCas3,3);

        cairo_move_to(mCairoDC, aStartPoint.X, aStartPoint.Y);
        cairo_curve_to(mCairoDC, TanStartPointLocalCas3.X,TanStartPointLocalCas3.Y, TanEndPointLocalCas3.X, TanEndPointLocalCas3.Y, aEndPoint.X, aEndPoint.Y);
        cairo_set_line_width(mCairoDC, 3);
        cairo_stroke(mCairoDC);

// 4ème cas : (12) <=> MinDistTan / 2 et (34) <=> MinDistTan / 2
        // Coordonnées de TanStartPointLocal dans le repère R1
        TanStartPointLocalCas4.X = StartPointLocalR1.X + MinDistTan * 0.5 * aCoef;
        TanStartPointLocalCas4.Y = 0.0;
        cairo_matrix_transform_point(&RotateMatrixR0toR1, &TanStartPointLocalCas4.X, &TanStartPointLocalCas4.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR1, &TanStartPointLocalCas4.X, &TanStartPointLocalCas4.Y);
        // Coordonnées de TanEndPointLocal dans le repère R1
        TanEndPointLocalCas4.X = EndPointR2.X + MinDistTan * 0.5 * aCoef;
        TanEndPointLocalCas4.Y = 0.0;
        cairo_matrix_transform_point(&RotateMatrixR0toR2, &TanEndPointLocalCas4.X, &TanEndPointLocalCas4.Y);
        cairo_matrix_transform_point(&TranslateMatrixR0toR2, &TanEndPointLocalCas4.X, &TanEndPointLocalCas4.Y);

        SetColor(0,1,1);
        DrawPoint(TanStartPointLocalCas4,3);
        DrawPoint(TanEndPointLocalCas4,3);

        cairo_move_to(mCairoDC, aStartPoint.X, aStartPoint.Y);
        cairo_curve_to(mCairoDC, TanStartPointLocalCas4.X,TanStartPointLocalCas4.Y, TanEndPointLocalCas4.X, TanEndPointLocalCas4.Y, aEndPoint.X, aEndPoint.Y);
        cairo_set_line_width(mCairoDC, 3);
        cairo_stroke(mCairoDC);

    }
}