001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019/*
020*
021
022Licensed under the Apache License, Version 2.0 (the "License");
023you may not use this file except in compliance with the License.
024You may obtain a copy of the License at
025
026   http://www.apache.org/licenses/LICENSE-2.0
027
028Unless required by applicable law or agreed to in writing, software
029distributed under the License is distributed on an "AS IS" BASIS,
030WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
031See the License for the specific language governing permissions and
032limitations under the License.
033*/
034
035package lucee.runtime.img.composite;
036
037import java.awt.Composite;
038import java.awt.CompositeContext;
039import java.awt.RenderingHints;
040import java.awt.image.ColorModel;
041import java.awt.image.Raster;
042import java.awt.image.WritableRaster;
043
044/**
045 * A special Composite used for drawing "marching ants". It draws the ants at the 127 contour of the alpha channel of the source.
046 * This can only be used on TYPE_INT_RGBA images.
047 */
048public final class ContourComposite implements Composite {
049
050        private int offset;
051
052        public ContourComposite( int offset ) {
053                this.offset = offset;
054        }
055
056        public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) {
057                return new ContourCompositeContext( offset, srcColorModel, dstColorModel );
058        }
059
060        public int hashCode() {
061                return 0;
062        }
063
064        public boolean equals(Object o) {
065                if (!(o instanceof ContourComposite))
066                        return false;
067                return true;
068        }
069
070}
071
072class ContourCompositeContext implements CompositeContext {
073
074        private int offset;
075
076        public ContourCompositeContext( int offset, ColorModel srcColorModel, ColorModel dstColorModel ) {
077                this.offset = offset;
078        }
079
080        public void dispose() {
081        }
082        
083        public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
084                int x = src.getMinX();
085                int y = src.getMinY();
086                int w = src.getWidth();
087                int h = src.getHeight();
088
089                int[] srcPix = null;
090                int[] srcPix2 = null;
091                int[] dstInPix = null;
092                int[] dstOutPix = new int[w*4];
093
094                for ( int i = 0; i < h; i++ ) {
095                        srcPix = src.getPixels(x, y, w, 1, srcPix);
096                        dstInPix = dstIn.getPixels(x, y, w, 1, dstInPix);
097
098                        int lastAlpha = 0;
099                        int k = 0;
100                        for ( int j = 0; j < w; j++ ) {
101                                int alpha = srcPix[k+3];
102                                int alphaAbove = i != 0 ? srcPix2[k+3] : alpha;
103
104                                if ( i != 0 && j != 0 && ((alpha ^ lastAlpha) & 0x80) != 0 || ((alpha ^ alphaAbove) & 0x80) != 0 ) {
105                                        if ((offset+i+j)%10 > 4) {
106                                                dstOutPix[k] = 0x00;
107                                                dstOutPix[k+1] = 0x00;
108                                                dstOutPix[k+2] = 0x00;
109                                        } else {
110                                                dstOutPix[k] = 0xff;
111                                                dstOutPix[k+1] = 0xff;
112                                                dstOutPix[k+2] = 0x7f;
113                                        }
114                                        dstOutPix[k+3] = 0xff;
115                                } else {
116                                        dstOutPix[k] = dstInPix[k];
117                                        dstOutPix[k+1] = dstInPix[k+1];
118                                        dstOutPix[k+2] = dstInPix[k+2];
119//                                      if ( dstOut == dstIn )
120                                                dstOutPix[k] = 0xff;
121                                                dstOutPix[k+1] = 0;
122                                                dstOutPix[k+2] = 0;
123                                                dstOutPix[k+3] = 0;
124//                                      else
125//                                              dstOutPix[k+3] = dstInPix[k+3];
126                                }
127
128                                lastAlpha = alpha;
129                                k += 4;
130                        }
131
132                        dstOut.setPixels(x, y, w, 1, dstOutPix);
133
134                        int[] t = srcPix;
135                        srcPix = srcPix2;
136                        srcPix2 = t;
137                        y++;
138                }
139        }
140
141}