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.composite; 018 019 import java.awt.Composite; 020 import java.awt.CompositeContext; 021 import java.awt.RenderingHints; 022 import java.awt.image.ColorModel; 023 import java.awt.image.Raster; 024 import java.awt.image.WritableRaster; 025 026 /** 027 * A special Composite used for drawing "marching ants". It draws the ants at the 127 contour of the alpha channel of the source. 028 * This can only be used on TYPE_INT_RGBA images. 029 */ 030 public final class ContourComposite implements Composite { 031 032 private int offset; 033 034 public ContourComposite( int offset ) { 035 this.offset = offset; 036 } 037 038 public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) { 039 return new ContourCompositeContext( offset, srcColorModel, dstColorModel ); 040 } 041 042 public int hashCode() { 043 return 0; 044 } 045 046 public boolean equals(Object o) { 047 if (!(o instanceof ContourComposite)) 048 return false; 049 return true; 050 } 051 052 } 053 054 class ContourCompositeContext implements CompositeContext { 055 056 private int offset; 057 058 public ContourCompositeContext( int offset, ColorModel srcColorModel, ColorModel dstColorModel ) { 059 this.offset = offset; 060 } 061 062 public void dispose() { 063 } 064 065 public void compose(Raster src, Raster dstIn, WritableRaster dstOut) { 066 int x = src.getMinX(); 067 int y = src.getMinY(); 068 int w = src.getWidth(); 069 int h = src.getHeight(); 070 071 int[] srcPix = null; 072 int[] srcPix2 = null; 073 int[] dstInPix = null; 074 int[] dstOutPix = new int[w*4]; 075 076 for ( int i = 0; i < h; i++ ) { 077 srcPix = src.getPixels(x, y, w, 1, srcPix); 078 dstInPix = dstIn.getPixels(x, y, w, 1, dstInPix); 079 080 int lastAlpha = 0; 081 int k = 0; 082 for ( int j = 0; j < w; j++ ) { 083 int alpha = srcPix[k+3]; 084 int alphaAbove = i != 0 ? srcPix2[k+3] : alpha; 085 086 if ( i != 0 && j != 0 && ((alpha ^ lastAlpha) & 0x80) != 0 || ((alpha ^ alphaAbove) & 0x80) != 0 ) { 087 if ((offset+i+j)%10 > 4) { 088 dstOutPix[k] = 0x00; 089 dstOutPix[k+1] = 0x00; 090 dstOutPix[k+2] = 0x00; 091 } else { 092 dstOutPix[k] = 0xff; 093 dstOutPix[k+1] = 0xff; 094 dstOutPix[k+2] = 0x7f; 095 } 096 dstOutPix[k+3] = 0xff; 097 } else { 098 dstOutPix[k] = dstInPix[k]; 099 dstOutPix[k+1] = dstInPix[k+1]; 100 dstOutPix[k+2] = dstInPix[k+2]; 101 // if ( dstOut == dstIn ) 102 dstOutPix[k] = 0xff; 103 dstOutPix[k+1] = 0; 104 dstOutPix[k+2] = 0; 105 dstOutPix[k+3] = 0; 106 // else 107 // dstOutPix[k+3] = dstInPix[k+3]; 108 } 109 110 lastAlpha = alpha; 111 k += 4; 112 } 113 114 dstOut.setPixels(x, y, w, 1, dstOutPix); 115 116 int[] t = srcPix; 117 srcPix = srcPix2; 118 srcPix2 = t; 119 y++; 120 } 121 } 122 123 }