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"
36 #define PARENT_CLASS ((GInitiallyUnownedClass *) adg_entity_parent_class)
55 static void get_property (GObject
*object
,
59 static void set_property (GObject
*object
,
63 static void dispose (GObject
*object
);
64 static AdgContainer
* get_parent (AdgEntity
*entity
);
65 static void set_parent (AdgEntity
*entity
,
66 AdgContainer
*parent
);
67 static void parent_set (AdgEntity
*entity
,
68 AdgContainer
*old_parent
);
69 static AdgContext
* get_context (AdgEntity
*entity
);
70 static void set_context (AdgEntity
*entity
,
72 static void model_matrix_changed (AdgEntity
*entity
,
73 AdgMatrix
*parent_matrix
);
74 static void paper_matrix_changed (AdgEntity
*entity
,
75 AdgMatrix
*parent_matrix
);
76 static void render (AdgEntity
*entity
,
78 static const AdgMatrix
*get_model_matrix (AdgEntity
*entity
);
79 static const AdgMatrix
*get_paper_matrix (AdgEntity
*entity
);
81 static guint signals
[LAST_SIGNAL
] = { 0 };
84 G_DEFINE_ABSTRACT_TYPE(AdgEntity
, adg_entity
, G_TYPE_INITIALLY_UNOWNED
)
88 adg_entity_class_init(AdgEntityClass
*klass
)
90 GObjectClass
*gobject_class
;
93 gobject_class
= (GObjectClass
*) klass
;
95 g_type_class_add_private(klass
, sizeof(AdgEntityPrivate
));
97 gobject_class
->get_property
= get_property
;
98 gobject_class
->set_property
= set_property
;
99 gobject_class
->dispose
= dispose
;
101 klass
->get_parent
= get_parent
;
102 klass
->set_parent
= set_parent
;
103 klass
->parent_set
= parent_set
;
104 klass
->get_context
= get_context
;
105 klass
->model_matrix_changed
= model_matrix_changed
;
106 klass
->paper_matrix_changed
= NULL
;
107 klass
->invalidate
= NULL
;
108 klass
->render
= render
;
109 klass
->get_model_matrix
= get_model_matrix
;
110 klass
->get_paper_matrix
= get_paper_matrix
;
112 param
= g_param_spec_object("parent",
113 P_("Parent Container"),
114 P_("The parent AdgContainer of this entity or NULL if this is a top-level entity"),
115 ADG_TYPE_CONTAINER
, G_PARAM_READWRITE
);
116 g_object_class_install_property(gobject_class
, PROP_PARENT
, param
);
118 param
= g_param_spec_object("context",
120 P_("The context associated to this entity or NULL to inherit the parent context"),
121 ADG_TYPE_CONTEXT
, G_PARAM_READWRITE
);
122 g_object_class_install_property(gobject_class
, PROP_CONTEXT
, param
);
125 * AdgEntity::parent-set:
126 * @entity: an #AdgEntity
127 * @parent: the #AdgContainer parent of @entity
129 * Emitted after the parent container has changed.
131 signals
[PARENT_SET
] =
132 g_signal_new("parent-set",
133 G_OBJECT_CLASS_TYPE(gobject_class
),
135 G_STRUCT_OFFSET(AdgEntityClass
, parent_set
),
137 g_cclosure_marshal_VOID__OBJECT
,
138 G_TYPE_NONE
, 1, ADG_TYPE_CONTAINER
);
141 * AdgEntity::model-matrix-changed:
142 * @entity: an #AdgEntity
143 * @parent_matrix: the parent model matrix
145 * Emitted after the current model matrix has changed.
147 signals
[MODEL_MATRIX_CHANGED
] =
148 g_signal_new("model-matrix-changed",
149 G_OBJECT_CLASS_TYPE(gobject_class
),
151 G_STRUCT_OFFSET(AdgEntityClass
, model_matrix_changed
),
153 g_cclosure_marshal_VOID__BOXED
,
155 ADG_TYPE_MATRIX
| G_SIGNAL_TYPE_STATIC_SCOPE
);
158 * AdgEntity::paper-matrix-changed:
159 * @entity: an #AdgEntity
160 * @parent_matrix: the parent paper matrix
162 * Emitted after the current paper matrix has changed.
164 signals
[PAPER_MATRIX_CHANGED
] =
165 g_signal_new("paper-matrix-changed",
166 G_OBJECT_CLASS_TYPE(gobject_class
),
168 G_STRUCT_OFFSET(AdgEntityClass
, paper_matrix_changed
),
170 g_cclosure_marshal_VOID__BOXED
,
172 ADG_TYPE_MATRIX
| G_SIGNAL_TYPE_STATIC_SCOPE
);
175 * AdgEntity::invalidate:
176 * @entity: an #AdgEntity
178 * Clears the cached data of @entity.
180 signals
[INVALIDATE
] =
181 g_signal_new("invalidate",
182 G_OBJECT_CLASS_TYPE(gobject_class
),
184 G_STRUCT_OFFSET(AdgEntityClass
, invalidate
),
186 g_cclosure_marshal_VOID__BOOLEAN
,
191 * @entity: an #AdgEntity
192 * @cr: a #cairo_t drawing context
194 * Causes the rendering of @entity on @cr.
197 g_signal_new("render",
198 G_OBJECT_CLASS_TYPE(gobject_class
),
200 G_STRUCT_OFFSET(AdgEntityClass
, render
),
202 g_cclosure_marshal_VOID__POINTER
,
203 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
207 adg_entity_init(AdgEntity
*entity
)
209 AdgEntityPrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE(entity
,
214 priv
->context
= NULL
;
220 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
222 AdgEntity
*entity
= (AdgEntity
*) object
;
226 g_value_set_object(value
, get_parent(entity
));
229 g_value_set_object(value
, get_context(entity
));
232 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
238 set_property(GObject
*object
,
239 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
241 AdgEntity
*entity
= (AdgEntity
*) object
;
245 set_parent(entity
, (AdgContainer
*) g_value_get_object(value
));
248 set_context(entity
, g_value_get_object(value
));
251 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
257 dispose(GObject
*object
)
261 entity
= (AdgEntity
*) object
;
263 if (entity
->priv
->parent
)
264 adg_container_remove(entity
->priv
->parent
, entity
);
266 PARENT_CLASS
->dispose(object
);
271 * adg_entity_get_parent:
272 * @entity: an #AdgEntity
274 * Gets the container parent of @entity.
276 * This function is only useful in entity implementations.
278 * Return value: the container object or %NULL if @entity is not contained
281 adg_entity_get_parent(AdgEntity
*entity
)
283 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
285 return ADG_ENTITY_GET_CLASS(entity
)->get_parent(entity
);
289 * adg_entity_set_parent:
290 * @entity: an #AdgEntity
291 * @parent: an #AdgContainer
293 * Sets a new container of @entity.
295 * This function is only useful in entity implementations.
298 adg_entity_set_parent(AdgEntity
*entity
, AdgContainer
*parent
)
300 g_return_if_fail(ADG_IS_ENTITY(entity
));
302 ADG_ENTITY_GET_CLASS(entity
)->set_parent(entity
, parent
);
303 g_object_notify((GObject
*) entity
, "parent");
307 * adg_entity_unparent:
308 * @entity: an #AdgEntity
310 * Removes the current parent of @entity, properly handling
311 * the references between them.
313 * If @entity has no parent, this function simply returns.
316 adg_entity_unparent(AdgEntity
*entity
)
318 AdgContainer
*old_parent
;
320 g_return_if_fail(ADG_IS_ENTITY(entity
));
322 old_parent
= ADG_ENTITY_GET_CLASS(entity
)->get_parent(entity
);
324 if (old_parent
== NULL
)
327 ADG_ENTITY_GET_CLASS(entity
)->set_parent(entity
, NULL
);
328 g_signal_emit(entity
, signals
[PARENT_SET
], 0, old_parent
);
330 g_object_unref(entity
);
334 * adg_entity_reparent:
335 * @entity: an #AdgEntity
336 * @parent: the new container
338 * Moves @entity from the old parent to @parent, handling reference
339 * count issues to avoid destroying the object.
342 adg_entity_reparent(AdgEntity
*entity
, AdgContainer
*parent
)
344 AdgContainer
*old_parent
;
346 g_return_if_fail(ADG_IS_CONTAINER(parent
));
348 old_parent
= adg_entity_get_parent(entity
);
350 /* Reparenting on the same container: do nothing */
351 if (old_parent
== parent
)
354 g_return_if_fail(ADG_IS_CONTAINER(old_parent
));
356 g_object_ref(entity
);
357 adg_container_remove(old_parent
, entity
);
358 adg_container_add(parent
, entity
);
359 g_object_unref(entity
);
363 * adg_entity_get_context:
364 * @entity: an #AdgEntity instance
366 * Gets the context associated to @entity.
367 * If no context was explicitely set, get the parent context.
369 * Return value: the requested context or %NULL on errors
372 adg_entity_get_context(AdgEntity
*entity
)
374 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
376 if (entity
->priv
->context
)
377 return entity
->priv
->context
;
379 if (entity
->priv
->parent
)
380 return adg_entity_get_context((AdgEntity
*) entity
->priv
->parent
);
386 * adg_entity_set_context:
387 * @entity: an #AdgEntity instance
388 * @context: the new context
390 * Sets a new context. The old context (if any) will be unreferenced
391 * while a new reference will be added to @context.
394 adg_entity_set_context(AdgEntity
*entity
, AdgContext
*context
)
396 g_return_if_fail(ADG_IS_ENTITY(entity
));
397 g_return_if_fail(ADG_IS_CONTEXT(context
));
399 set_context(entity
, context
);
400 g_object_notify((GObject
*) entity
, "context");
404 * adg_entity_get_canvas:
405 * @entity: an #AdgEntity
407 * Walks on the @entity hierarchy and gets the first parent of @entity that is
408 * of #AdgCanvas derived type.
410 * Return value: the requested object or %NULL if there is no #AdgCanvas in
411 * the parent hierarchy.
414 adg_entity_get_canvas(AdgEntity
*entity
)
416 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
419 if (ADG_IS_CANVAS(entity
))
420 return (AdgCanvas
*) entity
;
422 entity
= (AdgEntity
*) adg_entity_get_parent(entity
);
429 * adg_entity_get_model_matrix:
430 * @entity: an #AdgEntity object
432 * Gets the model matrix to be used in rendering this @entity.
434 * Return value: the requested matrix
437 adg_entity_get_model_matrix(AdgEntity
*entity
)
439 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
440 return ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
444 * adg_entity_get_paper_matrix:
445 * @entity: an #AdgEntity object
447 * Gets the paper matrix to be used in rendering this @entity.
449 * Return value: the requested matrix
452 adg_entity_get_paper_matrix(AdgEntity
*entity
)
454 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
455 return ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
459 * adg_entity_scale_to_model:
460 * @entity: an #AdgEntity object
461 * @cr: a #cairo_t drawing context
463 * Sets the model matrix as current matrix on @cr. The translation
464 * and rotation component of the previous matrix are kept: only the
468 adg_entity_scale_to_model(AdgEntity
*entity
, cairo_t
*cr
)
470 const AdgMatrix
*model_matrix
;
471 cairo_matrix_t matrix
;
473 g_return_if_fail(ADG_IS_ENTITY(entity
));
475 model_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
476 cairo_get_matrix(cr
, &matrix
);
478 matrix
.xx
= model_matrix
->xx
;
479 matrix
.yy
= model_matrix
->yy
;
480 cairo_set_matrix(cr
, &matrix
);
484 * adg_entity_scale_to_paper:
485 * @entity: an #AdgEntity object
486 * @cr: a #cairo_t drawing context
488 * Sets the paper matrix as current matrix on @cr. The translation
489 * and rotation component of the previous matrix are kept: only the
493 adg_entity_scale_to_paper(AdgEntity
*entity
, cairo_t
*cr
)
495 const AdgMatrix
*paper_matrix
;
496 cairo_matrix_t matrix
;
498 g_return_if_fail(ADG_IS_ENTITY(entity
));
500 paper_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
501 cairo_get_matrix(cr
, &matrix
);
503 matrix
.xx
= paper_matrix
->xx
;
504 matrix
.yy
= paper_matrix
->yy
;
505 cairo_set_matrix(cr
, &matrix
);
509 * adg_entity_build_paper2model:
510 * @entity: an #AdgEntity
511 * @matrix: the destination matrix
513 * Builds a matrix to translate from paper to model space and
514 * put the result in @matrix.
516 * Return value: %TRUE on success, %FALSE on errors
519 adg_entity_build_paper2model(AdgEntity
*entity
, AdgMatrix
*matrix
)
521 cairo_status_t status
;
523 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
524 g_return_val_if_fail(matrix
!= NULL
, FALSE
);
526 adg_matrix_copy(matrix
, adg_entity_get_model_matrix(entity
));
527 status
= cairo_matrix_invert(matrix
);
528 if (status
!= CAIRO_STATUS_SUCCESS
) {
529 g_error("Unable to invert model matrix (cairo message: %s)",
530 cairo_status_to_string(status
));
534 cairo_matrix_multiply(matrix
, matrix
, adg_entity_get_paper_matrix(entity
));
539 * adg_entity_build_model2paper:
540 * @entity: an #AdgEntity
541 * @matrix: the destination matrix
543 * Builds a matrix to translate from model to paper space and
544 * put the result in @matrix.
546 * Return value: %TRUE on success, %FALSE on errors
549 adg_entity_build_model2paper(AdgEntity
*entity
, AdgMatrix
*matrix
)
551 cairo_status_t status
;
553 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
554 g_return_val_if_fail(matrix
!= NULL
, FALSE
);
556 adg_matrix_copy(matrix
, adg_entity_get_paper_matrix(entity
));
557 status
= cairo_matrix_invert(matrix
);
558 if (status
!= CAIRO_STATUS_SUCCESS
) {
559 g_error("Unable to invert paper matrix (cairo message: %s)",
560 cairo_status_to_string(status
));
564 cairo_matrix_multiply(matrix
, matrix
, adg_entity_get_model_matrix(entity
));
569 * adg_entity_model_matrix_changed:
570 * @entity: an #AdgEntity
571 * @parent_matrix: the parent #AdgMatrix
573 * Emits the "model-matrix-changed" signal on @entity.
575 * This function is only useful in entity implementations.
578 adg_entity_model_matrix_changed(AdgEntity
*entity
,
579 const AdgMatrix
*parent_matrix
)
581 g_return_if_fail(ADG_IS_ENTITY(entity
));
583 g_signal_emit(entity
, signals
[MODEL_MATRIX_CHANGED
], 0, parent_matrix
);
587 * adg_entity_paper_matrix_changed:
588 * @entity: an #AdgEntity
589 * @parent_matrix: the parent #AdgMatrix
591 * Emits the "paper-matrix-changed" signal on @entity.
593 * This function is only useful in entity implementations.
596 adg_entity_paper_matrix_changed(AdgEntity
*entity
,
597 const AdgMatrix
*parent_matrix
)
599 g_return_if_fail(ADG_IS_ENTITY(entity
));
601 g_signal_emit(entity
, signals
[PAPER_MATRIX_CHANGED
], 0, parent_matrix
);
605 * adg_entity_get_style:
606 * @entity: an #AdgEntity
607 * @style_slot: the slot of the style to get
609 * Gets a style from this entity. If the entity has no context associated
610 * or the style in undefined within this context, gets the style from its
613 * Return value: the requested style
616 adg_entity_get_style(AdgEntity
*entity
, AdgStyleSlot style_slot
)
618 g_return_if_fail(ADG_IS_ENTITY(entity
));
620 if (entity
->priv
->context
) {
621 AdgStyle
*style
= adg_context_get_style(entity
->priv
->context
,
627 if (entity
->priv
->parent
)
628 return adg_entity_get_style((AdgEntity
*) entity
->priv
->parent
,
636 * @entity: an #AdgEntity
637 * @style_slot: the slot of the style to apply
638 * @cr: a #cairo_t drawing context
640 * Applies the specified style to the @cr cairo context.
643 adg_entity_apply(AdgEntity
*entity
, AdgStyleSlot style_slot
, cairo_t
*cr
)
645 AdgStyle
*style
= adg_entity_get_style(entity
, style_slot
);
648 adg_style_apply(style
, cr
);
652 * adg_entity_point_to_pair:
653 * @entity: an #AdgEntity
654 * @point: the source #AdgPoint
655 * @pair: the destination #AdgPair
656 * @cr: a #cairo_t drawing context
658 * Converts @point to @pair using the model and paper matrix of @entity,
659 * as if the current matrix is an identity matrix.
662 adg_entity_point_to_pair(AdgEntity
*entity
, const AdgPoint
*point
,
663 AdgPair
*pair
, cairo_t
*cr
)
665 AdgMatrix inverted_ctm
;
666 const AdgMatrix
*model_matrix
;
667 const AdgMatrix
*paper_matrix
;
668 AdgPair model_pair
, paper_pair
;
670 g_return_if_fail(ADG_IS_ENTITY(entity
));
671 g_return_if_fail(point
!= NULL
);
672 g_return_if_fail(pair
!= NULL
);
674 cairo_get_matrix(cr
, &inverted_ctm
);
675 cairo_matrix_invert(&inverted_ctm
);
676 model_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
677 paper_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
679 adg_pair_copy(&model_pair
, &point
->model
);
680 cpml_pair_transform(&model_pair
, model_matrix
);
682 adg_pair_copy(&paper_pair
, &point
->paper
);
683 cpml_pair_transform(&paper_pair
, paper_matrix
);
685 pair
->x
= model_pair
.x
+ paper_pair
.x
;
686 pair
->y
= model_pair
.y
+ paper_pair
.y
;
688 cpml_pair_transform(pair
, &inverted_ctm
);
692 * adg_entity_point_to_model_pair:
693 * @entity: an #AdgEntity
694 * @point: the source #AdgPoint
695 * @pair: the destination #AdgPair
697 * Converts @point to @pair in model space.
700 adg_entity_point_to_model_pair(AdgEntity
*entity
,
701 const AdgPoint
*point
, AdgPair
*pair
)
703 const AdgMatrix
*paper_matrix
;
705 g_return_if_fail(ADG_IS_ENTITY(entity
));
706 g_return_if_fail(point
!= NULL
);
707 g_return_if_fail(pair
!= NULL
);
709 paper_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
710 adg_pair_copy(pair
, &point
->paper
);
711 cpml_pair_transform(pair
, paper_matrix
);
713 pair
->x
+= point
->model
.x
;
714 pair
->y
+= point
->model
.y
;
718 * adg_entity_point_to_paper_pair:
719 * @entity: an #AdgEntity
720 * @point: the source #AdgPoint
721 * @pair: the destination #AdgPair
723 * Converts @point to @pair in paper space.
726 adg_entity_point_to_paper_pair(AdgEntity
*entity
,
727 const AdgPoint
*point
, AdgPair
*pair
)
729 const AdgMatrix
*model_matrix
;
731 g_return_if_fail(ADG_IS_ENTITY(entity
));
732 g_return_if_fail(point
!= NULL
);
733 g_return_if_fail(pair
!= NULL
);
735 model_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
736 adg_pair_copy(pair
, &point
->model
);
737 cpml_pair_transform(pair
, model_matrix
);
739 pair
->x
+= point
->paper
.x
;
740 pair
->y
+= point
->paper
.y
;
741 g_print("Pair (%lf, %lf)\n", pair
->x
, pair
->y
);
745 * adg_entity_model_matrix_applied:
746 * @entity: an #AdgEntity
748 * Return value: %TRUE if the model matrix didn't change from the last render
751 adg_entity_model_matrix_applied(AdgEntity
*entity
)
753 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
754 return ADG_ISSET(entity
->priv
->flags
, MODEL_MATRIX_APPLIED
);
758 * adg_entity_paper_matrix_applied:
759 * @entity: an #AdgEntity
761 * Return value: %TRUE if the paper matrix didn't change from the last render
764 adg_entity_paper_matrix_applied(AdgEntity
*entity
)
766 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
767 return ADG_ISSET(entity
->priv
->flags
, PAPER_MATRIX_APPLIED
);
771 * adg_entity_model_applied:
772 * @entity: an #AdgEntity
774 * Return value: %TRUE if the model didn't change from the last render
777 adg_entity_model_applied(AdgEntity
*entity
)
779 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
780 return ADG_ISSET(entity
->priv
->flags
, MODEL_APPLIED
);
784 * adg_entity_invalidate:
785 * @entity: an #AdgEntity
787 * Emits the "invalidate" signal on @entity and all its children, if any,
788 * so subsequent rendering will need a global recomputation.
791 adg_entity_invalidate(AdgEntity
*entity
)
793 g_return_if_fail(ADG_IS_ENTITY(entity
));
795 g_signal_emit(entity
, signals
[INVALIDATE
], 0, NULL
);
800 * @entity: an #AdgEntity
801 * @cr: a #cairo_t drawing context
803 * Emits the "render" signal on @entity and all its children, if any,
804 * causing the rendering operation the @cr cairo context.
807 adg_entity_render(AdgEntity
*entity
, cairo_t
*cr
)
809 g_return_if_fail(ADG_IS_ENTITY(entity
));
811 g_signal_emit(entity
, signals
[RENDER
], 0, cr
);
815 static AdgContainer
*
816 get_parent(AdgEntity
*entity
)
818 return entity
->priv
->parent
;
822 set_parent(AdgEntity
*entity
, AdgContainer
*parent
)
824 entity
->priv
->parent
= parent
;
828 parent_set(AdgEntity
*entity
, AdgContainer
*old_parent
)
830 if (ADG_IS_CONTAINER(old_parent
)) {
831 const AdgMatrix
*old_model
;
832 const AdgMatrix
*old_paper
;
834 old_model
= adg_entity_get_model_matrix((AdgEntity
*) old_parent
);
835 old_paper
= adg_entity_get_paper_matrix((AdgEntity
*) old_parent
);
837 adg_entity_model_matrix_changed(entity
, old_model
);
838 adg_entity_paper_matrix_changed(entity
, old_paper
);
843 get_context(AdgEntity
*entity
)
847 if (entity
->priv
->context
)
848 return entity
->priv
->context
;
850 parent
= (AdgEntity
*) entity
->priv
->parent
;
852 return parent
? ADG_ENTITY_GET_CLASS(parent
)->get_context(parent
) : NULL
;
856 set_context(AdgEntity
*entity
, AdgContext
*context
)
858 if (entity
->priv
->context
)
859 g_object_unref((GObject
*) entity
->priv
->context
);
861 g_object_ref((GObject
*) context
);
862 entity
->priv
->context
= context
;
866 model_matrix_changed(AdgEntity
*entity
, AdgMatrix
*parent_matrix
)
868 ADG_UNSET(entity
->priv
->flags
, MODEL_MATRIX_APPLIED
);
872 paper_matrix_changed(AdgEntity
*entity
, AdgMatrix
*parent_matrix
)
874 ADG_UNSET(entity
->priv
->flags
, PAPER_MATRIX_APPLIED
);
878 render(AdgEntity
*entity
, cairo_t
*cr
)
880 ADG_SET(entity
->priv
->flags
,
881 MODEL_MATRIX_APPLIED
| PAPER_MATRIX_APPLIED
| MODEL_APPLIED
);
884 static const AdgMatrix
*
885 get_model_matrix(AdgEntity
*entity
)
887 return adg_entity_get_model_matrix((AdgEntity
*) entity
->priv
->parent
);
890 static const AdgMatrix
*
891 get_paper_matrix(AdgEntity
*entity
)
893 return adg_entity_get_paper_matrix((AdgEntity
*) entity
->priv
->parent
);