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"); }
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; }
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; }
/** * 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); }
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); }
/*! * \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; }
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); }
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; }
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); }
/** * 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; }
void Matrix::initRotate( double radians ) { cairo_matrix_init_rotate( &getCairoMatrix(), radians ); }
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); }
/** * \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"); }
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); } }
/** * 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"); } }
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); } }
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"); }
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); } }