001    /*
002    *
003    
004    Licensed under the Apache License, Version 2.0 (the "License");
005    you may not use this file except in compliance with the License.
006    You may obtain a copy of the License at
007    
008       http://www.apache.org/licenses/LICENSE-2.0
009    
010    Unless required by applicable law or agreed to in writing, software
011    distributed under the License is distributed on an "AS IS" BASIS,
012    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013    See the License for the specific language governing permissions and
014    limitations under the License.
015    */
016    
017    package railo.runtime.img.filter;import java.awt.AlphaComposite;
018    import java.awt.Color;
019    import java.awt.GradientPaint;
020    import java.awt.Graphics2D;
021    import java.awt.Shape;
022    import java.awt.image.BufferedImage;
023    
024    import railo.runtime.engine.ThreadLocalPageContext;
025    import railo.runtime.exp.FunctionException;
026    import railo.runtime.exp.PageException;
027    import railo.runtime.img.ImageUtil;
028    import railo.runtime.type.KeyImpl;
029    import railo.runtime.type.List;
030    import railo.runtime.type.Struct;
031    
032    public class MirrorFilter extends AbstractBufferedImageOp  implements DynFiltering {
033        private float opacity = 1.0f;
034            private float centreY = 0.5f;
035        private float distance;
036        private float angle;
037        private float rotation;
038        private float gap;
039    
040        public MirrorFilter() {
041            }
042            
043            /**
044         * Specifies the angle of the mirror.
045         * @param angle the angle of the mirror.
046         * @angle
047         * @see #getAngle
048         */
049            public void setAngle( float angle ) {
050                    this.angle = angle;
051            }
052    
053            /**
054         * Returns the angle of the mirror.
055         * @return the angle of the mirror.
056         * @see #setAngle
057         */
058            public float getAngle() {
059                    return angle;
060            }
061            
062            public void setDistance( float distance ) {
063                    this.distance = distance;
064            }
065    
066            public float getDistance() {
067                    return distance;
068            }
069            
070            public void setRotation( float rotation ) {
071                    this.rotation = rotation;
072            }
073    
074            public float getRotation() {
075                    return rotation;
076            }
077            
078            public void setGap( float gap ) {
079                    this.gap = gap;
080            }
081    
082            public float getGap() {
083                    return gap;
084            }
085            
086            /**
087         * Set the opacity of the reflection.
088         * @param opacity the opacity.
089         * @see #getOpacity
090         */
091            public void setOpacity( float opacity ) {
092                    this.opacity = opacity;
093            }
094    
095            /**
096         * Get the opacity of the reflection.
097         * @return the opacity.
098         * @see #setOpacity
099         */
100            public float getOpacity() {
101                    return opacity;
102            }
103            
104            public void setCentreY( float centreY ) {
105                    this.centreY = centreY;
106            }
107    
108            public float getCentreY() {
109                    return centreY;
110            }
111            
112        public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
113            if ( dst == null )
114                dst = createCompatibleDestImage( src, null );
115            BufferedImage tsrc = src;
116                    Shape clip;
117                    int width = src.getWidth();
118                    int height = src.getHeight();
119                    int h = (int)(centreY * height);
120                    int d = (int)(gap * height);
121    
122                    Graphics2D g = dst.createGraphics();
123                    clip = g.getClip();
124                    g.clipRect( 0, 0, width, h );
125                    g.drawRenderedImage( src, null );
126                    g.setClip( clip );
127                    g.clipRect( 0, h+d, width, height-h-d );
128                    g.translate( 0, 2*h+d );
129                    g.scale( 1, -1 );
130                    g.drawRenderedImage( src, null );
131                    g.setPaint( new GradientPaint( 0, 0, new Color( 1.0f, 0.0f, 0.0f, 0.0f ), 0, h, new Color( 0.0f, 1.0f, 0.0f, opacity ) ) );
132                    g.setComposite( AlphaComposite.getInstance( AlphaComposite.DST_IN ) );
133                    g.fillRect( 0, 0, width, h );
134                    g.setClip( clip );
135                    g.dispose();
136            
137            return dst;
138        }
139        
140            public String toString() {
141                    return "Effects/Mirror...";
142            }
143            public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
144                    Object o;
145                    if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle"));
146                    if((o=parameters.removeEL(KeyImpl.init("CentreY")))!=null)setCentreY(ImageFilterUtil.toFloatValue(o,"CentreY"));
147                    if((o=parameters.removeEL(KeyImpl.init("Distance")))!=null)setDistance(ImageFilterUtil.toFloatValue(o,"Distance"));
148                    if((o=parameters.removeEL(KeyImpl.init("Rotation")))!=null)setRotation(ImageFilterUtil.toFloatValue(o,"Rotation"));
149                    if((o=parameters.removeEL(KeyImpl.init("Gap")))!=null)setGap(ImageFilterUtil.toFloatValue(o,"Gap"));
150                    if((o=parameters.removeEL(KeyImpl.init("Opacity")))!=null)setOpacity(ImageFilterUtil.toFloatValue(o,"Opacity"));
151    
152                    // check for arguments not supported
153                    if(parameters.size()>0) {
154                            throw new FunctionException(ThreadLocalPageContext.get(), "ImageFilter", 3, "parameters", "the parameter"+(parameters.size()>1?"s":"")+" ["+List.arrayToList(parameters.keysAsString(),", ")+"] "+(parameters.size()>1?"are":"is")+" not allowed, only the following parameters are supported [Angle, CentreY, Distance, Rotation, Gap, Opacity]");
155                    }
156    
157                    return filter(src, dst);
158            }
159    }