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 }
|