com.codename1.ui.Transform Maven / Gradle / Ivy
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codename1.ui;
import com.codename1.impl.CodenameOneImplementation;
import com.codename1.io.Log;
import java.util.Arrays;
/**
* Encapsulates a 3D transform that can be used in {@link com.codename1.ui.Graphics} contexts
* or with {@link com.codename1.ui.geom.Shape}s to transform in various ways.
*
* Use the {@link #isSupported} and {@link #isPerspectiveSupported} to check if transforms and
* perspective transforms are supported on this platform. If they are not supported, this
* class will throw RuntimeExceptions if you try to use it.
* @author shannah
*/
public class Transform {
public static class NotInvertibleException extends Exception {
}
/**
* Reference to the native transform. This should only be used by the implementation.
*/
private Object nativeTransform;
/**
* The type of transform. This allows us to cut corners in transformation
* when using a special matrix like a translation, scale, or identity matrix.
*/
private int type = TYPE_UNKNOWN;
private Transform inverse;
private boolean inverseDirty=true;
private float translateX=0, translateY=0, translateZ=0;
private float scaleX=1f, scaleY=1f, scaleZ=1f;
private boolean dirty = true;
private CodenameOneImplementation impl = null;
private static class ImmutableTransform extends Transform {
public ImmutableTransform(Object nativeTransform) {
super(nativeTransform);
}
private void unsupported(){
throw new RuntimeException("Cannot change immutable transform");
}
@Override
public void setCamera(float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) {
unsupported();
}
@Override
public void setIdentity() {
unsupported();
}
@Override
public void setOrtho(float left, float right, float bottom, float top, float near, float far) {
unsupported();
}
@Override
public void setPerspective(float fovy, float aspect, float zNear, float zFar) {
unsupported();
}
@Override
public void setRotation(float angle, float px, float py) {
unsupported();
}
@Override
public void setTransform(Transform t) {
unsupported();
}
@Override
public void setRotation(float angle, float x, float y, float z) {
unsupported();
}
@Override
public void setTranslation(float x, float y) {
unsupported();
}
@Override
public void setTranslation(float x, float y, float z) {
unsupported();
}
@Override
public void rotate(float angle, float px, float py) {
unsupported();
}
@Override
public void rotate(float angle, float x, float y, float z) {
unsupported();
}
@Override
public void translate(float x, float y) {
unsupported();
}
@Override
public void translate(float x, float y, float z) {
unsupported();
}
@Override
public void scale(float x, float y) {
unsupported();
}
@Override
public void scale(float x, float y, float z) {
unsupported();
}
}
/**
* Constant for transform type. Transform is not a special matrix.
*/
public static final int TYPE_UNKNOWN=-1;
/**
* Constant for transform type. Transform is the identity transform.
*/
public static final int TYPE_IDENTITY=0;
/**
* Constant for transform type. Transform is a translation transform
* only.
*/
public static final int TYPE_TRANSLATION=1;
/**
* Constant for transform type. Transform is a scale transform only.
*/
public static final int TYPE_SCALE=2;
private static Transform _IDENTITY;
public static Transform IDENTITY(){
if ( _IDENTITY == null ){
_IDENTITY = new ImmutableTransform(Display.impl.makeTransformIdentity());
_IDENTITY.type = TYPE_IDENTITY;
}
return _IDENTITY;
}
/**
* Private constructor
* @param nativeTransform
*/
private Transform(Object nativeTransform){
this.nativeTransform = nativeTransform;
impl();
}
private CodenameOneImplementation impl(){
if ( impl == null ){
impl = Display.impl;
}
return impl;
}
/**
* Initializes the native transform with appropriate values. For efficiency,
* some special kinds of transforms don't keep the native transform in sync
* (or even created at all). Before accessing, the native transform from the
* implementation, the native transform needs to be initialized. This method
* is called internally in the appropriate places to ensure that the native
* transform is kept in sync when it is needed.
*/
private void initNativeTransform(){
if ( nativeTransform == null ){
nativeTransform = impl.makeTransformIdentity();
if ( type == TYPE_TRANSLATION ){
impl.setTransformTranslation(nativeTransform, translateX, translateY, translateZ);
} else if ( type == TYPE_SCALE ){
impl.setTransformScale(nativeTransform, scaleX, scaleY, scaleZ);
}
} else {
switch (type){
case TYPE_TRANSLATION:
impl.setTransformTranslation(nativeTransform, translateX, translateY, translateZ);
break;
case TYPE_SCALE:
impl.setTransformScale(nativeTransform, scaleX, scaleY, scaleZ);
break;
case TYPE_IDENTITY:
impl.setTransformIdentity(nativeTransform);
break;
}
}
dirty = false;
}
/**
* Makes a new identity transform.
* @return An identity transform.
*/
public static Transform makeIdentity(){
Transform out = new Transform(null);
out.type = TYPE_IDENTITY;
return out;
}
/**
* Checks if this transform is the identity transform.
* @return True if the transform is the identity.
*/
public boolean isIdentity(){
if (type == TYPE_IDENTITY) return true;
if ( this.equals(IDENTITY())){
setIdentity();
return true;
}
return false;
}
/**
* Checks if this transform is a translation transform.
* @return True if this transform performs translation only. Note that this
* will return false if the transform is the identity (i.e. is actually
* a translation of (0,0,0).
*/
public boolean isTranslation(){
return (type == TYPE_TRANSLATION);
}
/**
* Gets the x scale factor of this transformation. This value is only reliable
* if the transform is a scale transform.
* @return The x scale factor of this transformation.
* @see #isScale()
* @see #setScale()
*/
public float getScaleX(){
return scaleX;
}
/**
* Gets the y scale factor of this transformation. This value is only reliable
* if the transform is a scale transform.
* @return The y scale factor of this transformation.
* @see #isScale()
* @see #setScale()
* @return
*/
public float getScaleY(){
return scaleY;
}
/**
* Gets the z scale factor of this transformation. This value is only reliable
* if the transform is a scale transform.
* @return The z scale factor of this transformation.
* @see #isScale()
* @see #setScale()
* @return
*/
public float getScaleZ(){
return scaleZ;
}
/**
* Gets the x translation of this transformation. This value is only reliable
* if the transform is a translation transform.
* @return The x translation of this transform.
* @see #isTranslation()
* @see #setTranslation()
* @see #translate()
*/
public float getTranslateX(){
return translateX;
}
/**
* Gets the y translation of this transformation. This value is only reliable
* if the transform is a translation transform.
* @return The y translation of this transform.
* @see #isTranslation()
* @see #setTranslation()
* @see #translate()
*/
public float getTranslateY(){
return translateY;
}
/**
* Gets the z translation of this transformation. This value is only reliable
* if the transform is a translation transform.
* @return The z translation of this transform.
* @see #isTranslation()
* @see #setTranslation()
* @see #translate()
*/
public float getTranslateZ(){
return translateZ;
}
/**
* Checks if this transform is a scale transformation .
* @return Returns true if and only if this is a non-identity scale transformation.
*/
public boolean isScale(){
return (type == TYPE_SCALE);
}
/**
* Makes a new rotation transformation.
* Note: If {@link #isSupported()} is false, then this will throw a Runtime Exception.
* @param angle The angle of the rotation in radians.
* @param x The x component of the vector around which the rotation occurs.
* @param y The y component of the vector around which the rotation occurs.
* @param z The z component of the vector around which the rotation occurs.
* @return A transform that makes the appropriate rotation.
* @throws RuntimeException If {@link #isSupported()} is false.
*/
public static Transform makeRotation(float angle, float x, float y, float z){
Object t = Display.impl.makeTransformRotation(angle, x, y, z);
Transform out = new Transform(t);
return out;
}
public static Transform makeRotation(float angle, float x, float y){
Transform t = makeTranslation(x, y, 0);
t.rotate(angle, 0, 0, 1);
t.translate(-x, -y, 0);
return t;
}
/**
* Makes a new translation transformation.
* @param x The x component of the translation.
* @param y The y component of the translation.
* @param z The z component of the translation.
* @return A transform that makes the specified translation.
*/
public static Transform makeTranslation(float x, float y, float z){
Transform out = new Transform(null);
out.translateX = x;
out.translateY = y;
out.translateZ = z;
out.type = TYPE_TRANSLATION;
return out;
}
public static Transform makeTranslation(float x, float y){
return makeTranslation(x, y, 0);
}
/**
* Makes a new scale transformation.
* @param x The x scale factor.
* @param y The y scale factor.
* @param z The z scale factor.
* @return A transform that scales values according to the provided scale factors.
*/
public static Transform makeScale(float x, float y, float z){
if (x==1 && y == 1 && z == 1) {
return makeIdentity();
}
Transform out = new Transform(null);
out.scaleX = x;
out.scaleY = y;
out.scaleZ = z;
out.type = TYPE_SCALE;
return out;
}
/**
* Creates a new scale transform.
* @param x Factor to scale in x axis.
* @param y Factor to scale by in y axis.
* @return A new transform with the specified scale.
*/
public static Transform makeScale(float x, float y){
return makeScale(x, y, 1);
}
public static Transform makeAffine(double m00,
double m10,
double m01,
double m11,
double m02,
double m12) {
return new Transform(Display.impl.makeTransformAffine(m00, m10, m01, m11, m02, m12));
}
/**
* Resets the transformation to a scale transformation.
* @param x x-axis scaling
* @param y y-axis scaling
* @param z z-axis scaling
*/
public void setScale(float x, float y, float z) {
if (x==1 && y == 1 && z == 1) {
setIdentity();
return;
}
Transform out = this;
out.scaleX = x;
out.scaleY = y;
out.scaleZ = z;
out.type = TYPE_SCALE;
}
/**
* Resets the transformation to scale transform.
* @param x x-axis scaling.
* @param y y-axis scaling.
*/
public void setScale(float x, float y) {
setScale(x, y, 1);
}
/**
* Makes a new perspective transform.
* Note: If {@link #isPerspectiveSupported()} is false, then this will throw a Runtime Exception.
* @param fovy The y field of view angle.
* @param aspect The aspect ratio.
* @param zNear The nearest visible z coordinate.
* @param zFar The farthest z coordinate.
* @return A transform for the given perspective.
*/
public static Transform makePerspective(float fovy, float aspect, float zNear, float zFar) {
Object t = Display.impl.makeTransformPerspective(fovy, aspect, zNear, zFar);
Transform out = new Transform(t);
return out;
}
/**
* Makes a new orthographic projection transform.
* Note: If {@link #isPerspectiveSupported()} is false, then this will throw a Runtime Exception.
* @param left x-coordinate that is the left edge of the view.
* @param right The x-coordinate that is the right edge of the view.
* @param bottom The y-coordinate that is the bottom edge of the view.
* @param top The y-coordinate that is the top edge of the view.
* @param near The nearest visible z-coordinate.
* @param far The farthest visible z-coordinate.
* @return A transform with the provided orthographic projection.
*/
public static Transform makeOrtho(float left, float right, float bottom, float top,
float near, float far){
Object t = Display.impl.makeTransformOrtho(left, right, bottom, top, near, far);
Transform out = new Transform(t);
return out;
}
/**
* Makes a transform to simulate a camera's perspective at a given location.
* Note: If {@link #isPerspectiveSupported()} is false, then this will throw a Runtime Exception.
* @param eyeX The x-coordinate of the camera's eye.
* @param eyeY The y-coordinate of the camera's eye.
* @param eyeZ The z-coordinate of the camera's eye.
* @param centerX The center x coordinate of the view.
* @param centerY The center y coordinate of the view.
* @param centerZ The center z coordinate of the view.
* @param upX The x-coordinate of the up vector for the camera.
* @param upY The y-coordinate of the up vector for the camera.
* @param upZ The z-coordinate of the up vector for the camera.
* @return A transform with the provided camera's view perspective.
*/
public static Transform makeCamera(float eyeX, float eyeY, float eyeZ,
float centerX, float centerY, float centerZ, float upX, float upY,
float upZ){
Object t = Display.impl.makeTransformCamera(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
Transform out = new Transform(t);
return out;
}
/**
* Rotates the current transform.
* Note: If {@link #isSupported()} is false, then this will throw a Runtime Exception.
* @param angle The angle to rotate in radians.
* @param x The x-coordinate of the vector around which to rotate.
* @param y The y-coordinate of the vector around which to rotate.
* @param z The z-coordinate of the vector around which to rotate.
* @see #setRotation
*/
public void rotate(float angle, float x, float y, float z){
initNativeTransform();
Display.impl.transformRotate(nativeTransform, angle, x, y, z);
type = TYPE_UNKNOWN;
}
public void rotate(float angle, float px, float py){
translate(px, py, 0);
rotate(angle, 0, 0, 1);
translate(-px, -py, 0);
}
/**
* Sets the transform to be the provided rotation. This replaces the current transform
* whereas {@link #rotate()} further rotates the current transform.
* Note: If {@link #isSupported()} is false, then this will throw a Runtime Exception.
* @param angle The angle to rotate in radians.
* @param x The x-coordinate of the vector around which to rotate.
* @param y The y-coordinate of the vector around which to rotate.
* @param z The z-coordinate of the vector around which to rotate.
* @see #rotate()
*/
public void setRotation(float angle, float x, float y, float z){
initNativeTransform();
setTransform(makeRotation(angle, x, y, z));
type = TYPE_UNKNOWN;
}
public void setRotation(float angle, float px, float py){
initNativeTransform();
setTransform(makeRotation(angle, px, py));
type = TYPE_UNKNOWN;
}
/**
* Sets the transform to the identity transform.
*/
public void setIdentity(){
type = TYPE_IDENTITY;
scaleX = 1f; scaleY = 1f; scaleZ = 1f;
translateX = 0f; translateY = 0f; translateZ = 0f;
dirty = true;
inverseDirty=true;
}
public String toString(){
getNativeTransform();
return ""+nativeTransform;
}
/**
* Translates the transform by the specified amounts. This adds additional
* translations to whereas {@link #setTranslation()} replaces the transform
* with the specified translation.
* Note: If {@link #isSupported()} is false, then this may throw a Runtime Exception.
* @param x The x translation.
* @param y The y translation.
* @param z The z translation.
* @see #setTranslation()
*/
public void translate(float x, float y, float z){
if ( type == TYPE_IDENTITY ){
type = TYPE_TRANSLATION;
}
inverseDirty=true;
if ( type == TYPE_TRANSLATION){
translateX += x;
translateY += y;
translateZ += z;
if ( translateX == 0 && translateY == 0 && translateZ == 0 ){
type = TYPE_IDENTITY;
}
dirty = true;
} else {
initNativeTransform();
type = TYPE_UNKNOWN;
impl.transformTranslate(nativeTransform, x, y, z);
}
}
public void translate(float x, float y){
translate(x, y, 0);
}
/**
* Sets the current transform to be the specified translation. This replaces the current
* transform with the given translation whereas {@link #translate()} adds additional translation
* to the existing translation.
*
* @param x The x translation.
* @param y The y translation.
* @param z The z translation.
* @see #translate()
*/
public void setTranslation(float x, float y, float z){
type = TYPE_TRANSLATION;
inverseDirty=true;
if ( type == TYPE_TRANSLATION){
translateX = x;
translateY = y;
translateZ = z;
if ( translateX == 0 && translateY == 0 && translateZ == 0 ){
type = TYPE_IDENTITY;
}
dirty = true;
}
}
public void setTranslation(float x, float y){
setTranslation(x, y, 0);
}
/**
* Scales the current transform by the provide scale factors. Not to be confused with
* {@link #setScale()} which replaces the transform.
* Note: If {@link #isSupported()} is false, then this may throw a Runtime Exception.
* @param x The x-scale factor
* @param y The y-scale factor
* @param z The z-scale factor
* @see #setScale()
*/
public void scale(float x, float y, float z){
if ( type == TYPE_IDENTITY ){
type = TYPE_SCALE;
}
inverseDirty=true;
if ( type == TYPE_SCALE ){
scaleX *= x;
scaleY *= y;
scaleZ *= z;
if ( scaleZ == 1f && scaleY == 1f && scaleZ == 1f ){
type = TYPE_IDENTITY;
}
dirty = true;
} else {
initNativeTransform();
type = TYPE_UNKNOWN;
impl.transformScale(nativeTransform, x, y, z);
}
}
public void scale(float x, float y){
scale(x, y, 1);
}
/**
* Gets the inverse transformation for this transform.
* Note: If {@link #isSupported()} is false, then this will throw a Runtime Exception.
* @return The inverse transform.
* @deprecated Use {@link #getInverse(com.codename1.ui.Transform) } instead.
*/
public Transform getInverse(){
return makeInverse();
}
private Transform makeInverse() {
if ( type == TYPE_IDENTITY ){
return makeIdentity();
} else if ( type == TYPE_TRANSLATION ){
return makeTranslation(-translateX, -translateY, -translateZ);
} else if ( type == TYPE_SCALE ){
return makeScale(1f/scaleX, 1f/scaleY, 1f/scaleZ);
} else {
initNativeTransform();
Object t = impl.makeTransformInverse(nativeTransform);
Transform out = new Transform(t);
return out;
}
}
public void getInverse(Transform inverseOut) throws NotInvertibleException {
if (inverse == null) {
inverse = makeInverse();
inverseDirty = false;
} else if (inverseDirty) {
inverse.setTransform(this);
inverse.invert();
inverseDirty = false;
}
inverseOut.setTransform(inverse);
}
public void invert() throws NotInvertibleException {
if ( type == TYPE_IDENTITY ){
// Do nothing
} else if ( type == TYPE_TRANSLATION ){
setTranslation(-translateX, -translateY, -translateZ);
} else if ( type == TYPE_SCALE ){
setScale(1f/scaleX, 1f/scaleY, 1f/scaleZ);
} else {
initNativeTransform();
impl.setTransformInverse(nativeTransform);
}
}
/**
* Sets the current transform to be identical to the provided transform.
* Note: If {@link #isSupported()} is false, then this will may throw a Runtime Exception.
* @param t A transform to copy into the current transform.
*/
public void setTransform(Transform t){
type = t.type;
scaleX = t.scaleX;
scaleY = t.scaleY;
scaleZ = t.scaleZ;
translateX = t.translateX;
translateY = t.translateY;
translateZ = t.translateZ;
inverseDirty = true;
switch (type){
case TYPE_IDENTITY:
case TYPE_TRANSLATION:
case TYPE_SCALE:
// do nothing here
dirty = true;
break;
default:
initNativeTransform();
t.initNativeTransform();
impl.copyTransform(t.nativeTransform, nativeTransform);
break;
}
}
/**
* Sets the current transform to be the concatenation of the current transform and
* the provided transform.
* Note: If {@link #isSupported()} is false, then this will throw a Runtime Exception.
* @param t The transform to concatenate to this one.
*/
public void concatenate(Transform t){
inverseDirty=true;
impl.concatenateTransform(getNativeTransform(), t.getNativeTransform());
type = TYPE_UNKNOWN;
}
/**
* Sets the transform to be the specified perspective transformation.
* Note: If {@link #isPerspectiveSupported()} is false, then this will throw a Runtime Exception.
* @param fovy Y-field of view angle.
* @param aspect Apspect ratio of the view window.
* @param zNear Nearest visible z-coordinate.
* @param zFar Farthest visible z-coordinate.
* @see #makePerspective()
*/
public void setPerspective(float fovy, float aspect, float zNear, float zFar){
type = TYPE_UNKNOWN;
inverseDirty=true;
impl.setTransformPerspective(getNativeTransform(), fovy, aspect, zNear, zFar);
}
public void setAffine(double m00,
double m10,
double m01,
double m11,
double m02,
double m12) {
type = TYPE_UNKNOWN;
inverseDirty=true;
impl.setTransformAffine(getNativeTransform(), m00, m10, m01, m11, m02, m12);
}
/**
* Sets the transform to be the specified orthogonal view.
* Note: If {@link #isPerspectiveSupported()} is false, then this will throw a Runtime Exception.
* @param left Left x-coord of view.
* @param right Right x-coord of view.
* @param bottom Bottom y-coord of view.
* @param top Top y-coord of view.
* @param near Nearest visible z-coordinate
* @param far Farthest visible z-coordinate
*/
public void setOrtho(float left, float right, float bottom, float top,
float near, float far){
type = TYPE_UNKNOWN;
inverseDirty=true;
impl.setTransformOrtho(getNativeTransform(), left, right, bottom, top, near, far);
}
/**
* Sets the transform to the specified camera's perspective.
* Note: If {@link #isPerspectiveSupported()} is false, then this will throw a Runtime Exception.
* @param eyeX The x-coordinate of the camera's eye.
* @param eyeY The y-coordinate of the camera's eye.
* @param eyeZ The z-coordinate of the camera's eye.
* @param centerX The center x coordinate of the view.
* @param centerY The center y coordinate of the view.
* @param centerZ The center z coordinate of the view.
* @param upX The x-coordinate of the up vector for the camera.
* @param upY The y-coordinate of the up vector for the camera.
* @param upZ The z-coordinate of the up vector for the camera.
*/
public void setCamera(float eyeX, float eyeY, float eyeZ,
float centerX, float centerY, float centerZ, float upX, float upY,
float upZ){
setTransform(makeCamera(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ));
}
/**
* Transforms a set of points using the current transform.
* @param pointSize The size of the points to transform (2 or 3)
* @param in Input array of points.
* @param srcPos Start position in input array
* @param out Output array of points
* @param destPos Start position in output array
* @param numPoints Number of points to transform.
*/
public void transformPoints(int pointSize, float[] in, int srcPos, float[] out, int destPos, int numPoints) {
switch (type) {
case TYPE_TRANSLATION:
impl.translatePoints(pointSize, translateX, translateY, translateZ, in, srcPos, out, destPos, numPoints);
break;
case TYPE_SCALE:
impl.scalePoints(pointSize, scaleX, scaleY, scaleZ, in, srcPos, out, destPos, numPoints);
break;
case TYPE_IDENTITY:
System.arraycopy(in, srcPos, out, destPos, numPoints * pointSize);
break;
default :
impl.transformPoints(getNativeTransform(), pointSize, in, srcPos, out, destPos, numPoints);
break;
}
}
/**
* Transforms a provided point.
* Note: If {@link #isSupported()} is false, then this will throw a Runtime Exception.
* @param point 2 or 3 element array representing either an (x,y) or (x,y,z) tuple.
* @return A 3-element array representing transformed (x,y,z) tuple.
*/
public float[] transformPoint(float[] point){
float[] out = new float[3];
transformPoint(point, out);
return out;
}
/**
* Transforms a provided point and places the result in the provided array.
* Note: If {@link #isSupported()} is false, then this will throw a Runtime Exception.
* @param in A 2 or 3 element array representing either an (x,y) or (x,y,z) tuple.
* @param out A 2 or 3 element array in which the transformed point will be stored. Should match the length of the in array.
*/
public void transformPoint(float[] in, float[] out){
int len = in.length;
int olen = out.length;
switch (type){
case TYPE_TRANSLATION:
out[0] = in[0]+translateX;
out[1] = in[1]+translateY;
if ( len > 2 && olen > 2 ){
out[2] = in[2]+translateZ;
} else if (olen > 2){
out[2] = 0;
}
break;
case TYPE_SCALE:
out[0] = in[0]*scaleX;
out[1] = in[1]*scaleY;
if ( len > 2 && olen > 2 ){
out[2] = in[2]*scaleZ;
} else if ( olen > 2){
out[2] = 0;
}
break;
case TYPE_IDENTITY:
System.arraycopy(in,0,out,0,len);
if ( len <= 2 && olen > 2 ){
out[2] = 0;
}
break;
default:
impl.transformPoint(getNativeTransform(), in, out);
}
}
/**
* Gets the native transform object. This object is implementation dependent so this
* method should really only be used by the implementation.
* Note: If {@link #isSupported()} is false, then this will throw a Runtime Exception.
* @return The native transform object.
*/
public Object getNativeTransform(){
if ( dirty ){
initNativeTransform();
}
return nativeTransform;
}
/**
* Creates a copy of the current transform.
* Note: If {@link #isSupported()} is false, then this will throw a Runtime Exception.
* @return A copy of the current transform.
*/
public Transform copy(){
Transform out = new Transform(null);
out.setTransform(this);
return out;
}
/**
* Checks if transforms are supported on this platform. If this returns false,
* you cannot use this class.
* @return True if and only if this platform supports transforms.
*/
public static boolean isSupported(){
return Display.impl.isTransformSupported();
}
/**
* Checks if perspective transforms are supported on this platform. If this returns false,
* you cannot use this class.
* @return True if and only if this platform supports transforms.
*/
public static boolean isPerspectiveSupported(){
return Display.impl.isPerspectiveTransformSupported();
}
public boolean equals(Transform t2){
if ( type == TYPE_IDENTITY && t2.type == TYPE_IDENTITY ){
return true;
}
boolean out = impl.transformEqualsImpl(this, t2);
return out;
}
}