/*! * \brief Rotate path towards clicked point * * Rotate the given path around it's center with the angle given by * the top center handle and the clicked point. This function is * available with the context menu of the 'Standard - Path' object. * @return Undo information * * \relates _StdPath */ static ObjectChange * _path_rotate_callback (DiaObject *obj, Point *clicked, gpointer data) { StdPath *sp = (StdPath *)obj; real cx = (sp->object.bounding_box.left + sp->object.bounding_box.right) / 2; real cy = (sp->object.bounding_box.top + sp->object.bounding_box.bottom) / 2; DiaMatrix m = {1, 0, 0, 1, 0, 0 }; DiaMatrix translate = {1, 0, 0, 1, 0, 0 }; Point d; d.x = clicked->x - cx; d.y = clicked->y - cy; point_normalize (&d); /* to make the top, center handle clicked no rotation we subtract -PI/2 */ dia_matrix_set_angle_and_scales (&m, atan2 (d.y, d.x) + M_PI/2.0, 1.0, 1.0); /* rotate around center */ translate.x0 = cx; translate.y0 = cy; dia_matrix_multiply (&m, &m, &translate); translate.x0 = -cx; translate.y0 = -cy; dia_matrix_multiply (&m, &translate, &m); _path_transform (sp, &m); return _path_object_transform_change_create (obj, &m); }
static void _textobj_get_poly (const Textobj *textobj, Point poly[4]) { Point ul, lr; Point pt = textobj->text_handle.pos; Rectangle box; DiaMatrix m = { 1, 0, 0, 1, pt.x, pt.y }; DiaMatrix t = { 1, 0, 0, 1, -pt.x, -pt.y }; int i; dia_matrix_set_angle_and_scales (&m, G_PI * textobj->text_angle / 180.0, 1.0, 1.0); dia_matrix_multiply (&m, &t, &m); text_calc_boundingbox (textobj->text, &box); ul.x = box.left - textobj->margin; ul.y = box.top - textobj->margin; lr.x = box.right + textobj->margin; lr.y = box.bottom + textobj->margin; poly[0].x = ul.x; poly[0].y = ul.y; poly[1].x = lr.x; poly[1].y = ul.y; poly[2].x = lr.x; poly[2].y = lr.y; poly[3].x = ul.x; poly[3].y = lr.y; for (i = 0; i < 4; ++i) transform_point (&poly[i], &m); }
/*! * \brief Flip the path over the vertical or horizontal axis * * Flip horizontal/vertical like custom objects do, except that this * function is modifying the underlying point data. This function is * available with the context menu of the 'Standard - Path' object. * @return Undo information * * \relates _StdPath */ static ObjectChange * _path_flip_callback (DiaObject *obj, Point *clicked, gpointer data) { gboolean horz = data == NULL; StdPath *sp = (StdPath *)obj; DiaMatrix m = {horz ? -1 : 1, 0, 0, horz ? 1 : -1, 0, 0 }; DiaMatrix translate = {1, 0, 0, 1, 0, 0 }; real cx = (sp->object.bounding_box.left + sp->object.bounding_box.right) / 2; real cy = (sp->object.bounding_box.top + sp->object.bounding_box.bottom) / 2; /* flip around center */ translate.x0 = cx; translate.y0 = cy; dia_matrix_multiply (&m, &m, &translate); translate.x0 = -cx; translate.y0 = -cy; dia_matrix_multiply (&m, &translate, &m); _path_transform (sp, &m); return _path_object_transform_change_create (obj, &m); }
void updateCTM(GfxState *state, double m11, double m12, double m21, double m22, double m31, double m32) { DiaMatrix mat; mat.xx = m11; mat.yx = m12; mat.xy = m21; mat.yy = m22; mat.x0 = m31 * scale; mat.y0 = m32 * scale; //this->matrix = mat; dia_matrix_multiply (&this->matrix, &mat, &this->matrix); updateLineDash(state); updateLineJoin(state); updateLineCap(state); updateLineWidth(state); }
/* * renderer methods */ static void draw_object(DiaRenderer *self, DiaObject *object, DiaMatrix *matrix) { DrsRenderer *renderer = DRS_RENDERER (self); DiaMatrix *m = g_queue_peek_tail (renderer->matrices); xmlNodePtr node; g_queue_push_tail (renderer->parents, renderer->root); renderer->root = node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"object", NULL); xmlSetProp(node, (const xmlChar *)"type", (xmlChar *)object->type->name); /* if it looks like intdata store it as well */ if ((int)object->type->default_user_data > 0 && (int)object->type->default_user_data < 0xFF) { gchar buffer[30]; g_snprintf(buffer, sizeof(buffer), "%d", (int)object->type->default_user_data); xmlSetProp(node, (const xmlChar *)"intdata", (xmlChar *)buffer); } if (renderer->save_props) { xmlNodePtr props_node; props_node = xmlNewChild(node, NULL, (const xmlChar *)"properties", NULL); object_save_props (object, props_node, renderer->ctx); } if (matrix) { DiaMatrix *m2 = g_new (DiaMatrix, 1); if (m) dia_matrix_multiply (m2, matrix, m); else *m2 = *matrix; g_queue_push_tail (renderer->matrices, m2); /* lazy creation of our transformer */ if (!renderer->transformer) renderer->transformer = dia_transform_renderer_new (self); } /* special handling for group objects: * - for the render branch use DiaTransformRenderer, but not it's draw_object, * to see all the children's draw_object ourself * - for the object branch we rely on this draw_object being called so need * to inline group_draw here * - to maintain the correct transform build our own queue of matrices like * the DiaTransformRenderer would do through it's draw_object */ { g_queue_push_tail (renderer->parents, renderer->root); renderer->root = node = xmlNewChild(renderer->root, NULL, (const xmlChar *)"render", NULL); if (renderer->transformer) { DiaMatrix *m = g_queue_peek_tail (renderer->matrices); if (IS_GROUP (object)) { /* reimplementation of group_draw to use this draw_object method */ GList *list; DiaObject *obj; list = group_objects (object); while (list != NULL) { obj = (DiaObject *) list->data; DIA_RENDERER_GET_CLASS(self)->draw_object(self, obj, m); list = g_list_next(list); } } else { /* just the leaf */ DIA_RENDERER_GET_CLASS(renderer->transformer)->draw_object(renderer->transformer, object, m); } } else { object->ops->draw(object, DIA_RENDERER (renderer)); } renderer->root = g_queue_pop_tail (renderer->parents); } renderer->root = g_queue_pop_tail (renderer->parents); if (matrix) g_queue_pop_tail (renderer->matrices); /* one lost demand destruction */ if (renderer->transformer && g_queue_is_empty (renderer->matrices)) { g_object_unref (renderer->transformer); renderer->transformer = NULL; } }