modules/graphics/src/main/java/com/sun/scenario/effect/PerspectiveTransform.java

Print this page




  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.scenario.effect;
  27 
  28 import com.sun.scenario.effect.impl.state.PerspectiveTransformState;
  29 import com.sun.javafx.geom.Point2D;
  30 import com.sun.javafx.geom.BaseBounds;
  31 import com.sun.javafx.geom.DirtyRegionContainer;
  32 import com.sun.javafx.geom.DirtyRegionPool;
  33 import com.sun.javafx.geom.RectBounds;
  34 import com.sun.javafx.geom.Rectangle;
  35 import com.sun.javafx.geom.transform.BaseTransform;

  36 
  37 public class PerspectiveTransform extends CoreEffect {
  38     private float tx[][] = new float[3][3];
  39     private float ulx, uly, urx, ury, lrx, lry, llx, lly;
  40     private float devcoords[] = new float[8];
  41     private final PerspectiveTransformState state = new PerspectiveTransformState();
  42 
  43     public PerspectiveTransform() {
  44         this(DefaultInput);
  45     }
  46 
  47     public PerspectiveTransform(Effect input) {
  48         super(input);
  49         setQuadMapping(0f, 0f, 100f, 0f, 100f, 100f, 0f, 100f);
  50         updatePeerKey("PerspectiveTransform");
  51     }
  52 
  53     @Override
  54     Object getState() {
  55         return state;


 166             else if (maxx < devcoords[i]) maxx = devcoords[i];
 167             if (miny > devcoords[i+1]) miny = devcoords[i+1];
 168             else if (maxy < devcoords[i+1]) maxy = devcoords[i+1];
 169         }
 170         return new RectBounds(minx, miny, maxx, maxy);
 171     }
 172 
 173     private void setupDevCoords(BaseTransform transform) {
 174         devcoords[0] = ulx;
 175         devcoords[1] = uly;
 176         devcoords[2] = urx;
 177         devcoords[3] = ury;
 178         devcoords[4] = lrx;
 179         devcoords[5] = lry;
 180         devcoords[6] = llx;
 181         devcoords[7] = lly;
 182         transform.transform(devcoords, 0, devcoords, 0, 4);
 183     }
 184 
 185     @Override
 186     public boolean operatesInUserSpace() {
 187         return true;
 188     }
 189 
 190     @Override
 191     public ImageData filter(FilterContext fctx,
 192                             BaseTransform transform,
 193                             Rectangle outputClip,
 194                             Object renderHelper,
 195                             Effect defaultInput)
 196     {
 197         setupTransforms(transform);


 198         Effect input = getDefaultedInput(0, defaultInput);
 199         Rectangle inputClip = getInputClip(0, transform, outputClip);
 200         ImageData inputData =
 201             input.filter(fctx, BaseTransform.IDENTITY_TRANSFORM,
 202                          inputClip, null, defaultInput);
 203         if (!inputData.validate(fctx)) {
 204             inputData.unref();
 205             return new ImageData(fctx, null, inputData.getUntransformedBounds());
 206         }
 207         ImageData ret = filterImageDatas(fctx, transform, outputClip, inputData);
 208         inputData.unref();
 209         return ret;
 210     }
 211 
 212     @Override
 213     public Rectangle getResultBounds(BaseTransform transform,
 214                                      Rectangle outputClip,
 215                                      ImageData... inputDatas)
 216     {
 217         Rectangle ob = new Rectangle(getBounds(transform, null));
 218         ob.intersectWith(outputClip);
 219         return ob;
 220     }
 221 
 222     @Override
 223     public Point2D transform(Point2D p, Effect defaultInput) {
 224         setupTransforms(BaseTransform.IDENTITY_TRANSFORM);
 225         Effect input = getDefaultedInput(0, defaultInput);
 226         p = input.transform(p, defaultInput);
 227         BaseBounds b = input.getBounds(BaseTransform.IDENTITY_TRANSFORM, defaultInput);


 243         float itx[][] = state.getITX();
 244         float sx = itx[0][0] * dx + itx[0][1] * dy + itx[0][2];
 245         float sy = itx[1][0] * dx + itx[1][1] * dy + itx[1][2];
 246         float sw = itx[2][0] * dx + itx[2][1] * dy + itx[2][2];
 247         BaseBounds b = input.getBounds(BaseTransform.IDENTITY_TRANSFORM, defaultInput);
 248         p = new Point2D(b.getMinX() + (sx / sw) * b.getWidth(),
 249                         b.getMinY() + (sy / sw) * b.getHeight());
 250         p = getDefaultedInput(0, defaultInput).untransform(p, defaultInput);
 251         return p;
 252     }
 253 
 254     private void setupTransforms(BaseTransform transform) {
 255         setupDevCoords(transform);
 256         setUnitQuadMapping(devcoords[0], devcoords[1],
 257                            devcoords[2], devcoords[3],
 258                            devcoords[4], devcoords[5],
 259                            devcoords[6], devcoords[7]);
 260     }
 261 
 262     @Override
 263     protected Rectangle getInputClip(int inputIndex,
 264                                      BaseTransform transform,
 265                                      Rectangle outputClip)


 266     {
 267         // RT-27402
 268         // TODO: Inverse map the bounds through the perspective
 269         // transform to see what portions of the source contribute
 270         // to it.
 271         return null;

 272     }
 273 
 274     @Override
 275     public boolean reducesOpaquePixels() {
 276         return true;
 277     }
 278 
 279     @Override
 280     public DirtyRegionContainer getDirtyRegions(Effect defaultInput, DirtyRegionPool regionPool) {
 281         DirtyRegionContainer drc = regionPool.checkOut();
 282 
 283         //RT-28197 - Dirty regions could be computed in more efficient way
 284         drc.deriveWithNewRegion((RectBounds) getBounds(BaseTransform.IDENTITY_TRANSFORM, defaultInput));
 285         
 286         return drc;
 287     }
 288 }


  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.scenario.effect;
  27 
  28 import com.sun.scenario.effect.impl.state.PerspectiveTransformState;
  29 import com.sun.javafx.geom.Point2D;
  30 import com.sun.javafx.geom.BaseBounds;
  31 import com.sun.javafx.geom.DirtyRegionContainer;
  32 import com.sun.javafx.geom.DirtyRegionPool;
  33 import com.sun.javafx.geom.RectBounds;
  34 import com.sun.javafx.geom.Rectangle;
  35 import com.sun.javafx.geom.transform.BaseTransform;
  36 import com.sun.scenario.effect.impl.state.RenderState;
  37 
  38 public class PerspectiveTransform extends CoreEffect {
  39     private float tx[][] = new float[3][3];
  40     private float ulx, uly, urx, ury, lrx, lry, llx, lly;
  41     private float devcoords[] = new float[8];
  42     private final PerspectiveTransformState state = new PerspectiveTransformState();
  43 
  44     public PerspectiveTransform() {
  45         this(DefaultInput);
  46     }
  47 
  48     public PerspectiveTransform(Effect input) {
  49         super(input);
  50         setQuadMapping(0f, 0f, 100f, 0f, 100f, 100f, 0f, 100f);
  51         updatePeerKey("PerspectiveTransform");
  52     }
  53 
  54     @Override
  55     Object getState() {
  56         return state;


 167             else if (maxx < devcoords[i]) maxx = devcoords[i];
 168             if (miny > devcoords[i+1]) miny = devcoords[i+1];
 169             else if (maxy < devcoords[i+1]) maxy = devcoords[i+1];
 170         }
 171         return new RectBounds(minx, miny, maxx, maxy);
 172     }
 173 
 174     private void setupDevCoords(BaseTransform transform) {
 175         devcoords[0] = ulx;
 176         devcoords[1] = uly;
 177         devcoords[2] = urx;
 178         devcoords[3] = ury;
 179         devcoords[4] = lrx;
 180         devcoords[5] = lry;
 181         devcoords[6] = llx;
 182         devcoords[7] = lly;
 183         transform.transform(devcoords, 0, devcoords, 0, 4);
 184     }
 185 
 186     @Override





 187     public ImageData filter(FilterContext fctx,
 188                             BaseTransform transform,
 189                             Rectangle outputClip,
 190                             Object renderHelper,
 191                             Effect defaultInput)
 192     {
 193         setupTransforms(transform);
 194         RenderState rstate = getRenderState(fctx, transform, outputClip,
 195                                             renderHelper, defaultInput);
 196         Effect input = getDefaultedInput(0, defaultInput);
 197         Rectangle inputClip = rstate.getInputClip(0, outputClip);
 198         ImageData inputData =
 199             input.filter(fctx, BaseTransform.IDENTITY_TRANSFORM,
 200                          inputClip, null, defaultInput);
 201         if (!inputData.validate(fctx)) {
 202             inputData.unref();
 203             return new ImageData(fctx, null, inputData.getUntransformedBounds());
 204         }
 205         ImageData ret = filterImageDatas(fctx, transform, outputClip, rstate, inputData);
 206         inputData.unref();
 207         return ret;
 208     }
 209 
 210     @Override
 211     public Rectangle getResultBounds(BaseTransform transform,
 212                                      Rectangle outputClip,
 213                                      ImageData... inputDatas)
 214     {
 215         Rectangle ob = new Rectangle(getBounds(transform, null));
 216         ob.intersectWith(outputClip);
 217         return ob;
 218     }
 219 
 220     @Override
 221     public Point2D transform(Point2D p, Effect defaultInput) {
 222         setupTransforms(BaseTransform.IDENTITY_TRANSFORM);
 223         Effect input = getDefaultedInput(0, defaultInput);
 224         p = input.transform(p, defaultInput);
 225         BaseBounds b = input.getBounds(BaseTransform.IDENTITY_TRANSFORM, defaultInput);


 241         float itx[][] = state.getITX();
 242         float sx = itx[0][0] * dx + itx[0][1] * dy + itx[0][2];
 243         float sy = itx[1][0] * dx + itx[1][1] * dy + itx[1][2];
 244         float sw = itx[2][0] * dx + itx[2][1] * dy + itx[2][2];
 245         BaseBounds b = input.getBounds(BaseTransform.IDENTITY_TRANSFORM, defaultInput);
 246         p = new Point2D(b.getMinX() + (sx / sw) * b.getWidth(),
 247                         b.getMinY() + (sy / sw) * b.getHeight());
 248         p = getDefaultedInput(0, defaultInput).untransform(p, defaultInput);
 249         return p;
 250     }
 251 
 252     private void setupTransforms(BaseTransform transform) {
 253         setupDevCoords(transform);
 254         setUnitQuadMapping(devcoords[0], devcoords[1],
 255                            devcoords[2], devcoords[3],
 256                            devcoords[4], devcoords[5],
 257                            devcoords[6], devcoords[7]);
 258     }
 259 
 260     @Override
 261     public RenderState getRenderState(FilterContext fctx,
 262                                       BaseTransform transform,
 263                                       Rectangle outputClip,
 264                                       Object renderHelper,
 265                                       Effect defaultInput)
 266     {
 267         // RT-27402
 268         // TODO: We could inverse map the output bounds through the perspective
 269         // transform to see what portions of the input contribute to the result,
 270         // but until we implement such a process we will just use the stock
 271         // object that specifies no clipping of the inputs.
 272         return RenderState.UnclippedUserSpaceRenderState;
 273     }
 274 
 275     @Override
 276     public boolean reducesOpaquePixels() {
 277         return true;
 278     }
 279 
 280     @Override
 281     public DirtyRegionContainer getDirtyRegions(Effect defaultInput, DirtyRegionPool regionPool) {
 282         DirtyRegionContainer drc = regionPool.checkOut();
 283 
 284         //RT-28197 - Dirty regions could be computed in more efficient way
 285         drc.deriveWithNewRegion((RectBounds) getBounds(BaseTransform.IDENTITY_TRANSFORM, defaultInput));
 286         
 287         return drc;
 288     }
 289 }