1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module graphene.Matrix;
26 
27 private import glib.ConstructionException;
28 private import glib.MemorySlice;
29 private import gobject.ObjectG;
30 private import graphene.Box;
31 private import graphene.Euler;
32 private import graphene.Point;
33 private import graphene.Point3D;
34 private import graphene.Quad;
35 private import graphene.Quaternion;
36 private import graphene.Ray;
37 private import graphene.Rect;
38 private import graphene.Sphere;
39 private import graphene.Vec3;
40 private import graphene.Vec4;
41 private import graphene.c.functions;
42 public  import graphene.c.types;
43 private import gtkd.Loader;
44 
45 
46 /**
47  * A structure capable of holding a 4x4 matrix.
48  * 
49  * The contents of the #graphene_matrix_t structure are private and
50  * should never be accessed directly.
51  */
52 public class Matrix
53 {
54 	/** the main Gtk struct */
55 	protected graphene_matrix_t* graphene_matrix;
56 	protected bool ownedRef;
57 
58 	/** Get the main Gtk struct */
59 	public graphene_matrix_t* getMatrixStruct(bool transferOwnership = false)
60 	{
61 		if (transferOwnership)
62 			ownedRef = false;
63 		return graphene_matrix;
64 	}
65 
66 	/** the main Gtk struct as a void* */
67 	protected void* getStruct()
68 	{
69 		return cast(void*)graphene_matrix;
70 	}
71 
72 	/**
73 	 * Sets our main struct and passes it to the parent class.
74 	 */
75 	public this (graphene_matrix_t* graphene_matrix, bool ownedRef = false)
76 	{
77 		this.graphene_matrix = graphene_matrix;
78 		this.ownedRef = ownedRef;
79 	}
80 
81 	~this ()
82 	{
83 		if ( Linker.isLoaded(LIBRARY_GRAPHENE) && ownedRef )
84 			graphene_matrix_free(graphene_matrix);
85 	}
86 
87 
88 	/** */
89 	public static GType getType()
90 	{
91 		return graphene_matrix_get_type();
92 	}
93 
94 	/**
95 	 * Allocates a new #graphene_matrix_t.
96 	 *
97 	 * Returns: the newly allocated matrix
98 	 *
99 	 * Since: 1.0
100 	 *
101 	 * Throws: ConstructionException GTK+ fails to create the object.
102 	 */
103 	public this()
104 	{
105 		auto __p = graphene_matrix_alloc();
106 
107 		if(__p is null)
108 		{
109 			throw new ConstructionException("null returned by alloc");
110 		}
111 
112 		this(cast(graphene_matrix_t*) __p);
113 	}
114 
115 	/**
116 	 * Decomposes a transformation matrix into its component transformations.
117 	 *
118 	 * The algorithm for decomposing a matrix is taken from the
119 	 * [CSS3 Transforms specification](http://dev.w3.org/csswg/css-transforms/);
120 	 * specifically, the decomposition code is based on the equivalent code
121 	 * published in "Graphics Gems II", edited by Jim Arvo, and
122 	 * [available online](http://tog.acm.org/resources/GraphicsGems/gemsii/unmatrix.c).
123 	 *
124 	 * Params:
125 	 *     translate = the translation vector
126 	 *     scale = the scale vector
127 	 *     rotate = the rotation quaternion
128 	 *     shear = the shear vector
129 	 *     perspective = the perspective vector
130 	 *
131 	 * Returns: `true` if the matrix could be decomposed
132 	 */
133 	public bool decompose(out Vec3 translate, out Vec3 scale, out Quaternion rotate, out Vec3 shear, out Vec4 perspective)
134 	{
135 		graphene_vec3_t* outtranslate = sliceNew!graphene_vec3_t();
136 		graphene_vec3_t* outscale = sliceNew!graphene_vec3_t();
137 		graphene_quaternion_t* outrotate = sliceNew!graphene_quaternion_t();
138 		graphene_vec3_t* outshear = sliceNew!graphene_vec3_t();
139 		graphene_vec4_t* outperspective = sliceNew!graphene_vec4_t();
140 
141 		auto __p = graphene_matrix_decompose(graphene_matrix, outtranslate, outscale, outrotate, outshear, outperspective) != 0;
142 
143 		translate = ObjectG.getDObject!(Vec3)(outtranslate, true);
144 		scale = ObjectG.getDObject!(Vec3)(outscale, true);
145 		rotate = ObjectG.getDObject!(Quaternion)(outrotate, true);
146 		shear = ObjectG.getDObject!(Vec3)(outshear, true);
147 		perspective = ObjectG.getDObject!(Vec4)(outperspective, true);
148 
149 		return __p;
150 	}
151 
152 	/**
153 	 * Computes the determinant of the given matrix.
154 	 *
155 	 * Returns: the value of the determinant
156 	 *
157 	 * Since: 1.0
158 	 */
159 	public float determinant()
160 	{
161 		return graphene_matrix_determinant(graphene_matrix);
162 	}
163 
164 	/**
165 	 * Checks whether the two given #graphene_matrix_t matrices are equal.
166 	 *
167 	 * Params:
168 	 *     b = a #graphene_matrix_t
169 	 *
170 	 * Returns: `true` if the two matrices are equal, and `false` otherwise
171 	 *
172 	 * Since: 1.10
173 	 */
174 	public bool equal(Matrix b)
175 	{
176 		return graphene_matrix_equal(graphene_matrix, (b is null) ? null : b.getMatrixStruct()) != 0;
177 	}
178 
179 	/**
180 	 * Checks whether the two given #graphene_matrix_t matrices are
181 	 * byte-by-byte equal.
182 	 *
183 	 * While this function is faster than graphene_matrix_equal(), it
184 	 * can also return false negatives, so it should be used in
185 	 * conjuction with either graphene_matrix_equal() or
186 	 * graphene_matrix_near(). For instance:
187 	 *
188 	 * |[<!-- language="C" -->
189 	 * if (graphene_matrix_equal_fast (a, b))
190 	 * {
191 	 * // matrices are definitely the same
192 	 * }
193 	 * else
194 	 * {
195 	 * if (graphene_matrix_equal (a, b))
196 	 * // matrices contain the same values within an epsilon of FLT_EPSILON
197 	 * else if (graphene_matrix_near (a, b, 0.0001))
198 	 * // matrices contain the same values within an epsilon of 0.0001
199 	 * else
200 	 * // matrices are not equal
201 	 * }
202 	 * ]|
203 	 *
204 	 * Params:
205 	 *     b = a #graphene_matrix_t
206 	 *
207 	 * Returns: `true` if the matrices are equal. and `false` otherwise
208 	 *
209 	 * Since: 1.10
210 	 */
211 	public bool equalFast(Matrix b)
212 	{
213 		return graphene_matrix_equal_fast(graphene_matrix, (b is null) ? null : b.getMatrixStruct()) != 0;
214 	}
215 
216 	/**
217 	 * Frees the resources allocated by graphene_matrix_alloc().
218 	 *
219 	 * Since: 1.0
220 	 */
221 	public void free()
222 	{
223 		graphene_matrix_free(graphene_matrix);
224 		ownedRef = false;
225 	}
226 
227 	/**
228 	 * Retrieves the given row vector at @index_ inside a matrix.
229 	 *
230 	 * Params:
231 	 *     index = the index of the row vector, between 0 and 3
232 	 *     res = return location for the #graphene_vec4_t
233 	 *         that is used to store the row vector
234 	 *
235 	 * Since: 1.0
236 	 */
237 	public void getRow(uint index, out Vec4 res)
238 	{
239 		graphene_vec4_t* outres = sliceNew!graphene_vec4_t();
240 
241 		graphene_matrix_get_row(graphene_matrix, index, outres);
242 
243 		res = ObjectG.getDObject!(Vec4)(outres, true);
244 	}
245 
246 	/**
247 	 * Retrieves the value at the given @row and @col index.
248 	 *
249 	 * Params:
250 	 *     row = the row index
251 	 *     col = the column index
252 	 *
253 	 * Returns: the value at the given indices
254 	 *
255 	 * Since: 1.0
256 	 */
257 	public float getValue(uint row, uint col)
258 	{
259 		return graphene_matrix_get_value(graphene_matrix, row, col);
260 	}
261 
262 	/**
263 	 * Retrieves the scaling factor on the X axis in @m.
264 	 *
265 	 * Returns: the value of the scaling factor
266 	 *
267 	 * Since: 1.0
268 	 */
269 	public float getXScale()
270 	{
271 		return graphene_matrix_get_x_scale(graphene_matrix);
272 	}
273 
274 	/**
275 	 * Retrieves the translation component on the X axis from @m.
276 	 *
277 	 * Returns: the translation component
278 	 *
279 	 * Since: 1.10
280 	 */
281 	public float getXTranslation()
282 	{
283 		return graphene_matrix_get_x_translation(graphene_matrix);
284 	}
285 
286 	/**
287 	 * Retrieves the scaling factor on the Y axis in @m.
288 	 *
289 	 * Returns: the value of the scaling factor
290 	 *
291 	 * Since: 1.0
292 	 */
293 	public float getYScale()
294 	{
295 		return graphene_matrix_get_y_scale(graphene_matrix);
296 	}
297 
298 	/**
299 	 * Retrieves the translation component on the Y axis from @m.
300 	 *
301 	 * Returns: the translation component
302 	 *
303 	 * Since: 1.10
304 	 */
305 	public float getYTranslation()
306 	{
307 		return graphene_matrix_get_y_translation(graphene_matrix);
308 	}
309 
310 	/**
311 	 * Retrieves the scaling factor on the Z axis in @m.
312 	 *
313 	 * Returns: the value of the scaling factor
314 	 *
315 	 * Since: 1.0
316 	 */
317 	public float getZScale()
318 	{
319 		return graphene_matrix_get_z_scale(graphene_matrix);
320 	}
321 
322 	/**
323 	 * Retrieves the translation component on the Z axis from @m.
324 	 *
325 	 * Returns: the translation component
326 	 *
327 	 * Since: 1.10
328 	 */
329 	public float getZTranslation()
330 	{
331 		return graphene_matrix_get_z_translation(graphene_matrix);
332 	}
333 
334 	/**
335 	 * Initializes a #graphene_matrix_t from the values of an affine
336 	 * transformation matrix.
337 	 *
338 	 * The arguments map to the following matrix layout:
339 	 *
340 	 * |[<!-- language="plain" -->
341 	 * ⎛ xx  yx ⎞   ⎛  a   b  0 ⎞
342 	 * ⎜ xy  yy ⎟ = ⎜  c   d  0 ⎟
343 	 * ⎝ x0  y0 ⎠   ⎝ tx  ty  1 ⎠
344 	 * ]|
345 	 *
346 	 * This function can be used to convert between an affine matrix type
347 	 * from other libraries and a #graphene_matrix_t.
348 	 *
349 	 * Params:
350 	 *     xx = the xx member
351 	 *     yx = the yx member
352 	 *     xy = the xy member
353 	 *     yy = the yy member
354 	 *     x0 = the x0 member
355 	 *     y0 = the y0 member
356 	 *
357 	 * Returns: the initialized matrix
358 	 *
359 	 * Since: 1.0
360 	 */
361 	public Matrix initFrom2d(double xx, double yx, double xy, double yy, double x0, double y0)
362 	{
363 		auto __p = graphene_matrix_init_from_2d(graphene_matrix, xx, yx, xy, yy, x0, y0);
364 
365 		if(__p is null)
366 		{
367 			return null;
368 		}
369 
370 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
371 	}
372 
373 	/**
374 	 * Initializes a #graphene_matrix_t with the given array of floating
375 	 * point values.
376 	 *
377 	 * Params:
378 	 *     v = an array of at least 16 floating
379 	 *         point values
380 	 *
381 	 * Returns: the initialized matrix
382 	 *
383 	 * Since: 1.0
384 	 */
385 	public Matrix initFromFloat(float[16] v)
386 	{
387 		auto __p = graphene_matrix_init_from_float(graphene_matrix, v.ptr);
388 
389 		if(__p is null)
390 		{
391 			return null;
392 		}
393 
394 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
395 	}
396 
397 	/**
398 	 * Initializes a #graphene_matrix_t using the values of the
399 	 * given matrix.
400 	 *
401 	 * Params:
402 	 *     src = a #graphene_matrix_t
403 	 *
404 	 * Returns: the initialized matrix
405 	 *
406 	 * Since: 1.0
407 	 */
408 	public Matrix initFromMatrix(Matrix src)
409 	{
410 		auto __p = graphene_matrix_init_from_matrix(graphene_matrix, (src is null) ? null : src.getMatrixStruct());
411 
412 		if(__p is null)
413 		{
414 			return null;
415 		}
416 
417 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
418 	}
419 
420 	/**
421 	 * Initializes a #graphene_matrix_t with the given four row
422 	 * vectors.
423 	 *
424 	 * Params:
425 	 *     v0 = the first row vector
426 	 *     v1 = the second row vector
427 	 *     v2 = the third row vector
428 	 *     v3 = the fourth row vector
429 	 *
430 	 * Returns: the initialized matrix
431 	 *
432 	 * Since: 1.0
433 	 */
434 	public Matrix initFromVec4(Vec4 v0, Vec4 v1, Vec4 v2, Vec4 v3)
435 	{
436 		auto __p = graphene_matrix_init_from_vec4(graphene_matrix, (v0 is null) ? null : v0.getVec4Struct(), (v1 is null) ? null : v1.getVec4Struct(), (v2 is null) ? null : v2.getVec4Struct(), (v3 is null) ? null : v3.getVec4Struct());
437 
438 		if(__p is null)
439 		{
440 			return null;
441 		}
442 
443 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
444 	}
445 
446 	/**
447 	 * Initializes a #graphene_matrix_t compatible with #graphene_frustum_t.
448 	 *
449 	 * See also: graphene_frustum_init_from_matrix()
450 	 *
451 	 * Params:
452 	 *     left = distance of the left clipping plane
453 	 *     right = distance of the right clipping plane
454 	 *     bottom = distance of the bottom clipping plane
455 	 *     top = distance of the top clipping plane
456 	 *     zNear = distance of the near clipping plane
457 	 *     zFar = distance of the far clipping plane
458 	 *
459 	 * Returns: the initialized matrix
460 	 *
461 	 * Since: 1.2
462 	 */
463 	public Matrix initFrustum(float left, float right, float bottom, float top, float zNear, float zFar)
464 	{
465 		auto __p = graphene_matrix_init_frustum(graphene_matrix, left, right, bottom, top, zNear, zFar);
466 
467 		if(__p is null)
468 		{
469 			return null;
470 		}
471 
472 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
473 	}
474 
475 	/**
476 	 * Initializes a #graphene_matrix_t with the identity matrix.
477 	 *
478 	 * Returns: the initialized matrix
479 	 *
480 	 * Since: 1.0
481 	 */
482 	public Matrix initIdentity()
483 	{
484 		auto __p = graphene_matrix_init_identity(graphene_matrix);
485 
486 		if(__p is null)
487 		{
488 			return null;
489 		}
490 
491 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
492 	}
493 
494 	/**
495 	 * Initializes a #graphene_matrix_t so that it positions the "camera"
496 	 * at the given @eye coordinates towards an object at the @center
497 	 * coordinates. The top of the camera is aligned to the direction
498 	 * of the @up vector.
499 	 *
500 	 * Before the transform, the camera is assumed to be placed at the
501 	 * origin, looking towards the negative Z axis, with the top side of
502 	 * the camera facing in the direction of the Y axis and the right
503 	 * side in the direction of the X axis.
504 	 *
505 	 * In theory, one could use @m to transform a model of such a camera
506 	 * into world-space. However, it is more common to use the inverse of
507 	 * @m to transform another object from world coordinates to the view
508 	 * coordinates of the camera. Typically you would then apply the
509 	 * camera projection transform to get from view to screen
510 	 * coordinates.
511 	 *
512 	 * Params:
513 	 *     eye = the vector describing the position to look from
514 	 *     center = the vector describing the position to look at
515 	 *     up = the vector describing the world's upward direction; usually,
516 	 *         this is the graphene_vec3_y_axis() vector
517 	 *
518 	 * Returns: the initialized matrix
519 	 *
520 	 * Since: 1.0
521 	 */
522 	public Matrix initLookAt(Vec3 eye, Vec3 center, Vec3 up)
523 	{
524 		auto __p = graphene_matrix_init_look_at(graphene_matrix, (eye is null) ? null : eye.getVec3Struct(), (center is null) ? null : center.getVec3Struct(), (up is null) ? null : up.getVec3Struct());
525 
526 		if(__p is null)
527 		{
528 			return null;
529 		}
530 
531 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
532 	}
533 
534 	/**
535 	 * Initializes a #graphene_matrix_t with an orthographic projection.
536 	 *
537 	 * Params:
538 	 *     left = the left edge of the clipping plane
539 	 *     right = the right edge of the clipping plane
540 	 *     top = the top edge of the clipping plane
541 	 *     bottom = the bottom edge of the clipping plane
542 	 *     zNear = the distance of the near clipping plane
543 	 *     zFar = the distance of the far clipping plane
544 	 *
545 	 * Returns: the initialized matrix
546 	 *
547 	 * Since: 1.0
548 	 */
549 	public Matrix initOrtho(float left, float right, float top, float bottom, float zNear, float zFar)
550 	{
551 		auto __p = graphene_matrix_init_ortho(graphene_matrix, left, right, top, bottom, zNear, zFar);
552 
553 		if(__p is null)
554 		{
555 			return null;
556 		}
557 
558 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
559 	}
560 
561 	/**
562 	 * Initializes a #graphene_matrix_t with a perspective projection.
563 	 *
564 	 * Params:
565 	 *     fovy = the field of view angle, in degrees
566 	 *     aspect = the aspect value
567 	 *     zNear = the near Z plane
568 	 *     zFar = the far Z plane
569 	 *
570 	 * Returns: the initialized matrix
571 	 *
572 	 * Since: 1.0
573 	 */
574 	public Matrix initPerspective(float fovy, float aspect, float zNear, float zFar)
575 	{
576 		auto __p = graphene_matrix_init_perspective(graphene_matrix, fovy, aspect, zNear, zFar);
577 
578 		if(__p is null)
579 		{
580 			return null;
581 		}
582 
583 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
584 	}
585 
586 	/**
587 	 * Initializes @m to represent a rotation of @angle degrees on
588 	 * the axis represented by the @axis vector.
589 	 *
590 	 * Params:
591 	 *     angle = the rotation angle, in degrees
592 	 *     axis = the axis vector as a #graphene_vec3_t
593 	 *
594 	 * Returns: the initialized matrix
595 	 *
596 	 * Since: 1.0
597 	 */
598 	public Matrix initRotate(float angle, Vec3 axis)
599 	{
600 		auto __p = graphene_matrix_init_rotate(graphene_matrix, angle, (axis is null) ? null : axis.getVec3Struct());
601 
602 		if(__p is null)
603 		{
604 			return null;
605 		}
606 
607 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
608 	}
609 
610 	/**
611 	 * Initializes a #graphene_matrix_t with the given scaling factors.
612 	 *
613 	 * Params:
614 	 *     x = the scale factor on the X axis
615 	 *     y = the scale factor on the Y axis
616 	 *     z = the scale factor on the Z axis
617 	 *
618 	 * Returns: the initialized matrix
619 	 *
620 	 * Since: 1.0
621 	 */
622 	public Matrix initScale(float x, float y, float z)
623 	{
624 		auto __p = graphene_matrix_init_scale(graphene_matrix, x, y, z);
625 
626 		if(__p is null)
627 		{
628 			return null;
629 		}
630 
631 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
632 	}
633 
634 	/**
635 	 * Initializes a #graphene_matrix_t with a skew transformation
636 	 * with the given factors.
637 	 *
638 	 * Params:
639 	 *     xSkew = skew factor, in radians, on the X axis
640 	 *     ySkew = skew factor, in radians, on the Y axis
641 	 *
642 	 * Returns: the initialized matrix
643 	 *
644 	 * Since: 1.0
645 	 */
646 	public Matrix initSkew(float xSkew, float ySkew)
647 	{
648 		auto __p = graphene_matrix_init_skew(graphene_matrix, xSkew, ySkew);
649 
650 		if(__p is null)
651 		{
652 			return null;
653 		}
654 
655 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
656 	}
657 
658 	/**
659 	 * Initializes a #graphene_matrix_t with a translation to the
660 	 * given coordinates.
661 	 *
662 	 * Params:
663 	 *     p = the translation coordinates
664 	 *
665 	 * Returns: the initialized matrix
666 	 *
667 	 * Since: 1.0
668 	 */
669 	public Matrix initTranslate(Point3D p)
670 	{
671 		auto __p = graphene_matrix_init_translate(graphene_matrix, (p is null) ? null : p.getPoint3DStruct());
672 
673 		if(__p is null)
674 		{
675 			return null;
676 		}
677 
678 		return ObjectG.getDObject!(Matrix)(cast(graphene_matrix_t*) __p);
679 	}
680 
681 	/**
682 	 * Linearly interpolates the two given #graphene_matrix_t by
683 	 * interpolating the decomposed transformations separately.
684 	 *
685 	 * If either matrix cannot be reduced to their transformations
686 	 * then the interpolation cannot be performed, and this function
687 	 * will return an identity matrix.
688 	 *
689 	 * Params:
690 	 *     b = a #graphene_matrix_t
691 	 *     factor = the linear interpolation factor
692 	 *     res = return location for the
693 	 *         interpolated matrix
694 	 *
695 	 * Since: 1.0
696 	 */
697 	public void interpolate(Matrix b, double factor, out Matrix res)
698 	{
699 		graphene_matrix_t* outres = sliceNew!graphene_matrix_t();
700 
701 		graphene_matrix_interpolate(graphene_matrix, (b is null) ? null : b.getMatrixStruct(), factor, outres);
702 
703 		res = ObjectG.getDObject!(Matrix)(outres, true);
704 	}
705 
706 	/**
707 	 * Inverts the given matrix.
708 	 *
709 	 * Params:
710 	 *     res = return location for the
711 	 *         inverse matrix
712 	 *
713 	 * Returns: `true` if the matrix is invertible
714 	 *
715 	 * Since: 1.0
716 	 */
717 	public bool inverse(out Matrix res)
718 	{
719 		graphene_matrix_t* outres = sliceNew!graphene_matrix_t();
720 
721 		auto __p = graphene_matrix_inverse(graphene_matrix, outres) != 0;
722 
723 		res = ObjectG.getDObject!(Matrix)(outres, true);
724 
725 		return __p;
726 	}
727 
728 	/**
729 	 * Checks whether the given #graphene_matrix_t is compatible with an
730 	 * a 2D affine transformation matrix.
731 	 *
732 	 * Returns: `true` if the matrix is compatible with an affine
733 	 *     transformation matrix
734 	 *
735 	 * Since: 1.0
736 	 */
737 	public bool is2d()
738 	{
739 		return graphene_matrix_is_2d(graphene_matrix) != 0;
740 	}
741 
742 	/**
743 	 * Checks whether a #graphene_matrix_t has a visible back face.
744 	 *
745 	 * Returns: `true` if the back face of the matrix is visible
746 	 *
747 	 * Since: 1.0
748 	 */
749 	public bool isBackfaceVisible()
750 	{
751 		return graphene_matrix_is_backface_visible(graphene_matrix) != 0;
752 	}
753 
754 	/**
755 	 * Checks whether the given #graphene_matrix_t is the identity matrix.
756 	 *
757 	 * Returns: `true` if the matrix is the identity matrix
758 	 *
759 	 * Since: 1.0
760 	 */
761 	public bool isIdentity()
762 	{
763 		return graphene_matrix_is_identity(graphene_matrix) != 0;
764 	}
765 
766 	/**
767 	 * Checks whether a matrix is singular.
768 	 *
769 	 * Returns: `true` if the matrix is singular
770 	 *
771 	 * Since: 1.0
772 	 */
773 	public bool isSingular()
774 	{
775 		return graphene_matrix_is_singular(graphene_matrix) != 0;
776 	}
777 
778 	/**
779 	 * Multiplies two #graphene_matrix_t.
780 	 *
781 	 * Matrix multiplication is not commutative in general; the order of the factors matters.
782 	 * The product of this multiplication is (@a × @b)
783 	 *
784 	 * Params:
785 	 *     b = a #graphene_matrix_t
786 	 *     res = return location for the matrix
787 	 *         result
788 	 *
789 	 * Since: 1.0
790 	 */
791 	public void multiply(Matrix b, out Matrix res)
792 	{
793 		graphene_matrix_t* outres = sliceNew!graphene_matrix_t();
794 
795 		graphene_matrix_multiply(graphene_matrix, (b is null) ? null : b.getMatrixStruct(), outres);
796 
797 		res = ObjectG.getDObject!(Matrix)(outres, true);
798 	}
799 
800 	/**
801 	 * Compares the two given #graphene_matrix_t matrices and checks
802 	 * whether their values are within the given @epsilon of each
803 	 * other.
804 	 *
805 	 * Params:
806 	 *     b = a #graphene_matrix_t
807 	 *     epsilon = the threshold between the two matrices
808 	 *
809 	 * Returns: `true` if the two matrices are near each other, and
810 	 *     `false` otherwise
811 	 *
812 	 * Since: 1.10
813 	 */
814 	public bool near(Matrix b, float epsilon)
815 	{
816 		return graphene_matrix_near(graphene_matrix, (b is null) ? null : b.getMatrixStruct(), epsilon) != 0;
817 	}
818 
819 	/**
820 	 * Normalizes the given #graphene_matrix_t.
821 	 *
822 	 * Params:
823 	 *     res = return location for the normalized matrix
824 	 *
825 	 * Since: 1.0
826 	 */
827 	public void normalize(out Matrix res)
828 	{
829 		graphene_matrix_t* outres = sliceNew!graphene_matrix_t();
830 
831 		graphene_matrix_normalize(graphene_matrix, outres);
832 
833 		res = ObjectG.getDObject!(Matrix)(outres, true);
834 	}
835 
836 	/**
837 	 * Applies a perspective of @depth to the matrix.
838 	 *
839 	 * Params:
840 	 *     depth = the depth of the perspective
841 	 *     res = return location for the
842 	 *         perspective matrix
843 	 *
844 	 * Since: 1.0
845 	 */
846 	public void perspective(float depth, out Matrix res)
847 	{
848 		graphene_matrix_t* outres = sliceNew!graphene_matrix_t();
849 
850 		graphene_matrix_perspective(graphene_matrix, depth, outres);
851 
852 		res = ObjectG.getDObject!(Matrix)(outres, true);
853 	}
854 
855 	/**
856 	 * Prints the contents of a matrix to the standard error stream.
857 	 *
858 	 * This function is only useful for debugging; there are no guarantees
859 	 * made on the format of the output.
860 	 *
861 	 * Since: 1.0
862 	 */
863 	public void print()
864 	{
865 		graphene_matrix_print(graphene_matrix);
866 	}
867 
868 	/**
869 	 * Projects a #graphene_point_t using the matrix @m.
870 	 *
871 	 * Params:
872 	 *     p = a #graphene_point_t
873 	 *     res = return location for the projected
874 	 *         point
875 	 *
876 	 * Since: 1.0
877 	 */
878 	public void projectPoint(Point p, out Point res)
879 	{
880 		graphene_point_t* outres = sliceNew!graphene_point_t();
881 
882 		graphene_matrix_project_point(graphene_matrix, (p is null) ? null : p.getPointStruct(), outres);
883 
884 		res = ObjectG.getDObject!(Point)(outres, true);
885 	}
886 
887 	/**
888 	 * Projects all corners of a #graphene_rect_t using the given matrix.
889 	 *
890 	 * See also: graphene_matrix_project_point()
891 	 *
892 	 * Params:
893 	 *     r = a #graphene_rect_t
894 	 *     res = return location for the projected
895 	 *         rectangle
896 	 *
897 	 * Since: 1.2
898 	 */
899 	public void projectRect(Rect r, out Quad res)
900 	{
901 		graphene_quad_t* outres = sliceNew!graphene_quad_t();
902 
903 		graphene_matrix_project_rect(graphene_matrix, (r is null) ? null : r.getRectStruct(), outres);
904 
905 		res = ObjectG.getDObject!(Quad)(outres, true);
906 	}
907 
908 	/**
909 	 * Projects a #graphene_rect_t using the given matrix.
910 	 *
911 	 * The resulting rectangle is the axis aligned bounding rectangle capable
912 	 * of fully containing the projected rectangle.
913 	 *
914 	 * Params:
915 	 *     r = a #graphene_rect_t
916 	 *     res = return location for the projected
917 	 *         rectangle
918 	 *
919 	 * Since: 1.0
920 	 */
921 	public void projectRectBounds(Rect r, out Rect res)
922 	{
923 		graphene_rect_t* outres = sliceNew!graphene_rect_t();
924 
925 		graphene_matrix_project_rect_bounds(graphene_matrix, (r is null) ? null : r.getRectStruct(), outres);
926 
927 		res = ObjectG.getDObject!(Rect)(outres, true);
928 	}
929 
930 	/**
931 	 * Adds a rotation transformation to @m, using the given @angle
932 	 * and @axis vector.
933 	 *
934 	 * This is the equivalent of calling graphene_matrix_init_rotate() and
935 	 * then multiplying the matrix @m with the rotation matrix.
936 	 *
937 	 * Params:
938 	 *     angle = the rotation angle, in degrees
939 	 *     axis = the rotation axis, as a #graphene_vec3_t
940 	 *
941 	 * Since: 1.0
942 	 */
943 	public void rotate(float angle, Vec3 axis)
944 	{
945 		graphene_matrix_rotate(graphene_matrix, angle, (axis is null) ? null : axis.getVec3Struct());
946 	}
947 
948 	/**
949 	 * Adds a rotation transformation to @m, using the given
950 	 * #graphene_euler_t.
951 	 *
952 	 * Params:
953 	 *     e = a rotation described by a #graphene_euler_t
954 	 *
955 	 * Since: 1.2
956 	 */
957 	public void rotateEuler(Euler e)
958 	{
959 		graphene_matrix_rotate_euler(graphene_matrix, (e is null) ? null : e.getEulerStruct());
960 	}
961 
962 	/**
963 	 * Adds a rotation transformation to @m, using the given
964 	 * #graphene_quaternion_t.
965 	 *
966 	 * This is the equivalent of calling graphene_quaternion_to_matrix() and
967 	 * then multiplying @m with the rotation matrix.
968 	 *
969 	 * Params:
970 	 *     q = a rotation described by a #graphene_quaternion_t
971 	 *
972 	 * Since: 1.2
973 	 */
974 	public void rotateQuaternion(Quaternion q)
975 	{
976 		graphene_matrix_rotate_quaternion(graphene_matrix, (q is null) ? null : q.getQuaternionStruct());
977 	}
978 
979 	/**
980 	 * Adds a rotation transformation around the X axis to @m, using
981 	 * the given @angle.
982 	 *
983 	 * See also: graphene_matrix_rotate()
984 	 *
985 	 * Params:
986 	 *     angle = the rotation angle, in degrees
987 	 *
988 	 * Since: 1.0
989 	 */
990 	public void rotateX(float angle)
991 	{
992 		graphene_matrix_rotate_x(graphene_matrix, angle);
993 	}
994 
995 	/**
996 	 * Adds a rotation transformation around the Y axis to @m, using
997 	 * the given @angle.
998 	 *
999 	 * See also: graphene_matrix_rotate()
1000 	 *
1001 	 * Params:
1002 	 *     angle = the rotation angle, in degrees
1003 	 *
1004 	 * Since: 1.0
1005 	 */
1006 	public void rotateY(float angle)
1007 	{
1008 		graphene_matrix_rotate_y(graphene_matrix, angle);
1009 	}
1010 
1011 	/**
1012 	 * Adds a rotation transformation around the Z axis to @m, using
1013 	 * the given @angle.
1014 	 *
1015 	 * See also: graphene_matrix_rotate()
1016 	 *
1017 	 * Params:
1018 	 *     angle = the rotation angle, in degrees
1019 	 *
1020 	 * Since: 1.0
1021 	 */
1022 	public void rotateZ(float angle)
1023 	{
1024 		graphene_matrix_rotate_z(graphene_matrix, angle);
1025 	}
1026 
1027 	/**
1028 	 * Adds a scaling transformation to @m, using the three
1029 	 * given factors.
1030 	 *
1031 	 * This is the equivalent of calling graphene_matrix_init_scale() and then
1032 	 * multiplying the matrix @m with the scale matrix.
1033 	 *
1034 	 * Params:
1035 	 *     factorX = scaling factor on the X axis
1036 	 *     factorY = scaling factor on the Y axis
1037 	 *     factorZ = scaling factor on the Z axis
1038 	 *
1039 	 * Since: 1.0
1040 	 */
1041 	public void scale(float factorX, float factorY, float factorZ)
1042 	{
1043 		graphene_matrix_scale(graphene_matrix, factorX, factorY, factorZ);
1044 	}
1045 
1046 	/**
1047 	 * Adds a skew of @factor on the X and Y axis to the given matrix.
1048 	 *
1049 	 * Params:
1050 	 *     factor = skew factor
1051 	 *
1052 	 * Since: 1.0
1053 	 */
1054 	public void skewXy(float factor)
1055 	{
1056 		graphene_matrix_skew_xy(graphene_matrix, factor);
1057 	}
1058 
1059 	/**
1060 	 * Adds a skew of @factor on the X and Z axis to the given matrix.
1061 	 *
1062 	 * Params:
1063 	 *     factor = skew factor
1064 	 *
1065 	 * Since: 1.0
1066 	 */
1067 	public void skewXz(float factor)
1068 	{
1069 		graphene_matrix_skew_xz(graphene_matrix, factor);
1070 	}
1071 
1072 	/**
1073 	 * Adds a skew of @factor on the Y and Z axis to the given matrix.
1074 	 *
1075 	 * Params:
1076 	 *     factor = skew factor
1077 	 *
1078 	 * Since: 1.0
1079 	 */
1080 	public void skewYz(float factor)
1081 	{
1082 		graphene_matrix_skew_yz(graphene_matrix, factor);
1083 	}
1084 
1085 	/**
1086 	 * Converts a #graphene_matrix_t to an affine transformation
1087 	 * matrix, if the given matrix is compatible.
1088 	 *
1089 	 * The returned values have the following layout:
1090 	 *
1091 	 * |[<!-- language="plain" -->
1092 	 * ⎛ xx  yx ⎞   ⎛  a   b  0 ⎞
1093 	 * ⎜ xy  yy ⎟ = ⎜  c   d  0 ⎟
1094 	 * ⎝ x0  y0 ⎠   ⎝ tx  ty  1 ⎠
1095 	 * ]|
1096 	 *
1097 	 * This function can be used to convert between a #graphene_matrix_t
1098 	 * and an affine matrix type from other libraries.
1099 	 *
1100 	 * Params:
1101 	 *     xx = return location for the xx member
1102 	 *     yx = return location for the yx member
1103 	 *     xy = return location for the xy member
1104 	 *     yy = return location for the yy member
1105 	 *     x0 = return location for the x0 member
1106 	 *     y0 = return location for the y0 member
1107 	 *
1108 	 * Returns: `true` if the matrix is compatible with an affine
1109 	 *     transformation matrix
1110 	 *
1111 	 * Since: 1.0
1112 	 */
1113 	public bool to2d(out double xx, out double yx, out double xy, out double yy, out double x0, out double y0)
1114 	{
1115 		return graphene_matrix_to_2d(graphene_matrix, &xx, &yx, &xy, &yy, &x0, &y0) != 0;
1116 	}
1117 
1118 	/**
1119 	 * Converts a #graphene_matrix_t to an array of floating point
1120 	 * values.
1121 	 *
1122 	 * Params:
1123 	 *     v = return location
1124 	 *         for an array of floating point values. The array must be capable
1125 	 *         of holding at least 16 values.
1126 	 *
1127 	 * Since: 1.0
1128 	 */
1129 	public void toFloat(out float[16] v)
1130 	{
1131 		float[16] outv;
1132 
1133 		graphene_matrix_to_float(graphene_matrix, outv.ptr);
1134 
1135 		v = outv[0 .. 16];
1136 	}
1137 
1138 	/**
1139 	 * Transforms each corner of a #graphene_rect_t using the given matrix @m.
1140 	 *
1141 	 * The result is the axis aligned bounding rectangle containing the coplanar
1142 	 * quadrilateral.
1143 	 *
1144 	 * See also: graphene_matrix_transform_point()
1145 	 *
1146 	 * Params:
1147 	 *     r = a #graphene_rect_t
1148 	 *     res = return location for the bounds
1149 	 *         of the transformed rectangle
1150 	 *
1151 	 * Since: 1.0
1152 	 */
1153 	public void transformBounds(Rect r, out Rect res)
1154 	{
1155 		graphene_rect_t* outres = sliceNew!graphene_rect_t();
1156 
1157 		graphene_matrix_transform_bounds(graphene_matrix, (r is null) ? null : r.getRectStruct(), outres);
1158 
1159 		res = ObjectG.getDObject!(Rect)(outres, true);
1160 	}
1161 
1162 	/**
1163 	 * Transforms the vertices of a #graphene_box_t using the given matrix @m.
1164 	 *
1165 	 * The result is the axis aligned bounding box containing the transformed
1166 	 * vertices.
1167 	 *
1168 	 * Params:
1169 	 *     b = a #graphene_box_t
1170 	 *     res = return location for the bounds
1171 	 *         of the transformed box
1172 	 *
1173 	 * Since: 1.2
1174 	 */
1175 	public void transformBox(Box b, out Box res)
1176 	{
1177 		graphene_box_t* outres = sliceNew!graphene_box_t();
1178 
1179 		graphene_matrix_transform_box(graphene_matrix, (b is null) ? null : b.getBoxStruct(), outres);
1180 
1181 		res = ObjectG.getDObject!(Box)(outres, true);
1182 	}
1183 
1184 	/**
1185 	 * Transforms the given #graphene_point_t using the matrix @m.
1186 	 *
1187 	 * Unlike graphene_matrix_transform_vec3(), this function will take into
1188 	 * account the fourth row vector of the #graphene_matrix_t when computing
1189 	 * the dot product of each row vector of the matrix.
1190 	 *
1191 	 * See also: graphene_simd4x4f_point3_mul()
1192 	 *
1193 	 * Params:
1194 	 *     p = a #graphene_point_t
1195 	 *     res = return location for the
1196 	 *         transformed #graphene_point_t
1197 	 *
1198 	 * Since: 1.0
1199 	 */
1200 	public void transformPoint(Point p, out Point res)
1201 	{
1202 		graphene_point_t* outres = sliceNew!graphene_point_t();
1203 
1204 		graphene_matrix_transform_point(graphene_matrix, (p is null) ? null : p.getPointStruct(), outres);
1205 
1206 		res = ObjectG.getDObject!(Point)(outres, true);
1207 	}
1208 
1209 	/**
1210 	 * Transforms the given #graphene_point3d_t using the matrix @m.
1211 	 *
1212 	 * Unlike graphene_matrix_transform_vec3(), this function will take into
1213 	 * account the fourth row vector of the #graphene_matrix_t when computing
1214 	 * the dot product of each row vector of the matrix.
1215 	 *
1216 	 * See also: graphene_simd4x4f_point3_mul()
1217 	 *
1218 	 * Params:
1219 	 *     p = a #graphene_point3d_t
1220 	 *     res = return location for the result
1221 	 *
1222 	 * Since: 1.2
1223 	 */
1224 	public void transformPoint3d(Point3D p, out Point3D res)
1225 	{
1226 		graphene_point3d_t* outres = sliceNew!graphene_point3d_t();
1227 
1228 		graphene_matrix_transform_point3d(graphene_matrix, (p is null) ? null : p.getPoint3DStruct(), outres);
1229 
1230 		res = ObjectG.getDObject!(Point3D)(outres, true);
1231 	}
1232 
1233 	/**
1234 	 * Transform a #graphene_ray_t using the given matrix @m.
1235 	 *
1236 	 * Params:
1237 	 *     r = a #graphene_ray_t
1238 	 *     res = return location for the
1239 	 *         transformed ray
1240 	 *
1241 	 * Since: 1.4
1242 	 */
1243 	public void transformRay(Ray r, out Ray res)
1244 	{
1245 		graphene_ray_t* outres = sliceNew!graphene_ray_t();
1246 
1247 		graphene_matrix_transform_ray(graphene_matrix, (r is null) ? null : r.getRayStruct(), outres);
1248 
1249 		res = ObjectG.getDObject!(Ray)(outres, true);
1250 	}
1251 
1252 	/**
1253 	 * Transforms each corner of a #graphene_rect_t using the given matrix @m.
1254 	 *
1255 	 * The result is a coplanar quadrilateral.
1256 	 *
1257 	 * See also: graphene_matrix_transform_point()
1258 	 *
1259 	 * Params:
1260 	 *     r = a #graphene_rect_t
1261 	 *     res = return location for the
1262 	 *         transformed quad
1263 	 *
1264 	 * Since: 1.0
1265 	 */
1266 	public void transformRect(Rect r, out Quad res)
1267 	{
1268 		graphene_quad_t* outres = sliceNew!graphene_quad_t();
1269 
1270 		graphene_matrix_transform_rect(graphene_matrix, (r is null) ? null : r.getRectStruct(), outres);
1271 
1272 		res = ObjectG.getDObject!(Quad)(outres, true);
1273 	}
1274 
1275 	/**
1276 	 * Transforms a #graphene_sphere_t using the given matrix @m. The
1277 	 * result is the bounding sphere containing the transformed sphere.
1278 	 *
1279 	 * Params:
1280 	 *     s = a #graphene_sphere_t
1281 	 *     res = return location for the bounds
1282 	 *         of the transformed sphere
1283 	 *
1284 	 * Since: 1.2
1285 	 */
1286 	public void transformSphere(Sphere s, out Sphere res)
1287 	{
1288 		graphene_sphere_t* outres = sliceNew!graphene_sphere_t();
1289 
1290 		graphene_matrix_transform_sphere(graphene_matrix, (s is null) ? null : s.getSphereStruct(), outres);
1291 
1292 		res = ObjectG.getDObject!(Sphere)(outres, true);
1293 	}
1294 
1295 	/**
1296 	 * Transforms the given #graphene_vec3_t using the matrix @m.
1297 	 *
1298 	 * This function will multiply the X, Y, and Z row vectors of the matrix @m
1299 	 * with the corresponding components of the vector @v. The W row vector will
1300 	 * be ignored.
1301 	 *
1302 	 * See also: graphene_simd4x4f_vec3_mul()
1303 	 *
1304 	 * Params:
1305 	 *     v = a #graphene_vec3_t
1306 	 *     res = return location for a #graphene_vec3_t
1307 	 *
1308 	 * Since: 1.0
1309 	 */
1310 	public void transformVec3(Vec3 v, out Vec3 res)
1311 	{
1312 		graphene_vec3_t* outres = sliceNew!graphene_vec3_t();
1313 
1314 		graphene_matrix_transform_vec3(graphene_matrix, (v is null) ? null : v.getVec3Struct(), outres);
1315 
1316 		res = ObjectG.getDObject!(Vec3)(outres, true);
1317 	}
1318 
1319 	/**
1320 	 * Transforms the given #graphene_vec4_t using the matrix @m.
1321 	 *
1322 	 * See also: graphene_simd4x4f_vec4_mul()
1323 	 *
1324 	 * Params:
1325 	 *     v = a #graphene_vec4_t
1326 	 *     res = return location for a #graphene_vec4_t
1327 	 *
1328 	 * Since: 1.0
1329 	 */
1330 	public void transformVec4(Vec4 v, out Vec4 res)
1331 	{
1332 		graphene_vec4_t* outres = sliceNew!graphene_vec4_t();
1333 
1334 		graphene_matrix_transform_vec4(graphene_matrix, (v is null) ? null : v.getVec4Struct(), outres);
1335 
1336 		res = ObjectG.getDObject!(Vec4)(outres, true);
1337 	}
1338 
1339 	/**
1340 	 * Adds a translation transformation to @m using the coordinates
1341 	 * of the given #graphene_point3d_t.
1342 	 *
1343 	 * This is the equivalent of calling graphene_matrix_init_translate() and
1344 	 * then multiplying @m with the translation matrix.
1345 	 *
1346 	 * Params:
1347 	 *     pos = a #graphene_point3d_t
1348 	 *
1349 	 * Since: 1.0
1350 	 */
1351 	public void translate(Point3D pos)
1352 	{
1353 		graphene_matrix_translate(graphene_matrix, (pos is null) ? null : pos.getPoint3DStruct());
1354 	}
1355 
1356 	/**
1357 	 * Transposes the given matrix.
1358 	 *
1359 	 * Params:
1360 	 *     res = return location for the
1361 	 *         transposed matrix
1362 	 *
1363 	 * Since: 1.0
1364 	 */
1365 	public void transpose(out Matrix res)
1366 	{
1367 		graphene_matrix_t* outres = sliceNew!graphene_matrix_t();
1368 
1369 		graphene_matrix_transpose(graphene_matrix, outres);
1370 
1371 		res = ObjectG.getDObject!(Matrix)(outres, true);
1372 	}
1373 
1374 	/**
1375 	 * Unprojects the given @point using the @projection matrix and
1376 	 * a @modelview matrix.
1377 	 *
1378 	 * Params:
1379 	 *     modelview = a #graphene_matrix_t for the modelview matrix; this is
1380 	 *         the inverse of the modelview used when projecting the point
1381 	 *     point = a #graphene_point3d_t with the coordinates of the point
1382 	 *     res = return location for the unprojected
1383 	 *         point
1384 	 *
1385 	 * Since: 1.2
1386 	 */
1387 	public void unprojectPoint3d(Matrix modelview, Point3D point, out Point3D res)
1388 	{
1389 		graphene_point3d_t* outres = sliceNew!graphene_point3d_t();
1390 
1391 		graphene_matrix_unproject_point3d(graphene_matrix, (modelview is null) ? null : modelview.getMatrixStruct(), (point is null) ? null : point.getPoint3DStruct(), outres);
1392 
1393 		res = ObjectG.getDObject!(Point3D)(outres, true);
1394 	}
1395 
1396 	/**
1397 	 * Undoes the transformation on the corners of a #graphene_rect_t using the
1398 	 * given matrix, within the given axis aligned rectangular @bounds.
1399 	 *
1400 	 * Params:
1401 	 *     r = a #graphene_rect_t
1402 	 *     bounds = the bounds of the transformation
1403 	 *     res = return location for the
1404 	 *         untransformed rectangle
1405 	 *
1406 	 * Since: 1.0
1407 	 */
1408 	public void untransformBounds(Rect r, Rect bounds, out Rect res)
1409 	{
1410 		graphene_rect_t* outres = sliceNew!graphene_rect_t();
1411 
1412 		graphene_matrix_untransform_bounds(graphene_matrix, (r is null) ? null : r.getRectStruct(), (bounds is null) ? null : bounds.getRectStruct(), outres);
1413 
1414 		res = ObjectG.getDObject!(Rect)(outres, true);
1415 	}
1416 
1417 	/**
1418 	 * Undoes the transformation of a #graphene_point_t using the
1419 	 * given matrix, within the given axis aligned rectangular @bounds.
1420 	 *
1421 	 * Params:
1422 	 *     p = a #graphene_point_t
1423 	 *     bounds = the bounds of the transformation
1424 	 *     res = return location for the
1425 	 *         untransformed point
1426 	 *
1427 	 * Returns: `true` if the point was successfully untransformed
1428 	 *
1429 	 * Since: 1.0
1430 	 */
1431 	public bool untransformPoint(Point p, Rect bounds, out Point res)
1432 	{
1433 		graphene_point_t* outres = sliceNew!graphene_point_t();
1434 
1435 		auto __p = graphene_matrix_untransform_point(graphene_matrix, (p is null) ? null : p.getPointStruct(), (bounds is null) ? null : bounds.getRectStruct(), outres) != 0;
1436 
1437 		res = ObjectG.getDObject!(Point)(outres, true);
1438 
1439 		return __p;
1440 	}
1441 }