Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2008, 2013, Oracle 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. Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.scenario.effect;
import com.sun.javafx.geom.Point2D;
import com.sun.javafx.geom.BaseBounds;
import com.sun.javafx.geom.RectBounds;
import com.sun.javafx.geom.Rectangle;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.javafx.geom.transform.NoninvertibleTransformException;
/**
* The implementation base class for {@link Effect} subclasses that operate
* by filtering the inputs at the pixel level.
*/
public abstract class FilterEffect extends Effect {
protected FilterEffect() {
super();
}
protected FilterEffect(Effect input) {
super(input);
}
protected FilterEffect(Effect input1, Effect input2) {
super(input1, input2);
}
public boolean operatesInUserSpace() {
return false;
}
public BaseBounds getBounds(BaseTransform transform,
Effect defaultInput)
{
int numinputs = getNumInputs();
BaseTransform inputtx = transform;
if (operatesInUserSpace()) {
inputtx = BaseTransform.IDENTITY_TRANSFORM;
}
BaseBounds ret;
if (numinputs == 1) {
Effect input = getDefaultedInput(0, defaultInput);
ret = input.getBounds(inputtx, defaultInput);
} else {
BaseBounds inputBounds[] = new BaseBounds[numinputs];
for (int i = 0; i < numinputs; i++) {
Effect input = getDefaultedInput(i, defaultInput);
inputBounds[i] = input.getBounds(inputtx, defaultInput);
}
ret = combineBounds(inputBounds);
}
if (inputtx != transform) {
ret = transformBounds(transform, ret);
}
return ret;
}
protected abstract Rectangle getInputClip(int inputIndex,
BaseTransform transform,
Rectangle outputBounds);
protected static Rectangle untransformClip(BaseTransform transform,
Rectangle clip)
{
if (transform.isIdentity() || clip == null || clip.isEmpty()) {
return clip;
}
// We are asked to produce samples for the pixels in the
// Rectangular clip. The samples requested are delivered for
// the centers of the pixels for every pixel in that range.
// Thus, we need valid data for the clip inset by 0.5 pixels
// all around.
// But, when we untransform, we need to make sure that the data
// we provide can be used to provide a valid sample for each of
// those points. If the mapped sample coordinate falls on a
// non-integer coordinate then we need the data for the 4 pixels
// around that point. Thus, we need a sample for the pixel that it
// falls on, and potentially a sample for the next pixel over if
// we are within 0.5 pixels of the edge of those border pixels.
// The full operation is then:
// clip.inset(0.5) // reduce to requested pixel centers
// tx.untransform(clip) // untransform to new source space
// clip.outset(0.5) // expand for bilinear interpolation
// clip.roundtopixels() // clamp to pixel edges
Rectangle transformedBounds = new Rectangle();
if (transform.isTranslateOrIdentity()) {
// In this case the inset and outset cancel each other out
// and the floor(x0,y0) and ceil(x1,y1) are enough to provide
// whatever padding is needed.
transformedBounds.setBounds(clip);
double tx = -transform.getMxt();
double ty = -transform.getMyt();
int itx = (int) Math.floor(tx);
int ity = (int) Math.floor(ty);
transformedBounds.translate(itx, ity);
if (itx != tx) {
// floor(x0) is 1 more pixel away from ceil(x1)
transformedBounds.width++;
}
if (ity != ty) {
// floor(y0) is 1 more pixel away from ceil(y1)
transformedBounds.height++;
}
return transformedBounds;
}
RectBounds b = new RectBounds(clip);
try {
b.grow(-0.5f, -0.5f);
b = (RectBounds) transform.inverseTransform(b, b);
b.grow(0.5f, 0.5f);
transformedBounds.setBounds(b);
} catch (NoninvertibleTransformException e) {
// Non-invertible means the transform has collapsed onto
// a point or line and so the results of the effect are
// not visible so we can use the empty bounds object we
// created for transformedBounds. Ideally this would be
// checked further up in the chain, but in case we get here
// we might as well do as little work as we can.
}
return transformedBounds;
}
@Override
public ImageData filter(FilterContext fctx,
BaseTransform transform,
Rectangle outputClip,
Object renderHelper,
Effect defaultInput)
{
int numinputs = getNumInputs();
ImageData inputDatas[] = new ImageData[numinputs];
Rectangle inputClip;
BaseTransform inputtx;
if (operatesInUserSpace()) {
inputClip = untransformClip(transform, outputClip);
inputtx = BaseTransform.IDENTITY_TRANSFORM;
} else {
inputClip = outputClip;
inputtx = transform;
}
for (int i = 0; i < numinputs; i++) {
Effect input = getDefaultedInput(i, defaultInput);
inputDatas[i] =
input.filter(fctx, inputtx,
getInputClip(i, inputtx, inputClip),
null, defaultInput);
if (!inputDatas[i].validate(fctx)) {
for (int j = 0; j <= i; j++) {
inputDatas[j].unref();
}
return new ImageData(fctx, null, null);
}
}
ImageData ret = filterImageDatas(fctx, inputtx, inputClip, inputDatas);
for (int i = 0; i < numinputs; i++) {
inputDatas[i].unref();
}
if (inputtx != transform) {
if (renderHelper instanceof ImageDataRenderer) {
ImageDataRenderer renderer = (ImageDataRenderer) renderHelper;
renderer.renderImage(ret, transform, fctx);
ret.unref();
ret = null;
} else {
ret = ret.transform(transform);
}
}
return ret;
}
@Override
public Point2D transform(Point2D p, Effect defaultInput) {
return getDefaultedInput(0, defaultInput).transform(p, defaultInput);
}
@Override
public Point2D untransform(Point2D p, Effect defaultInput) {
return getDefaultedInput(0, defaultInput).untransform(p, defaultInput);
}
protected abstract ImageData filterImageDatas(FilterContext fctx,
BaseTransform transform,
Rectangle outputClip,
ImageData... inputDatas);
}