001/*
002Copyright 2006 Jerry Huxtable
003
004Licensed under the Apache License, Version 2.0 (the "License");
005you may not use this file except in compliance with the License.
006You may obtain a copy of the License at
007
008   http://www.apache.org/licenses/LICENSE-2.0
009
010Unless required by applicable law or agreed to in writing, software
011distributed under the License is distributed on an "AS IS" BASIS,
012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013See the License for the specific language governing permissions and
014limitations under the License.
015*/
016
017package com.jhlabs.composite;
018
019import java.awt.*;
020import java.awt.image.*;
021import java.awt.color.*;
022
023/**
024 * A special Composite used for drawing "marching ants". It draws the ants at the 127 contour of the alpha channel of the source.
025 * This can only be used on TYPE_INT_RGBA images.
026 */
027public final class ContourComposite implements Composite {
028
029        private int offset;
030
031        public ContourComposite( int offset ) {
032                this.offset = offset;
033        }
034
035        public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) {
036                return new ContourCompositeContext( offset, srcColorModel, dstColorModel );
037        }
038
039        public int hashCode() {
040                return 0;
041        }
042
043        public boolean equals(Object o) {
044                if (!(o instanceof ContourComposite))
045                        return false;
046                return true;
047        }
048
049}
050
051class ContourCompositeContext implements CompositeContext {
052
053        private int offset;
054
055        public ContourCompositeContext( int offset, ColorModel srcColorModel, ColorModel dstColorModel ) {
056                this.offset = offset;
057        }
058
059        public void dispose() {
060        }
061        
062        public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
063                int x = src.getMinX();
064                int y = src.getMinY();
065                int w = src.getWidth();
066                int h = src.getHeight();
067
068                int[] srcPix = null;
069                int[] srcPix2 = null;
070                int[] dstInPix = null;
071                int[] dstOutPix = new int[w*4];
072
073                for ( int i = 0; i < h; i++ ) {
074                        srcPix = src.getPixels(x, y, w, 1, srcPix);
075                        dstInPix = dstIn.getPixels(x, y, w, 1, dstInPix);
076
077                        int lastAlpha = 0;
078                        int k = 0;
079                        for ( int j = 0; j < w; j++ ) {
080                                int alpha = srcPix[k+3];
081                                int alphaAbove = i != 0 ? srcPix2[k+3] : alpha;
082
083                                if ( i != 0 && j != 0 && ((alpha ^ lastAlpha) & 0x80) != 0 || ((alpha ^ alphaAbove) & 0x80) != 0 ) {
084                                        if ((offset+i+j)%10 > 4) {
085                                                dstOutPix[k] = 0x00;
086                                                dstOutPix[k+1] = 0x00;
087                                                dstOutPix[k+2] = 0x00;
088                                        } else {
089                                                dstOutPix[k] = 0xff;
090                                                dstOutPix[k+1] = 0xff;
091                                                dstOutPix[k+2] = 0x7f;
092                                        }
093                                        dstOutPix[k+3] = 0xff;
094                                } else {
095                                        dstOutPix[k] = dstInPix[k];
096                                        dstOutPix[k+1] = dstInPix[k+1];
097                                        dstOutPix[k+2] = dstInPix[k+2];
098//                                      if ( dstOut == dstIn )
099                                                dstOutPix[k] = 0xff;
100                                                dstOutPix[k+1] = 0;
101                                                dstOutPix[k+2] = 0;
102                                                dstOutPix[k+3] = 0;
103//                                      else
104//                                              dstOutPix[k+3] = dstInPix[k+3];
105                                }
106
107                                lastAlpha = alpha;
108                                k += 4;
109                        }
110
111                        dstOut.setPixels(x, y, w, 1, dstOutPix);
112
113                        int[] t = srcPix;
114                        srcPix = srcPix2;
115                        srcPix2 = t;
116                        y++;
117                }
118        }
119
120}