1796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta/* 2796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Copyright (C) 2014 The Android Open Source Project 3796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 4796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Licensed under the Apache License, Version 2.0 (the "License"); 5796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * you may not use this file except in compliance with the License. 6796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * You may obtain a copy of the License at 7796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 8796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * http://www.apache.org/licenses/LICENSE-2.0 9796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 10796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Unless required by applicable law or agreed to in writing, software 11796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * distributed under the License is distributed on an "AS IS" BASIS, 12796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * See the License for the specific language governing permissions and 14796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * limitations under the License. 15796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 16796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 17796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptapackage android.view; 18796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 19796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptaimport com.android.annotations.NonNull; 20796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 21796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptaimport java.awt.Graphics2D; 22796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptaimport java.awt.Image; 23796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptaimport java.awt.image.BufferedImage; 24796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptaimport java.awt.image.DataBufferInt; 25796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptaimport java.io.IOException; 26796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptaimport java.io.InputStream; 27796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 28796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptaimport javax.imageio.ImageIO; 29796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 30796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Guptapublic class ShadowPainter { 31796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 32796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 33796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Adds a drop shadow to a semi-transparent image (of an arbitrary shape) and returns it as a 34796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * new image. This method attempts to mimic the same visual characteristics as the rectangular 35796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * shadow painting methods in this class, {@link #createRectangularDropShadow(java.awt.image.BufferedImage)} 36796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * and {@link #createSmallRectangularDropShadow(java.awt.image.BufferedImage)}. 37796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 38796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param source the source image 39796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param shadowSize the size of the shadow, normally {@link #SHADOW_SIZE or {@link 40796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * #SMALL_SHADOW_SIZE}} 41796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 42796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @return a new image with the shadow painted in 43796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 44796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta @NonNull 45796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static BufferedImage createDropShadow(BufferedImage source, int shadowSize) { 46796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta shadowSize /= 2; // make shadow size have the same meaning as in the other shadow paint methods in this class 47796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 48796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta return createDropShadow(source, shadowSize, 0.7f, 0); 49796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 50796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 51796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 52796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Creates a drop shadow of a given image and returns a new image which shows the input image on 53796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * top of its drop shadow. 54796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * <p/> 55796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * <b>NOTE: If the shape is rectangular and opaque, consider using {@link 56796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * #drawRectangleShadow(Graphics2D, int, int, int, int)} instead.</b> 57796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 58796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param source the source image to be shadowed 59796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param shadowSize the size of the shadow in pixels 60796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param shadowOpacity the opacity of the shadow, with 0=transparent and 1=opaque 61796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param shadowRgb the RGB int to use for the shadow color 62796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 63796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @return a new image with the source image on top of its shadow 64796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 65796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta @SuppressWarnings({"SuspiciousNameCombination", "UnnecessaryLocalVariable"}) // Imported code 66796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static BufferedImage createDropShadow(BufferedImage source, int shadowSize, 67796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta float shadowOpacity, int shadowRgb) { 68796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 69796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // This code is based on 70796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // http://www.jroller.com/gfx/entry/non_rectangular_shadow 71796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 72796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta BufferedImage image; 73796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int width = source.getWidth(); 74796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int height = source.getHeight(); 75796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta image = new BufferedImage(width + SHADOW_SIZE, height + SHADOW_SIZE, 76796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta BufferedImage.TYPE_INT_ARGB); 77796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 78796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta Graphics2D g2 = image.createGraphics(); 79796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta g2.drawImage(image, shadowSize, shadowSize, null); 80796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 81796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int dstWidth = image.getWidth(); 82796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int dstHeight = image.getHeight(); 83796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 84796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int left = (shadowSize - 1) >> 1; 85796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int right = shadowSize - left; 86796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int xStart = left; 87796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int xStop = dstWidth - right; 88796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int yStart = left; 89796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int yStop = dstHeight - right; 90796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 91796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta shadowRgb &= 0x00FFFFFF; 92796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 93796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int[] aHistory = new int[shadowSize]; 94796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int historyIdx; 95796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 96796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int aSum; 97796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 98796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int[] dataBuffer = ((DataBufferInt) image.getRaster().getDataBuffer()).getData(); 99796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int lastPixelOffset = right * dstWidth; 100796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta float sumDivider = shadowOpacity / shadowSize; 101796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 102796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // horizontal pass 103796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta for (int y = 0, bufferOffset = 0; y < dstHeight; y++, bufferOffset = y * dstWidth) { 104796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aSum = 0; 105796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta historyIdx = 0; 106796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta for (int x = 0; x < shadowSize; x++, bufferOffset++) { 107796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int a = dataBuffer[bufferOffset] >>> 24; 108796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aHistory[x] = a; 109796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aSum += a; 110796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 111796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 112796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta bufferOffset -= right; 113796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 114796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta for (int x = xStart; x < xStop; x++, bufferOffset++) { 115796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int a = (int) (aSum * sumDivider); 116796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta dataBuffer[bufferOffset] = a << 24 | shadowRgb; 117796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 118796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // subtract the oldest pixel from the sum 119796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aSum -= aHistory[historyIdx]; 120796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 121796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // get the latest pixel 122796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta a = dataBuffer[bufferOffset + right] >>> 24; 123796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aHistory[historyIdx] = a; 124796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aSum += a; 125796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 126796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta if (++historyIdx >= shadowSize) { 127796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta historyIdx -= shadowSize; 128796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 129796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 130796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 131796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // vertical pass 132796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x) { 133796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aSum = 0; 134796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta historyIdx = 0; 135796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta for (int y = 0; y < shadowSize; y++, bufferOffset += dstWidth) { 136796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int a = dataBuffer[bufferOffset] >>> 24; 137796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aHistory[y] = a; 138796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aSum += a; 139796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 140796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 141796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta bufferOffset -= lastPixelOffset; 142796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 143796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta for (int y = yStart; y < yStop; y++, bufferOffset += dstWidth) { 144796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int a = (int) (aSum * sumDivider); 145796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta dataBuffer[bufferOffset] = a << 24 | shadowRgb; 146796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 147796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // subtract the oldest pixel from the sum 148796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aSum -= aHistory[historyIdx]; 149796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 150796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // get the latest pixel 151796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta a = dataBuffer[bufferOffset + lastPixelOffset] >>> 24; 152796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aHistory[historyIdx] = a; 153796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta aSum += a; 154796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 155796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta if (++historyIdx >= shadowSize) { 156796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta historyIdx -= shadowSize; 157796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 158796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 159796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 160796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 161796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta g2.drawImage(source, null, 0, 0); 162796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta g2.dispose(); 163796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 164796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta return image; 165796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 166796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 167796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 168796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Draws a rectangular drop shadow (of size {@link #SHADOW_SIZE} by {@link #SHADOW_SIZE} around 169796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * the given source and returns a new image with both combined 170796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 171796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param source the source image 172796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 173796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @return the source image with a drop shadow on the bottom and right 174796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 175796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta @SuppressWarnings("UnusedDeclaration") 176796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static BufferedImage createRectangularDropShadow(BufferedImage source) { 177796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int type = source.getType(); 178796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta if (type == BufferedImage.TYPE_CUSTOM) { 179796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta type = BufferedImage.TYPE_INT_ARGB; 180796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 181796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 182796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int width = source.getWidth(); 183796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int height = source.getHeight(); 184796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta BufferedImage image; 185796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta image = new BufferedImage(width + SHADOW_SIZE, height + SHADOW_SIZE, type); 186796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta Graphics2D g = image.createGraphics(); 187796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta g.drawImage(source, 0, 0, null); 188796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta drawRectangleShadow(image, 0, 0, width, height); 189796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta g.dispose(); 190796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 191796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta return image; 192796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 193796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 194796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 195796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Draws a small rectangular drop shadow (of size {@link #SMALL_SHADOW_SIZE} by {@link 196796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * #SMALL_SHADOW_SIZE} around the given source and returns a new image with both combined 197796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 198796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param source the source image 199796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 200796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @return the source image with a drop shadow on the bottom and right 201796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 202796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta @SuppressWarnings("UnusedDeclaration") 203796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static BufferedImage createSmallRectangularDropShadow(BufferedImage source) { 204796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int type = source.getType(); 205796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta if (type == BufferedImage.TYPE_CUSTOM) { 206796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta type = BufferedImage.TYPE_INT_ARGB; 207796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 208796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 209796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int width = source.getWidth(); 210796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int height = source.getHeight(); 211796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 212796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta BufferedImage image; 213796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta image = new BufferedImage(width + SMALL_SHADOW_SIZE, height + SMALL_SHADOW_SIZE, type); 214796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 215796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta Graphics2D g = image.createGraphics(); 216796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta g.drawImage(source, 0, 0, null); 217796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta drawSmallRectangleShadow(image, 0, 0, width, height); 218796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta g.dispose(); 219796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 220796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta return image; 221796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 222796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 223796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 224796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Draws a drop shadow for the given rectangle into the given context. It will not draw anything 225796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * if the rectangle is smaller than a minimum determined by the assets used to draw the shadow 226796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * graphics. The size of the shadow is {@link #SHADOW_SIZE}. 227796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 228796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param image the image to draw the shadow into 229796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param x the left coordinate of the left hand side of the rectangle 230796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param y the top coordinate of the top of the rectangle 231796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param width the width of the rectangle 232796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param height the height of the rectangle 233796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 234796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static void drawRectangleShadow(BufferedImage image, 235796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int x, int y, int width, int height) { 236796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta Graphics2D gc = image.createGraphics(); 237796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta try { 238796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta drawRectangleShadow(gc, x, y, width, height); 239796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } finally { 240796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.dispose(); 241796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 242796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 243796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 244796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 245796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Draws a small drop shadow for the given rectangle into the given context. It will not draw 246796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * anything if the rectangle is smaller than a minimum determined by the assets used to draw the 247796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * shadow graphics. The size of the shadow is {@link #SMALL_SHADOW_SIZE}. 248796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 249796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param image the image to draw the shadow into 250796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param x the left coordinate of the left hand side of the rectangle 251796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param y the top coordinate of the top of the rectangle 252796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param width the width of the rectangle 253796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param height the height of the rectangle 254796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 255796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static void drawSmallRectangleShadow(BufferedImage image, 256796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int x, int y, int width, int height) { 257796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta Graphics2D gc = image.createGraphics(); 258796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta try { 259796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta drawSmallRectangleShadow(gc, x, y, width, height); 260796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } finally { 261796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.dispose(); 262796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 263796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 264796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 265796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 266796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * The width and height of the drop shadow painted by 267796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * {@link #drawRectangleShadow(Graphics2D, int, int, int, int)} 268796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 269796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static final int SHADOW_SIZE = 20; // DO NOT EDIT. This corresponds to bitmap graphics 270796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 271796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 272796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * The width and height of the drop shadow painted by 273796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * {@link #drawSmallRectangleShadow(Graphics2D, int, int, int, int)} 274796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 275796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static final int SMALL_SHADOW_SIZE = 10; // DO NOT EDIT. Corresponds to bitmap graphics 276796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 277796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 278796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Draws a drop shadow for the given rectangle into the given context. It will not draw anything 279796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * if the rectangle is smaller than a minimum determined by the assets used to draw the shadow 280796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * graphics. 281796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 282796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param gc the graphics context to draw into 283796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param x the left coordinate of the left hand side of the rectangle 284796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param y the top coordinate of the top of the rectangle 285796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param width the width of the rectangle 286796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param height the height of the rectangle 287796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 288796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static void drawRectangleShadow(Graphics2D gc, int x, int y, int width, int height) { 289796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta assert ShadowBottomLeft != null; 290796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta assert ShadowBottomRight.getWidth(null) == SHADOW_SIZE; 291796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta assert ShadowBottomRight.getHeight(null) == SHADOW_SIZE; 292796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 293796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int blWidth = ShadowBottomLeft.getWidth(null); 294796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int trHeight = ShadowTopRight.getHeight(null); 295796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta if (width < blWidth) { 296796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta return; 297796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 298796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta if (height < trHeight) { 299796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta return; 300796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 301796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 302796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(ShadowBottomLeft, x - ShadowBottomLeft.getWidth(null), y + height, null); 303796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(ShadowBottomRight, x + width, y + height, null); 304796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(ShadowTopRight, x + width, y, null); 305796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(ShadowTopLeft, x - ShadowTopLeft.getWidth(null), y, null); 306796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(ShadowBottom, 307796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta x, y + height, x + width, y + height + ShadowBottom.getHeight(null), 308796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 0, 0, ShadowBottom.getWidth(null), ShadowBottom.getHeight(null), null); 309796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(ShadowRight, 310796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta x + width, y + ShadowTopRight.getHeight(null), x + width + ShadowRight.getWidth(null), y + height, 311796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 0, 0, ShadowRight.getWidth(null), ShadowRight.getHeight(null), null); 312796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(ShadowLeft, 313796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta x - ShadowLeft.getWidth(null), y + ShadowTopLeft.getHeight(null), x, y + height, 314796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 0, 0, ShadowLeft.getWidth(null), ShadowLeft.getHeight(null), null); 315796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 316796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 317796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta /** 318796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * Draws a small drop shadow for the given rectangle into the given context. It will not draw 319796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * anything if the rectangle is smaller than a minimum determined by the assets used to draw the 320796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * shadow graphics. 321796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * <p/> 322796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * 323796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param gc the graphics context to draw into 324796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param x the left coordinate of the left hand side of the rectangle 325796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param y the top coordinate of the top of the rectangle 326796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param width the width of the rectangle 327796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta * @param height the height of the rectangle 328796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta */ 329796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta public static void drawSmallRectangleShadow(Graphics2D gc, int x, int y, int width, 330796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int height) { 331796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta assert Shadow2BottomLeft != null; 332796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta assert Shadow2TopRight != null; 333796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta assert Shadow2BottomRight.getWidth(null) == SMALL_SHADOW_SIZE; 334796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta assert Shadow2BottomRight.getHeight(null) == SMALL_SHADOW_SIZE; 335796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 336796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int blWidth = Shadow2BottomLeft.getWidth(null); 337796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta int trHeight = Shadow2TopRight.getHeight(null); 338796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta if (width < blWidth) { 339796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta return; 340796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 341796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta if (height < trHeight) { 342796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta return; 343796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 344796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 345796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(Shadow2BottomLeft, x - Shadow2BottomLeft.getWidth(null), y + height, null); 346796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(Shadow2BottomRight, x + width, y + height, null); 347796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(Shadow2TopRight, x + width, y, null); 348796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(Shadow2TopLeft, x - Shadow2TopLeft.getWidth(null), y, null); 349796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(Shadow2Bottom, 350796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta x, y + height, x + width, y + height + Shadow2Bottom.getHeight(null), 351796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 0, 0, Shadow2Bottom.getWidth(null), Shadow2Bottom.getHeight(null), null); 352796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(Shadow2Right, 353796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta x + width, y + Shadow2TopRight.getHeight(null), x + width + Shadow2Right.getWidth(null), y + height, 354796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 0, 0, Shadow2Right.getWidth(null), Shadow2Right.getHeight(null), null); 355796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta gc.drawImage(Shadow2Left, 356796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta x - Shadow2Left.getWidth(null), y + Shadow2TopLeft.getHeight(null), x, y + height, 357796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 0, 0, Shadow2Left.getWidth(null), Shadow2Left.getHeight(null), null); 358796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 359796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 360796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static Image loadIcon(String name) { 361796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta InputStream inputStream = ShadowPainter.class.getResourceAsStream(name); 362796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta if (inputStream == null) { 363796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta throw new RuntimeException("Unable to load image for shadow: " + name); 364796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 365796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta try { 366796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta return ImageIO.read(inputStream); 367796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } catch (IOException e) { 368796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta throw new RuntimeException("Unable to load image for shadow:" + name, e); 369796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } finally { 370796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta try { 371796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta inputStream.close(); 372796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } catch (IOException e) { 373796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // ignore. 374796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 375796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 376796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta } 377796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 378796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // Shadow graphics. This was generated by creating a drop shadow in 379796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // Gimp, using the parameters x offset=10, y offset=10, blur radius=10, 380796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // (for the small drop shadows x offset=10, y offset=10, blur radius=10) 381796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // color=black, and opacity=51. These values attempt to make a shadow 382796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // that is legible both for dark and light themes, on top of the 383796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // canvas background (rgb(150,150,150). Darker shadows would tend to 384796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // blend into the foreground for a dark holo screen, and lighter shadows 385796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // would be hard to spot on the canvas background. If you make adjustments, 386796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // make sure to check the shadow with both dark and light themes. 387796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // 388796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // After making the graphics, I cut out the top right, bottom left 389796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // and bottom right corners as 20x20 images, and these are reproduced by 390796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // painting them in the corresponding places in the target graphics context. 391796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // I then grabbed a single horizontal gradient line from the middle of the 392796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // right edge,and a single vertical gradient line from the bottom. These 393796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // are then painted scaled/stretched in the target to fill the gaps between 394796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // the three corner images. 395796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // 396796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // Filenames: bl=bottom left, b=bottom, br=bottom right, r=right, tr=top right 397796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 398796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // Normal Drop Shadow 399796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image ShadowBottom = loadIcon("/icons/shadow-b.png"); 400796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image ShadowBottomLeft = loadIcon("/icons/shadow-bl.png"); 401796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image ShadowBottomRight = loadIcon("/icons/shadow-br.png"); 402796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image ShadowRight = loadIcon("/icons/shadow-r.png"); 403796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image ShadowTopRight = loadIcon("/icons/shadow-tr.png"); 404796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image ShadowTopLeft = loadIcon("/icons/shadow-tl.png"); 405796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image ShadowLeft = loadIcon("/icons/shadow-l.png"); 406796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta 407796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta // Small Drop Shadow 408796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image Shadow2Bottom = loadIcon("/icons/shadow2-b.png"); 409796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image Shadow2BottomLeft = loadIcon("/icons/shadow2-bl.png"); 410796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image Shadow2BottomRight = loadIcon("/icons/shadow2-br.png"); 411796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image Shadow2Right = loadIcon("/icons/shadow2-r.png"); 412796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image Shadow2TopRight = loadIcon("/icons/shadow2-tr.png"); 413796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image Shadow2TopLeft = loadIcon("/icons/shadow2-tl.png"); 414796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta private static final Image Shadow2Left = loadIcon("/icons/shadow2-l.png"); 415796e9b7f9910f2ba8133cdb6f137107585b2e5faDeepanshu Gupta} 416