1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
23 * @short_description: The base class for renderable objects
25 * This abstract class provides a base interface for all renderable objects
26 * (all the objects that can be printed or viewed).
29 #include "adg-entity.h"
30 #include "adg-entity-private.h"
31 #include "adg-canvas.h"
32 #include "adg-context.h"
53 static void get_property (GObject
*object
,
57 static void set_property (GObject
*object
,
61 static void dispose (GObject
*object
);
62 static AdgContainer
* get_parent (AdgEntity
*entity
);
63 static void set_parent (AdgEntity
*entity
,
64 AdgContainer
*parent
);
65 static void parent_set (AdgEntity
*entity
,
66 AdgContainer
*old_parent
);
67 static AdgContext
* get_context (AdgEntity
*entity
);
68 static void set_context (AdgEntity
*entity
,
70 static void model_matrix_changed (AdgEntity
*entity
,
71 AdgMatrix
*parent_matrix
);
72 static void paper_matrix_changed (AdgEntity
*entity
,
73 AdgMatrix
*parent_matrix
);
74 static void render (AdgEntity
*entity
,
76 static const AdgMatrix
*get_model_matrix (AdgEntity
*entity
);
77 static const AdgMatrix
*get_paper_matrix (AdgEntity
*entity
);
79 static guint signals
[LAST_SIGNAL
] = { 0 };
82 G_DEFINE_ABSTRACT_TYPE(AdgEntity
, adg_entity
, G_TYPE_INITIALLY_UNOWNED
)
86 adg_entity_class_init(AdgEntityClass
*klass
)
88 GObjectClass
*gobject_class
;
91 gobject_class
= (GObjectClass
*) klass
;
93 g_type_class_add_private(klass
, sizeof(AdgEntityPrivate
));
95 gobject_class
->get_property
= get_property
;
96 gobject_class
->set_property
= set_property
;
97 gobject_class
->dispose
= dispose
;
99 klass
->get_parent
= get_parent
;
100 klass
->set_parent
= set_parent
;
101 klass
->parent_set
= parent_set
;
102 klass
->get_context
= get_context
;
103 klass
->model_matrix_changed
= model_matrix_changed
;
104 klass
->paper_matrix_changed
= paper_matrix_changed
;
105 klass
->invalidate
= NULL
;
106 klass
->render
= render
;
107 klass
->get_model_matrix
= get_model_matrix
;
108 klass
->get_paper_matrix
= get_paper_matrix
;
110 param
= g_param_spec_object("parent",
111 P_("Parent Container"),
112 P_("The parent AdgContainer of this entity or NULL if this is a top-level entity"),
113 ADG_TYPE_CONTAINER
, G_PARAM_READWRITE
);
114 g_object_class_install_property(gobject_class
, PROP_PARENT
, param
);
116 param
= g_param_spec_object("context",
118 P_("The context associated to this entity or NULL to inherit the parent context"),
119 ADG_TYPE_CONTEXT
, G_PARAM_READWRITE
);
120 g_object_class_install_property(gobject_class
, PROP_CONTEXT
, param
);
123 * AdgEntity::parent-set:
124 * @entity: an #AdgEntity
125 * @parent: the #AdgContainer parent of @entity
127 * Emitted after the parent container has changed.
129 signals
[PARENT_SET
] =
130 g_signal_new("parent-set",
131 G_OBJECT_CLASS_TYPE(gobject_class
),
133 G_STRUCT_OFFSET(AdgEntityClass
, parent_set
),
135 g_cclosure_marshal_VOID__OBJECT
,
136 G_TYPE_NONE
, 1, ADG_TYPE_CONTAINER
);
139 * AdgEntity::model-matrix-changed:
140 * @entity: an #AdgEntity
141 * @parent_matrix: the parent model matrix
143 * Emitted after the current model matrix has changed.
145 signals
[MODEL_MATRIX_CHANGED
] =
146 g_signal_new("model-matrix-changed",
147 G_OBJECT_CLASS_TYPE(gobject_class
),
149 G_STRUCT_OFFSET(AdgEntityClass
, model_matrix_changed
),
151 g_cclosure_marshal_VOID__BOXED
,
153 ADG_TYPE_MATRIX
| G_SIGNAL_TYPE_STATIC_SCOPE
);
156 * AdgEntity::paper-matrix-changed:
157 * @entity: an #AdgEntity
158 * @parent_matrix: the parent paper matrix
160 * Emitted after the current paper matrix has changed.
162 signals
[PAPER_MATRIX_CHANGED
] =
163 g_signal_new("paper-matrix-changed",
164 G_OBJECT_CLASS_TYPE(gobject_class
),
166 G_STRUCT_OFFSET(AdgEntityClass
, paper_matrix_changed
),
168 g_cclosure_marshal_VOID__BOXED
,
170 ADG_TYPE_MATRIX
| G_SIGNAL_TYPE_STATIC_SCOPE
);
173 * AdgEntity::invalidate:
174 * @entity: an #AdgEntity
176 * Clears the cached data of @entity.
178 signals
[INVALIDATE
] =
179 g_signal_new("invalidate",
180 G_OBJECT_CLASS_TYPE(gobject_class
),
182 G_STRUCT_OFFSET(AdgEntityClass
, invalidate
),
184 g_cclosure_marshal_VOID__BOOLEAN
,
189 * @entity: an #AdgEntity
190 * @cr: a #cairo_t drawing context
192 * Causes the rendering of @entity on @cr.
195 g_signal_new("render",
196 G_OBJECT_CLASS_TYPE(gobject_class
),
198 G_STRUCT_OFFSET(AdgEntityClass
, render
),
200 g_cclosure_marshal_VOID__POINTER
,
201 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
205 adg_entity_init(AdgEntity
*entity
)
207 AdgEntityPrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE(entity
,
212 priv
->context
= NULL
;
218 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
220 AdgEntity
*entity
= (AdgEntity
*) object
;
224 g_value_set_object(value
, get_parent(entity
));
227 g_value_set_object(value
, get_context(entity
));
230 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
236 set_property(GObject
*object
,
237 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
239 AdgEntity
*entity
= (AdgEntity
*) object
;
243 set_parent(entity
, (AdgContainer
*) g_value_get_object(value
));
246 set_context(entity
, g_value_get_object(value
));
249 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
255 dispose(GObject
*object
)
258 GObjectClass
*object_class
;
260 entity
= (AdgEntity
*) object
;
261 object_class
= (GObjectClass
*) adg_entity_parent_class
;
263 if (entity
->priv
->parent
)
264 adg_container_remove(entity
->priv
->parent
, entity
);
266 if (object_class
->dispose
!= NULL
)
267 object_class
->dispose(object
);
272 * adg_entity_get_parent:
273 * @entity: an #AdgEntity
275 * Gets the container parent of @entity.
277 * This function is only useful in entity implementations.
279 * Return value: the container object or %NULL if @entity is not contained
282 adg_entity_get_parent(AdgEntity
*entity
)
284 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
286 return ADG_ENTITY_GET_CLASS(entity
)->get_parent(entity
);
290 * adg_entity_set_parent:
291 * @entity: an #AdgEntity
292 * @parent: an #AdgContainer
294 * Sets a new container of @entity.
296 * This function is only useful in entity implementations.
299 adg_entity_set_parent(AdgEntity
*entity
, AdgContainer
*parent
)
301 g_return_if_fail(ADG_IS_ENTITY(entity
));
303 ADG_ENTITY_GET_CLASS(entity
)->set_parent(entity
, parent
);
304 g_object_notify((GObject
*) entity
, "parent");
308 * adg_entity_unparent:
309 * @entity: an #AdgEntity
311 * Removes the current parent of @entity, properly handling
312 * the references between them.
314 * If @entity has no parent, this function simply returns.
317 adg_entity_unparent(AdgEntity
*entity
)
319 AdgContainer
*old_parent
;
321 g_return_if_fail(ADG_IS_ENTITY(entity
));
323 old_parent
= ADG_ENTITY_GET_CLASS(entity
)->get_parent(entity
);
325 if (old_parent
== NULL
)
328 ADG_ENTITY_GET_CLASS(entity
)->set_parent(entity
, NULL
);
329 g_signal_emit(entity
, signals
[PARENT_SET
], 0, old_parent
);
331 g_object_unref(entity
);
335 * adg_entity_reparent:
336 * @entity: an #AdgEntity
337 * @parent: the new container
339 * Moves @entity from the old parent to @parent, handling reference
340 * count issues to avoid destroying the object.
343 adg_entity_reparent(AdgEntity
*entity
, AdgContainer
*parent
)
345 AdgContainer
*old_parent
;
347 g_return_if_fail(ADG_IS_CONTAINER(parent
));
349 old_parent
= adg_entity_get_parent(entity
);
351 /* Reparenting on the same container: do nothing */
352 if (old_parent
== parent
)
355 g_return_if_fail(ADG_IS_CONTAINER(old_parent
));
357 g_object_ref(entity
);
358 adg_container_remove(old_parent
, entity
);
359 adg_container_add(parent
, entity
);
360 g_object_unref(entity
);
364 * adg_entity_get_context:
365 * @entity: an #AdgEntity instance
367 * Gets the context associated to @entity.
368 * If no context was explicitely set, get the parent context.
370 * Return value: the requested context or %NULL on errors
373 adg_entity_get_context(AdgEntity
*entity
)
375 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
377 if (entity
->priv
->context
)
378 return entity
->priv
->context
;
380 if (entity
->priv
->parent
)
381 return adg_entity_get_context((AdgEntity
*) entity
->priv
->parent
);
387 * adg_entity_set_context:
388 * @entity: an #AdgEntity instance
389 * @context: the new context
391 * Sets a new context. The old context (if any) will be unreferenced
392 * while a new reference will be added to @context.
395 adg_entity_set_context(AdgEntity
*entity
, AdgContext
*context
)
397 g_return_if_fail(ADG_IS_ENTITY(entity
));
398 g_return_if_fail(ADG_IS_CONTEXT(context
));
400 set_context(entity
, context
);
401 g_object_notify((GObject
*) entity
, "context");
405 * adg_entity_get_canvas:
406 * @entity: an #AdgEntity
408 * Walks on the @entity hierarchy and gets the first parent of @entity that is
409 * of #AdgCanvas derived type.
411 * Return value: the requested object or %NULL if there is no #AdgCanvas in
412 * the parent hierarchy.
415 adg_entity_get_canvas(AdgEntity
*entity
)
417 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
420 if (ADG_IS_CANVAS(entity
))
421 return (AdgCanvas
*) entity
;
423 entity
= (AdgEntity
*) adg_entity_get_parent(entity
);
430 * adg_entity_get_model_matrix:
431 * @entity: an #AdgEntity object
433 * Gets the model matrix to be used in rendering this @entity.
435 * Return value: the requested matrix
438 adg_entity_get_model_matrix(AdgEntity
*entity
)
440 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
441 return ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
445 * adg_entity_get_paper_matrix:
446 * @entity: an #AdgEntity object
448 * Gets the paper matrix to be used in rendering this @entity.
450 * Return value: the requested matrix
453 adg_entity_get_paper_matrix(AdgEntity
*entity
)
455 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
456 return ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
460 * adg_entity_scale_to_model:
461 * @entity: an #AdgEntity object
462 * @cr: a #cairo_t drawing context
464 * Sets the model matrix as current matrix on @cr. The translation
465 * and rotation component of the previous matrix are kept: only the
469 adg_entity_scale_to_model(AdgEntity
*entity
, cairo_t
*cr
)
471 const AdgMatrix
*model_matrix
;
472 cairo_matrix_t matrix
;
474 g_return_if_fail(ADG_IS_ENTITY(entity
));
476 model_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
477 cairo_get_matrix(cr
, &matrix
);
479 matrix
.xx
= model_matrix
->xx
;
480 matrix
.yy
= model_matrix
->yy
;
481 cairo_set_matrix(cr
, &matrix
);
485 * adg_entity_scale_to_paper:
486 * @entity: an #AdgEntity object
487 * @cr: a #cairo_t drawing context
489 * Sets the paper matrix as current matrix on @cr. The translation
490 * and rotation component of the previous matrix are kept: only the
494 adg_entity_scale_to_paper(AdgEntity
*entity
, cairo_t
*cr
)
496 const AdgMatrix
*paper_matrix
;
497 cairo_matrix_t matrix
;
499 g_return_if_fail(ADG_IS_ENTITY(entity
));
501 paper_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
502 cairo_get_matrix(cr
, &matrix
);
504 matrix
.xx
= paper_matrix
->xx
;
505 matrix
.yy
= paper_matrix
->yy
;
506 cairo_set_matrix(cr
, &matrix
);
510 * adg_entity_build_paper2model:
511 * @entity: an #AdgEntity
512 * @matrix: the destination matrix
514 * Builds a matrix to translate from paper to model space and
515 * put the result in @matrix.
517 * Return value: %TRUE on success, %FALSE on errors
520 adg_entity_build_paper2model(AdgEntity
*entity
, AdgMatrix
*matrix
)
522 cairo_status_t status
;
524 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
525 g_return_val_if_fail(matrix
!= NULL
, FALSE
);
527 adg_matrix_copy(matrix
, adg_entity_get_model_matrix(entity
));
528 status
= cairo_matrix_invert(matrix
);
529 if (status
!= CAIRO_STATUS_SUCCESS
) {
530 g_error("Unable to invert model matrix (cairo message: %s)",
531 cairo_status_to_string(status
));
535 cairo_matrix_multiply(matrix
, matrix
, adg_entity_get_paper_matrix(entity
));
540 * adg_entity_build_model2paper:
541 * @entity: an #AdgEntity
542 * @matrix: the destination matrix
544 * Builds a matrix to translate from model to paper space and
545 * put the result in @matrix.
547 * Return value: %TRUE on success, %FALSE on errors
550 adg_entity_build_model2paper(AdgEntity
*entity
, AdgMatrix
*matrix
)
552 cairo_status_t status
;
554 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
555 g_return_val_if_fail(matrix
!= NULL
, FALSE
);
557 adg_matrix_copy(matrix
, adg_entity_get_paper_matrix(entity
));
558 status
= cairo_matrix_invert(matrix
);
559 if (status
!= CAIRO_STATUS_SUCCESS
) {
560 g_error("Unable to invert paper matrix (cairo message: %s)",
561 cairo_status_to_string(status
));
565 cairo_matrix_multiply(matrix
, matrix
, adg_entity_get_model_matrix(entity
));
570 * adg_entity_model_matrix_changed:
571 * @entity: an #AdgEntity
572 * @parent_matrix: the parent #AdgMatrix
574 * Emits the "model-matrix-changed" signal on @entity.
576 * This function is only useful in entity implementations.
579 adg_entity_model_matrix_changed(AdgEntity
*entity
,
580 const AdgMatrix
*parent_matrix
)
582 g_return_if_fail(ADG_IS_ENTITY(entity
));
584 g_signal_emit(entity
, signals
[MODEL_MATRIX_CHANGED
], 0, parent_matrix
);
588 * adg_entity_paper_matrix_changed:
589 * @entity: an #AdgEntity
590 * @parent_matrix: the parent #AdgMatrix
592 * Emits the "paper-matrix-changed" signal on @entity.
594 * This function is only useful in entity implementations.
597 adg_entity_paper_matrix_changed(AdgEntity
*entity
,
598 const AdgMatrix
*parent_matrix
)
600 g_return_if_fail(ADG_IS_ENTITY(entity
));
602 g_signal_emit(entity
, signals
[PAPER_MATRIX_CHANGED
], 0, parent_matrix
);
606 * adg_entity_get_style:
607 * @entity: an #AdgEntity
608 * @style_slot: the slot of the style to get
610 * Gets a style from this entity. If the entity has no context associated
611 * or the style in undefined within this context, gets the style from its
614 * Return value: the requested style or %NULL on errors
617 adg_entity_get_style(AdgEntity
*entity
, AdgStyleSlot style_slot
)
619 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
621 if (entity
->priv
->context
) {
622 AdgStyle
*style
= adg_context_get_style(entity
->priv
->context
,
628 if (entity
->priv
->parent
)
629 return adg_entity_get_style((AdgEntity
*) entity
->priv
->parent
,
637 * @entity: an #AdgEntity
638 * @style_slot: the slot of the style to apply
639 * @cr: a #cairo_t drawing context
641 * Applies the specified style to the @cr cairo context.
644 adg_entity_apply(AdgEntity
*entity
, AdgStyleSlot style_slot
, cairo_t
*cr
)
646 AdgStyle
*style
= adg_entity_get_style(entity
, style_slot
);
649 adg_style_apply(style
, cr
);
653 * adg_entity_point_to_pair:
654 * @entity: an #AdgEntity
655 * @point: the source #AdgPoint
656 * @pair: the destination #AdgPair
657 * @cr: a #cairo_t drawing context
659 * Converts @point to @pair using the model and paper matrix of @entity,
660 * as if the current matrix is an identity matrix.
663 adg_entity_point_to_pair(AdgEntity
*entity
, const AdgPoint
*point
,
664 AdgPair
*pair
, cairo_t
*cr
)
666 AdgMatrix inverted_ctm
;
667 const AdgMatrix
*model_matrix
;
668 const AdgMatrix
*paper_matrix
;
669 AdgPair model_pair
, paper_pair
;
671 g_return_if_fail(ADG_IS_ENTITY(entity
));
672 g_return_if_fail(point
!= NULL
);
673 g_return_if_fail(pair
!= NULL
);
675 cairo_get_matrix(cr
, &inverted_ctm
);
676 cairo_matrix_invert(&inverted_ctm
);
677 model_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
678 paper_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
680 cpml_pair_copy(&model_pair
, &point
->model
);
681 cpml_pair_transform(&model_pair
, model_matrix
);
683 cpml_pair_copy(&paper_pair
, &point
->paper
);
684 cpml_pair_transform(&paper_pair
, paper_matrix
);
686 pair
->x
= model_pair
.x
+ paper_pair
.x
;
687 pair
->y
= model_pair
.y
+ paper_pair
.y
;
689 cpml_pair_transform(pair
, &inverted_ctm
);
693 * adg_entity_point_to_model_pair:
694 * @entity: an #AdgEntity
695 * @point: the source #AdgPoint
696 * @pair: the destination #AdgPair
698 * Converts @point to @pair in model space.
701 adg_entity_point_to_model_pair(AdgEntity
*entity
,
702 const AdgPoint
*point
, AdgPair
*pair
)
704 const AdgMatrix
*paper_matrix
;
706 g_return_if_fail(ADG_IS_ENTITY(entity
));
707 g_return_if_fail(point
!= NULL
);
708 g_return_if_fail(pair
!= NULL
);
710 paper_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
711 cpml_pair_copy(pair
, &point
->paper
);
712 cpml_pair_transform(pair
, paper_matrix
);
714 pair
->x
+= point
->model
.x
;
715 pair
->y
+= point
->model
.y
;
719 * adg_entity_point_to_paper_pair:
720 * @entity: an #AdgEntity
721 * @point: the source #AdgPoint
722 * @pair: the destination #AdgPair
724 * Converts @point to @pair in paper space.
727 adg_entity_point_to_paper_pair(AdgEntity
*entity
,
728 const AdgPoint
*point
, AdgPair
*pair
)
730 const AdgMatrix
*model_matrix
;
732 g_return_if_fail(ADG_IS_ENTITY(entity
));
733 g_return_if_fail(point
!= NULL
);
734 g_return_if_fail(pair
!= NULL
);
736 model_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
737 cpml_pair_copy(pair
, &point
->model
);
738 cpml_pair_transform(pair
, model_matrix
);
740 pair
->x
+= point
->paper
.x
;
741 pair
->y
+= point
->paper
.y
;
742 g_print("Pair (%lf, %lf)\n", pair
->x
, pair
->y
);
746 * adg_entity_model_matrix_applied:
747 * @entity: an #AdgEntity
749 * Return value: %TRUE if the model matrix didn't change from the last render
752 adg_entity_model_matrix_applied(AdgEntity
*entity
)
754 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
755 return ADG_ISSET(entity
->priv
->flags
, MODEL_MATRIX_APPLIED
);
759 * adg_entity_paper_matrix_applied:
760 * @entity: an #AdgEntity
762 * Return value: %TRUE if the paper matrix didn't change from the last render
765 adg_entity_paper_matrix_applied(AdgEntity
*entity
)
767 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
768 return ADG_ISSET(entity
->priv
->flags
, PAPER_MATRIX_APPLIED
);
772 * adg_entity_model_applied:
773 * @entity: an #AdgEntity
775 * Return value: %TRUE if the model didn't change from the last render
778 adg_entity_model_applied(AdgEntity
*entity
)
780 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
781 return ADG_ISSET(entity
->priv
->flags
, MODEL_APPLIED
);
785 * adg_entity_invalidate:
786 * @entity: an #AdgEntity
788 * Emits the "invalidate" signal on @entity and all its children, if any,
789 * so subsequent rendering will need a global recomputation.
792 adg_entity_invalidate(AdgEntity
*entity
)
794 g_return_if_fail(ADG_IS_ENTITY(entity
));
796 g_signal_emit(entity
, signals
[INVALIDATE
], 0, NULL
);
801 * @entity: an #AdgEntity
802 * @cr: a #cairo_t drawing context
804 * Emits the "render" signal on @entity and all its children, if any,
805 * causing the rendering operation the @cr cairo context.
808 adg_entity_render(AdgEntity
*entity
, cairo_t
*cr
)
810 g_return_if_fail(ADG_IS_ENTITY(entity
));
812 g_signal_emit(entity
, signals
[RENDER
], 0, cr
);
816 static AdgContainer
*
817 get_parent(AdgEntity
*entity
)
819 return entity
->priv
->parent
;
823 set_parent(AdgEntity
*entity
, AdgContainer
*parent
)
825 entity
->priv
->parent
= parent
;
829 parent_set(AdgEntity
*entity
, AdgContainer
*old_parent
)
831 if (ADG_IS_CONTAINER(old_parent
)) {
832 const AdgMatrix
*old_model
;
833 const AdgMatrix
*old_paper
;
835 old_model
= adg_entity_get_model_matrix((AdgEntity
*) old_parent
);
836 old_paper
= adg_entity_get_paper_matrix((AdgEntity
*) old_parent
);
838 adg_entity_model_matrix_changed(entity
, old_model
);
839 adg_entity_paper_matrix_changed(entity
, old_paper
);
844 get_context(AdgEntity
*entity
)
848 if (entity
->priv
->context
)
849 return entity
->priv
->context
;
851 parent
= (AdgEntity
*) entity
->priv
->parent
;
853 return parent
? ADG_ENTITY_GET_CLASS(parent
)->get_context(parent
) : NULL
;
857 set_context(AdgEntity
*entity
, AdgContext
*context
)
859 if (entity
->priv
->context
)
860 g_object_unref((GObject
*) entity
->priv
->context
);
862 g_object_ref((GObject
*) context
);
863 entity
->priv
->context
= context
;
867 model_matrix_changed(AdgEntity
*entity
, AdgMatrix
*parent_matrix
)
869 ADG_UNSET(entity
->priv
->flags
, MODEL_MATRIX_APPLIED
);
873 paper_matrix_changed(AdgEntity
*entity
, AdgMatrix
*parent_matrix
)
875 ADG_UNSET(entity
->priv
->flags
, PAPER_MATRIX_APPLIED
);
879 render(AdgEntity
*entity
, cairo_t
*cr
)
881 ADG_SET(entity
->priv
->flags
,
882 MODEL_MATRIX_APPLIED
| PAPER_MATRIX_APPLIED
| MODEL_APPLIED
);
885 static const AdgMatrix
*
886 get_model_matrix(AdgEntity
*entity
)
888 return adg_entity_get_model_matrix((AdgEntity
*) entity
->priv
->parent
);
891 static const AdgMatrix
*
892 get_paper_matrix(AdgEntity
*entity
)
894 return adg_entity_get_paper_matrix((AdgEntity
*) entity
->priv
->parent
);