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.
24 * @short_description: The base class for renderable objects
26 * This abstract class provides a base interface for all renderable objects
27 * (all the objects that can be printed or viewed).
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
38 #include "adg-entity.h"
39 #include "adg-entity-private.h"
40 #include "adg-canvas.h"
41 #include "adg-context.h"
62 static void get_property (GObject
*object
,
66 static void set_property (GObject
*object
,
70 static void dispose (GObject
*object
);
71 static AdgContainer
* get_parent (AdgEntity
*entity
);
72 static void set_parent (AdgEntity
*entity
,
73 AdgContainer
*parent
);
74 static void parent_set (AdgEntity
*entity
,
75 AdgContainer
*old_parent
);
76 static AdgContext
* get_context (AdgEntity
*entity
);
77 static void set_context (AdgEntity
*entity
,
79 static void model_matrix_changed (AdgEntity
*entity
,
80 AdgMatrix
*parent_matrix
);
81 static void paper_matrix_changed (AdgEntity
*entity
,
82 AdgMatrix
*parent_matrix
);
83 static void render (AdgEntity
*entity
,
85 static const AdgMatrix
*get_model_matrix (AdgEntity
*entity
);
86 static const AdgMatrix
*get_paper_matrix (AdgEntity
*entity
);
88 static guint signals
[LAST_SIGNAL
] = { 0 };
91 G_DEFINE_ABSTRACT_TYPE(AdgEntity
, adg_entity
, G_TYPE_INITIALLY_UNOWNED
);
95 adg_entity_class_init(AdgEntityClass
*klass
)
97 GObjectClass
*gobject_class
;
100 gobject_class
= (GObjectClass
*) klass
;
102 g_type_class_add_private(klass
, sizeof(AdgEntityPrivate
));
104 gobject_class
->get_property
= get_property
;
105 gobject_class
->set_property
= set_property
;
106 gobject_class
->dispose
= dispose
;
108 klass
->get_parent
= get_parent
;
109 klass
->set_parent
= set_parent
;
110 klass
->parent_set
= parent_set
;
111 klass
->get_context
= get_context
;
112 klass
->model_matrix_changed
= model_matrix_changed
;
113 klass
->paper_matrix_changed
= paper_matrix_changed
;
114 klass
->invalidate
= NULL
;
115 klass
->render
= render
;
116 klass
->get_model_matrix
= get_model_matrix
;
117 klass
->get_paper_matrix
= get_paper_matrix
;
119 param
= g_param_spec_object("parent",
120 P_("Parent Container"),
121 P_("The parent AdgContainer of this entity or NULL if this is a top-level entity"),
122 ADG_TYPE_CONTAINER
, G_PARAM_READWRITE
);
123 g_object_class_install_property(gobject_class
, PROP_PARENT
, param
);
125 param
= g_param_spec_object("context",
127 P_("The context associated to this entity or NULL to inherit the parent context"),
128 ADG_TYPE_CONTEXT
, G_PARAM_READWRITE
);
129 g_object_class_install_property(gobject_class
, PROP_CONTEXT
, param
);
132 * AdgEntity::parent-set:
133 * @entity: an #AdgEntity
134 * @parent: the #AdgContainer parent of @entity
136 * Emitted after the parent container has changed.
138 signals
[PARENT_SET
] =
139 g_signal_new("parent-set",
140 G_OBJECT_CLASS_TYPE(gobject_class
),
142 G_STRUCT_OFFSET(AdgEntityClass
, parent_set
),
144 g_cclosure_marshal_VOID__OBJECT
,
145 G_TYPE_NONE
, 1, ADG_TYPE_CONTAINER
);
148 * AdgEntity::model-matrix-changed:
149 * @entity: an #AdgEntity
150 * @parent_matrix: the parent model matrix
152 * Emitted after the current model matrix has changed.
154 signals
[MODEL_MATRIX_CHANGED
] =
155 g_signal_new("model-matrix-changed",
156 G_OBJECT_CLASS_TYPE(gobject_class
),
158 G_STRUCT_OFFSET(AdgEntityClass
, model_matrix_changed
),
160 g_cclosure_marshal_VOID__BOXED
,
162 ADG_TYPE_MATRIX
| G_SIGNAL_TYPE_STATIC_SCOPE
);
165 * AdgEntity::paper-matrix-changed:
166 * @entity: an #AdgEntity
167 * @parent_matrix: the parent paper matrix
169 * Emitted after the current paper matrix has changed.
171 signals
[PAPER_MATRIX_CHANGED
] =
172 g_signal_new("paper-matrix-changed",
173 G_OBJECT_CLASS_TYPE(gobject_class
),
175 G_STRUCT_OFFSET(AdgEntityClass
, paper_matrix_changed
),
177 g_cclosure_marshal_VOID__BOXED
,
179 ADG_TYPE_MATRIX
| G_SIGNAL_TYPE_STATIC_SCOPE
);
182 * AdgEntity::invalidate:
183 * @entity: an #AdgEntity
185 * Clears the cached data of @entity.
187 signals
[INVALIDATE
] =
188 g_signal_new("invalidate",
189 G_OBJECT_CLASS_TYPE(gobject_class
),
191 G_STRUCT_OFFSET(AdgEntityClass
, invalidate
),
193 g_cclosure_marshal_VOID__BOOLEAN
,
198 * @entity: an #AdgEntity
199 * @cr: a #cairo_t drawing context
201 * Causes the rendering of @entity on @cr.
204 g_signal_new("render",
205 G_OBJECT_CLASS_TYPE(gobject_class
),
207 G_STRUCT_OFFSET(AdgEntityClass
, render
),
209 g_cclosure_marshal_VOID__POINTER
,
210 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
214 adg_entity_init(AdgEntity
*entity
)
216 AdgEntityPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(entity
,
221 data
->context
= NULL
;
227 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
229 AdgEntity
*entity
= (AdgEntity
*) object
;
233 g_value_set_object(value
, get_parent(entity
));
236 g_value_set_object(value
, get_context(entity
));
239 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
245 set_property(GObject
*object
,
246 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
248 AdgEntity
*entity
= (AdgEntity
*) object
;
252 set_parent(entity
, (AdgContainer
*) g_value_get_object(value
));
255 set_context(entity
, g_value_get_object(value
));
258 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
264 dispose(GObject
*object
)
267 AdgEntityPrivate
*data
;
268 GObjectClass
*object_class
;
270 entity
= (AdgEntity
*) object
;
272 object_class
= (GObjectClass
*) adg_entity_parent_class
;
275 adg_container_remove(data
->parent
, entity
);
277 if (object_class
->dispose
!= NULL
)
278 object_class
->dispose(object
);
283 * adg_entity_get_parent:
284 * @entity: an #AdgEntity
286 * Gets the container parent of @entity.
288 * This function is only useful in entity implementations.
290 * Return value: the container object or %NULL if @entity is not contained
293 adg_entity_get_parent(AdgEntity
*entity
)
295 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
297 return ADG_ENTITY_GET_CLASS(entity
)->get_parent(entity
);
301 * adg_entity_set_parent:
302 * @entity: an #AdgEntity
303 * @parent: an #AdgContainer
305 * Sets a new container of @entity.
307 * This function is only useful in entity implementations.
310 adg_entity_set_parent(AdgEntity
*entity
, AdgContainer
*parent
)
312 g_return_if_fail(ADG_IS_ENTITY(entity
));
314 ADG_ENTITY_GET_CLASS(entity
)->set_parent(entity
, parent
);
315 g_object_notify((GObject
*) entity
, "parent");
319 * adg_entity_unparent:
320 * @entity: an #AdgEntity
322 * Removes the current parent of @entity, properly handling
323 * the references between them.
325 * If @entity has no parent, this function simply returns.
328 adg_entity_unparent(AdgEntity
*entity
)
330 AdgContainer
*old_parent
;
332 g_return_if_fail(ADG_IS_ENTITY(entity
));
334 old_parent
= ADG_ENTITY_GET_CLASS(entity
)->get_parent(entity
);
336 if (old_parent
== NULL
)
339 ADG_ENTITY_GET_CLASS(entity
)->set_parent(entity
, NULL
);
340 g_signal_emit(entity
, signals
[PARENT_SET
], 0, old_parent
);
342 g_object_unref(entity
);
346 * adg_entity_reparent:
347 * @entity: an #AdgEntity
348 * @parent: the new container
350 * Moves @entity from the old parent to @parent, handling reference
351 * count issues to avoid destroying the object.
354 adg_entity_reparent(AdgEntity
*entity
, AdgContainer
*parent
)
356 AdgContainer
*old_parent
;
358 g_return_if_fail(ADG_IS_CONTAINER(parent
));
360 old_parent
= adg_entity_get_parent(entity
);
362 /* Reparenting on the same container: do nothing */
363 if (old_parent
== parent
)
366 g_return_if_fail(ADG_IS_CONTAINER(old_parent
));
368 g_object_ref(entity
);
369 adg_container_remove(old_parent
, entity
);
370 adg_container_add(parent
, entity
);
371 g_object_unref(entity
);
375 * adg_entity_get_context:
376 * @entity: an #AdgEntity instance
378 * Gets the context associated to @entity.
379 * If no context was explicitely set, get the parent context.
381 * Return value: the requested context or %NULL on errors
384 adg_entity_get_context(AdgEntity
*entity
)
386 AdgEntityPrivate
*data
;
388 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
393 return data
->context
;
396 return adg_entity_get_context((AdgEntity
*) data
->parent
);
402 * adg_entity_set_context:
403 * @entity: an #AdgEntity instance
404 * @context: the new context
406 * Sets a new context. The old context (if any) will be unreferenced
407 * while a new reference will be added to @context.
410 adg_entity_set_context(AdgEntity
*entity
, AdgContext
*context
)
412 g_return_if_fail(ADG_IS_ENTITY(entity
));
413 g_return_if_fail(ADG_IS_CONTEXT(context
));
415 set_context(entity
, context
);
416 g_object_notify((GObject
*) entity
, "context");
420 * adg_entity_get_canvas:
421 * @entity: an #AdgEntity
423 * Walks on the @entity hierarchy and gets the first parent of @entity that is
424 * of #AdgCanvas derived type.
426 * Return value: the requested object or %NULL if there is no #AdgCanvas in
427 * the parent hierarchy.
430 adg_entity_get_canvas(AdgEntity
*entity
)
432 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
435 if (ADG_IS_CANVAS(entity
))
436 return (AdgCanvas
*) entity
;
438 entity
= (AdgEntity
*) adg_entity_get_parent(entity
);
445 * adg_entity_get_model_matrix:
446 * @entity: an #AdgEntity object
448 * Gets the model matrix to be used in rendering this @entity.
450 * Return value: the requested matrix
453 adg_entity_get_model_matrix(AdgEntity
*entity
)
455 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
456 return ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
460 * adg_entity_get_paper_matrix:
461 * @entity: an #AdgEntity object
463 * Gets the paper matrix to be used in rendering this @entity.
465 * Return value: the requested matrix
468 adg_entity_get_paper_matrix(AdgEntity
*entity
)
470 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
471 return ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
475 * adg_entity_scale_to_model:
476 * @entity: an #AdgEntity object
477 * @cr: a #cairo_t drawing context
479 * Sets the model matrix as current matrix on @cr. The translation
480 * and rotation component of the previous matrix are kept: only the
484 adg_entity_scale_to_model(AdgEntity
*entity
, cairo_t
*cr
)
486 const AdgMatrix
*model_matrix
;
487 cairo_matrix_t matrix
;
489 g_return_if_fail(ADG_IS_ENTITY(entity
));
491 model_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
492 cairo_get_matrix(cr
, &matrix
);
494 matrix
.xx
= model_matrix
->xx
;
495 matrix
.yy
= model_matrix
->yy
;
496 cairo_set_matrix(cr
, &matrix
);
500 * adg_entity_scale_to_paper:
501 * @entity: an #AdgEntity object
502 * @cr: a #cairo_t drawing context
504 * Sets the paper matrix as current matrix on @cr. The translation
505 * and rotation component of the previous matrix are kept: only the
509 adg_entity_scale_to_paper(AdgEntity
*entity
, cairo_t
*cr
)
511 const AdgMatrix
*paper_matrix
;
512 cairo_matrix_t matrix
;
514 g_return_if_fail(ADG_IS_ENTITY(entity
));
516 paper_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
517 cairo_get_matrix(cr
, &matrix
);
519 matrix
.xx
= paper_matrix
->xx
;
520 matrix
.yy
= paper_matrix
->yy
;
521 cairo_set_matrix(cr
, &matrix
);
525 * adg_entity_build_paper2model:
526 * @entity: an #AdgEntity
527 * @matrix: the destination matrix
529 * Builds a matrix to translate from paper to model space and
530 * put the result in @matrix.
532 * Return value: %TRUE on success, %FALSE on errors
535 adg_entity_build_paper2model(AdgEntity
*entity
, AdgMatrix
*matrix
)
537 cairo_status_t status
;
539 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
540 g_return_val_if_fail(matrix
!= NULL
, FALSE
);
542 adg_matrix_copy(matrix
, adg_entity_get_model_matrix(entity
));
543 status
= cairo_matrix_invert(matrix
);
544 if (status
!= CAIRO_STATUS_SUCCESS
) {
545 g_error("Unable to invert model matrix (cairo message: %s)",
546 cairo_status_to_string(status
));
550 cairo_matrix_multiply(matrix
, matrix
, adg_entity_get_paper_matrix(entity
));
555 * adg_entity_build_model2paper:
556 * @entity: an #AdgEntity
557 * @matrix: the destination matrix
559 * Builds a matrix to translate from model to paper space and
560 * put the result in @matrix.
562 * Return value: %TRUE on success, %FALSE on errors
565 adg_entity_build_model2paper(AdgEntity
*entity
, AdgMatrix
*matrix
)
567 cairo_status_t status
;
569 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
570 g_return_val_if_fail(matrix
!= NULL
, FALSE
);
572 adg_matrix_copy(matrix
, adg_entity_get_paper_matrix(entity
));
573 status
= cairo_matrix_invert(matrix
);
574 if (status
!= CAIRO_STATUS_SUCCESS
) {
575 g_error("Unable to invert paper matrix (cairo message: %s)",
576 cairo_status_to_string(status
));
580 cairo_matrix_multiply(matrix
, matrix
, adg_entity_get_model_matrix(entity
));
585 * adg_entity_model_matrix_changed:
586 * @entity: an #AdgEntity
587 * @parent_matrix: the parent #AdgMatrix
589 * Emits the "model-matrix-changed" signal on @entity.
591 * This function is only useful in entity implementations.
594 adg_entity_model_matrix_changed(AdgEntity
*entity
,
595 const AdgMatrix
*parent_matrix
)
597 g_return_if_fail(ADG_IS_ENTITY(entity
));
599 g_signal_emit(entity
, signals
[MODEL_MATRIX_CHANGED
], 0, parent_matrix
);
603 * adg_entity_paper_matrix_changed:
604 * @entity: an #AdgEntity
605 * @parent_matrix: the parent #AdgMatrix
607 * Emits the "paper-matrix-changed" signal on @entity.
609 * This function is only useful in entity implementations.
612 adg_entity_paper_matrix_changed(AdgEntity
*entity
,
613 const AdgMatrix
*parent_matrix
)
615 g_return_if_fail(ADG_IS_ENTITY(entity
));
617 g_signal_emit(entity
, signals
[PAPER_MATRIX_CHANGED
], 0, parent_matrix
);
621 * adg_entity_get_style:
622 * @entity: an #AdgEntity
623 * @style_slot: the slot of the style to get
625 * Gets a style from this entity. If the entity has no context associated
626 * or the style in undefined within this context, gets the style from its
629 * Return value: the requested style or %NULL on errors
632 adg_entity_get_style(AdgEntity
*entity
, AdgStyleSlot style_slot
)
634 AdgEntityPrivate
*data
;
636 g_return_val_if_fail(ADG_IS_ENTITY(entity
), NULL
);
641 AdgStyle
*style
= adg_context_get_style(data
->context
, style_slot
);
647 return adg_entity_get_style((AdgEntity
*) data
->parent
, style_slot
);
654 * @entity: an #AdgEntity
655 * @style_slot: the slot of the style to apply
656 * @cr: a #cairo_t drawing context
658 * Applies the specified style to the @cr cairo context.
661 adg_entity_apply(AdgEntity
*entity
, AdgStyleSlot style_slot
, cairo_t
*cr
)
663 AdgStyle
*style
= adg_entity_get_style(entity
, style_slot
);
666 adg_style_apply(style
, cr
);
670 * adg_entity_point_to_pair:
671 * @entity: an #AdgEntity
672 * @point: the source #AdgPoint
673 * @pair: the destination #AdgPair
674 * @cr: a #cairo_t drawing context
676 * Converts @point to @pair using the model and paper matrix of @entity,
677 * as if the current matrix is an identity matrix.
680 adg_entity_point_to_pair(AdgEntity
*entity
, const AdgPoint
*point
,
681 AdgPair
*pair
, cairo_t
*cr
)
683 AdgMatrix inverted_ctm
;
684 const AdgMatrix
*model_matrix
;
685 const AdgMatrix
*paper_matrix
;
686 AdgPair model_pair
, paper_pair
;
688 g_return_if_fail(ADG_IS_ENTITY(entity
));
689 g_return_if_fail(point
!= NULL
);
690 g_return_if_fail(pair
!= NULL
);
692 cairo_get_matrix(cr
, &inverted_ctm
);
693 cairo_matrix_invert(&inverted_ctm
);
694 model_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
695 paper_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
697 cpml_pair_copy(&model_pair
, &point
->model
);
698 cpml_pair_transform(&model_pair
, model_matrix
);
700 cpml_pair_copy(&paper_pair
, &point
->paper
);
701 cpml_pair_transform(&paper_pair
, paper_matrix
);
703 pair
->x
= model_pair
.x
+ paper_pair
.x
;
704 pair
->y
= model_pair
.y
+ paper_pair
.y
;
706 cpml_pair_transform(pair
, &inverted_ctm
);
710 * adg_entity_point_to_model_pair:
711 * @entity: an #AdgEntity
712 * @point: the source #AdgPoint
713 * @pair: the destination #AdgPair
715 * Converts @point to @pair in model space.
718 adg_entity_point_to_model_pair(AdgEntity
*entity
,
719 const AdgPoint
*point
, AdgPair
*pair
)
721 const AdgMatrix
*paper_matrix
;
723 g_return_if_fail(ADG_IS_ENTITY(entity
));
724 g_return_if_fail(point
!= NULL
);
725 g_return_if_fail(pair
!= NULL
);
727 paper_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_paper_matrix(entity
);
728 cpml_pair_copy(pair
, &point
->paper
);
729 cpml_pair_transform(pair
, paper_matrix
);
731 pair
->x
+= point
->model
.x
;
732 pair
->y
+= point
->model
.y
;
736 * adg_entity_point_to_paper_pair:
737 * @entity: an #AdgEntity
738 * @point: the source #AdgPoint
739 * @pair: the destination #AdgPair
741 * Converts @point to @pair in paper space.
744 adg_entity_point_to_paper_pair(AdgEntity
*entity
,
745 const AdgPoint
*point
, AdgPair
*pair
)
747 const AdgMatrix
*model_matrix
;
749 g_return_if_fail(ADG_IS_ENTITY(entity
));
750 g_return_if_fail(point
!= NULL
);
751 g_return_if_fail(pair
!= NULL
);
753 model_matrix
= ADG_ENTITY_GET_CLASS(entity
)->get_model_matrix(entity
);
754 cpml_pair_copy(pair
, &point
->model
);
755 cpml_pair_transform(pair
, model_matrix
);
757 pair
->x
+= point
->paper
.x
;
758 pair
->y
+= point
->paper
.y
;
759 g_print("Pair (%lf, %lf)\n", pair
->x
, pair
->y
);
763 * adg_entity_model_matrix_applied:
764 * @entity: an #AdgEntity
766 * Return value: %TRUE if the model matrix didn't change from the last render
769 adg_entity_model_matrix_applied(AdgEntity
*entity
)
771 AdgEntityPrivate
*data
;
773 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
777 return ADG_ISSET(data
->flags
, MODEL_MATRIX_APPLIED
);
781 * adg_entity_paper_matrix_applied:
782 * @entity: an #AdgEntity
784 * Return value: %TRUE if the paper matrix didn't change from the last render
787 adg_entity_paper_matrix_applied(AdgEntity
*entity
)
789 AdgEntityPrivate
*data
;
791 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
795 return ADG_ISSET(data
->flags
, PAPER_MATRIX_APPLIED
);
799 * adg_entity_model_applied:
800 * @entity: an #AdgEntity
802 * Return value: %TRUE if the model didn't change from the last render
805 adg_entity_model_applied(AdgEntity
*entity
)
807 AdgEntityPrivate
*data
;
809 g_return_val_if_fail(ADG_IS_ENTITY(entity
), FALSE
);
813 return ADG_ISSET(data
->flags
, MODEL_APPLIED
);
817 * adg_entity_invalidate:
818 * @entity: an #AdgEntity
820 * Emits the "invalidate" signal on @entity and all its children, if any,
821 * so subsequent rendering will need a global recomputation.
824 adg_entity_invalidate(AdgEntity
*entity
)
826 g_return_if_fail(ADG_IS_ENTITY(entity
));
828 g_signal_emit(entity
, signals
[INVALIDATE
], 0, NULL
);
833 * @entity: an #AdgEntity
834 * @cr: a #cairo_t drawing context
836 * Emits the "render" signal on @entity and all its children, if any,
837 * causing the rendering operation the @cr cairo context.
840 adg_entity_render(AdgEntity
*entity
, cairo_t
*cr
)
842 g_return_if_fail(ADG_IS_ENTITY(entity
));
844 g_signal_emit(entity
, signals
[RENDER
], 0, cr
);
848 static AdgContainer
*
849 get_parent(AdgEntity
*entity
)
851 AdgEntityPrivate
*data
= entity
->data
;
857 set_parent(AdgEntity
*entity
, AdgContainer
*parent
)
859 AdgEntityPrivate
*data
= entity
->data
;
861 data
->parent
= parent
;
865 parent_set(AdgEntity
*entity
, AdgContainer
*old_parent
)
867 if (ADG_IS_CONTAINER(old_parent
)) {
868 const AdgMatrix
*old_model
;
869 const AdgMatrix
*old_paper
;
871 old_model
= adg_entity_get_model_matrix((AdgEntity
*) old_parent
);
872 old_paper
= adg_entity_get_paper_matrix((AdgEntity
*) old_parent
);
874 adg_entity_model_matrix_changed(entity
, old_model
);
875 adg_entity_paper_matrix_changed(entity
, old_paper
);
880 get_context(AdgEntity
*entity
)
882 AdgEntityPrivate
*data
= entity
->data
;
886 return data
->context
;
888 parent
= (AdgEntity
*) data
->parent
;
890 return parent
? ADG_ENTITY_GET_CLASS(parent
)->get_context(parent
) : NULL
;
894 set_context(AdgEntity
*entity
, AdgContext
*context
)
896 AdgEntityPrivate
*data
= entity
->data
;
899 g_object_unref((GObject
*) data
->context
);
901 g_object_ref((GObject
*) context
);
902 data
->context
= context
;
906 model_matrix_changed(AdgEntity
*entity
, AdgMatrix
*parent_matrix
)
908 AdgEntityPrivate
*data
= entity
->data
;
910 ADG_UNSET(data
->flags
, MODEL_MATRIX_APPLIED
);
914 paper_matrix_changed(AdgEntity
*entity
, AdgMatrix
*parent_matrix
)
916 AdgEntityPrivate
*data
= entity
->data
;
918 ADG_UNSET(data
->flags
, PAPER_MATRIX_APPLIED
);
922 render(AdgEntity
*entity
, cairo_t
*cr
)
924 AdgEntityPrivate
*data
= entity
->data
;
927 MODEL_MATRIX_APPLIED
| PAPER_MATRIX_APPLIED
| MODEL_APPLIED
);
930 static const AdgMatrix
*
931 get_model_matrix(AdgEntity
*entity
)
933 AdgEntityPrivate
*data
= entity
->data
;
935 return adg_entity_get_model_matrix((AdgEntity
*) data
->parent
);
938 static const AdgMatrix
*
939 get_paper_matrix(AdgEntity
*entity
)
941 AdgEntityPrivate
*data
= entity
->data
;
943 return adg_entity_get_paper_matrix((AdgEntity
*) data
->parent
);