diff options
author | Xavier Ducrohet <xav@android.com> | 2011-07-27 16:31:18 -0700 |
---|---|---|
committer | Android Code Review <code-review@android.com> | 2011-07-27 16:31:18 -0700 |
commit | c766a5e884fbb9a3a4f02809961942173c7cce8b (patch) | |
tree | d7c5dd610a5ee57c2768209eb1a71f9fee4c5d9b | |
parent | de230467f03fb816461b057e51c54364899cdab6 (diff) | |
parent | a7a3436d2d987c63116e7d5ab7501f4c24da9bf1 (diff) | |
download | sdk-c766a5e884fbb9a3a4f02809961942173c7cce8b.zip sdk-c766a5e884fbb9a3a4f02809961942173c7cce8b.tar.gz sdk-c766a5e884fbb9a3a4f02809961942173c7cce8b.tar.bz2 |
Merge "Initial commit for the Asset Studio library in the SDK"
55 files changed, 714 insertions, 0 deletions
diff --git a/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/GraphicGenerator.java b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/GraphicGenerator.java new file mode 100644 index 0000000..25f7039 --- /dev/null +++ b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/GraphicGenerator.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.assetstudiolib; + +/** + * The base Generator class. + */ +public class GraphicGenerator { + /** + * Options used for all generators. + */ + public static class Options { + /** + * The screen density of the icon. + */ + public static enum Density { + LDPI("ldpi", 120), MDPI("mdpi", 160), HDPI("hdpi", 240), XHDPI("xhdpi", 320); + + public String id; + public int dpi; + + Density(String id, int dpi) { + this.id = id; + this.dpi = dpi; + } + + public float scaleFactor() { + return (float) this.dpi / 160; + } + } + } +} diff --git a/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/GraphicGeneratorContext.java b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/GraphicGeneratorContext.java new file mode 100644 index 0000000..e0b00a6 --- /dev/null +++ b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/GraphicGeneratorContext.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.assetstudiolib; + +import java.awt.image.BufferedImage; + +/** + * The context used during graphic generation. + */ +public interface GraphicGeneratorContext { + /** + * Loads the given image resource, as requested by the graphic generator. + * + * @param path The path to the resource, relative to the general "resources" path, as defined by + * the context implementor. + * @return The loaded image resource, or null if there was an error. + */ + public BufferedImage loadImageResource(String path); +} diff --git a/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/LauncherIconGenerator.java b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/LauncherIconGenerator.java new file mode 100644 index 0000000..e9cc65b --- /dev/null +++ b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/LauncherIconGenerator.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.assetstudiolib; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; + +/** + * A {@link GraphicGenerator} that generates Android "launcher" icons. + */ +public class LauncherIconGenerator extends GraphicGenerator { + private static final Rectangle BASE_IMAGE_RECT = new Rectangle(0, 0, 48, 48); + private static final Rectangle BASE_TARGET_RECT = new Rectangle(4, 4, 40, 40); + + private Options mOptions; + private BufferedImage mBackImage; + private BufferedImage mMaskImage; + private BufferedImage mForeImage; + + public LauncherIconGenerator(GraphicGeneratorContext context, Options options) { + mOptions = options; + mBackImage = context.loadImageResource("launcher-stencil/" + + options.shape.id + "/" + options.density.id + "/back.png"); + mForeImage = context.loadImageResource("launcher-stencil/" + + options.shape.id + "/" + options.density.id + "/" + options.style.id + ".png"); + mMaskImage = context.loadImageResource("launcher-stencil/" + + options.shape.id + "/" + options.density.id + "/mask.png"); + } + + public BufferedImage generate() { + final float scaleFactor = mOptions.density.scaleFactor(); + Rectangle imageRect = Util.scaleRectangle(BASE_IMAGE_RECT, scaleFactor); + Rectangle targetRect = Util.scaleRectangle(BASE_TARGET_RECT, scaleFactor); + + BufferedImage outImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height); + Graphics2D g = (Graphics2D) outImage.getGraphics(); + g.drawImage(mBackImage, 0, 0, null); + + { + BufferedImage tempImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height); + Graphics2D g2 = (Graphics2D) tempImage.getGraphics(); + g2.drawImage(mMaskImage, 0, 0, null); + g2.setComposite(AlphaComposite.SrcAtop); + g2.setPaint(new Color(mOptions.backgroundColor)); + g2.fillRect(0, 0, imageRect.width, imageRect.height); + + if (mOptions.crop) { + Util.drawCenterCrop(g2, mOptions.sourceImage, targetRect); + } else { + Util.drawCenterInside(g2, mOptions.sourceImage, targetRect); + } + + g.drawImage(tempImage, 0, 0, null); + } + + g.drawImage(mForeImage, 0, 0, null); + return outImage; + } + + public static class Options { + public BufferedImage sourceImage; + public int backgroundColor = 0; + public boolean crop = true; + public Shape shape = Shape.SQUARE; + public Style style = Style.SIMPLE; + public GraphicGenerator.Options.Density density = GraphicGenerator.Options.Density.XHDPI; + + public static enum Shape { + CIRCLE("circle"), SQUARE("square"); + + public String id; + + Shape(String id) { + this.id = id; + } + } + + public static enum Style { + SIMPLE("fore1"), FANCY("fore2"), GLOSSY("fore3"); + + public String id; + + Style(String id) { + this.id = id; + } + } + } +} diff --git a/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/MenuIconGenerator.java b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/MenuIconGenerator.java new file mode 100644 index 0000000..bff6e42 --- /dev/null +++ b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/MenuIconGenerator.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.assetstudiolib; + +import java.awt.Color; +import java.awt.GradientPaint; +import java.awt.Graphics2D; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; + +/** + * A {@link GraphicGenerator} that generates Android "menu" icons. + */ +public class MenuIconGenerator extends GraphicGenerator { + private static final Rectangle BASE_IMAGE_RECT = new Rectangle(0, 0, 48, 48); + private static final Rectangle BASE_TARGET_RECT = new Rectangle(8, 8, 32, 32); + + private Options mOptions; + + public MenuIconGenerator(GraphicGeneratorContext context, Options options) { + mOptions = options; + } + + public BufferedImage generate() { + final float scaleFactor = mOptions.density.scaleFactor(); + Rectangle imageRect = Util.scaleRectangle(BASE_IMAGE_RECT, scaleFactor); + Rectangle targetRect = Util.scaleRectangle(BASE_TARGET_RECT, scaleFactor); + + BufferedImage outImage = Util.newArgbBufferedImage(imageRect.width, imageRect.height); + Graphics2D g = (Graphics2D) outImage.getGraphics(); + + { + BufferedImage tempImage = Util.newArgbBufferedImage( + imageRect.width, imageRect.height); + Graphics2D g2 = (Graphics2D) tempImage.getGraphics(); + Util.drawCenterInside(g2, mOptions.sourceImage, targetRect); + + Util.drawEffects(g, tempImage, 0, 0, new Util.Effect[]{ + new Util.FillEffect( + new GradientPaint( + 0, 0, + new Color(0xa3a3a3), + 0, imageRect.height, + new Color(0x787878))), + new Util.ShadowEffect( + 0, + 3 * scaleFactor, + 3 * scaleFactor, + Color.black, + 0.2, + true), + new Util.ShadowEffect( + 0, + 1, + 0, + Color.black, + 0.35, + true), + new Util.ShadowEffect( + 0, + -1, + 0, + Color.white, + 0.35, + true), + }); + } + + return outImage; + } + + public static class Options { + public BufferedImage sourceImage; + public GraphicGenerator.Options.Density density = GraphicGenerator.Options.Density.XHDPI; + } +} diff --git a/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/Util.java b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/Util.java new file mode 100644 index 0000000..82299a4 --- /dev/null +++ b/assetstudio/libs/assetstudiolib/src/com/android/assetstudiolib/Util.java @@ -0,0 +1,440 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.assetstudiolib; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Paint; +import java.awt.Rectangle; +import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; +import java.awt.image.ConvolveOp; +import java.awt.image.Kernel; +import java.awt.image.Raster; +import java.awt.image.RescaleOp; +import java.util.ArrayList; +import java.util.List; + +/** + * A set of utility classes for manipulating {@link BufferedImage} objects and drawing them to + * {@link Graphics2D} canvases. + */ +public class Util { + /** + * Scales the given rectangle by the given scale factor. + * + * @param rect The rectangle to scale. + * @param scaleFactor The factor to scale by. + * @return The scaled rectangle. + */ + public static Rectangle scaleRectangle(Rectangle rect, float scaleFactor) { + return new Rectangle( + (int) (rect.x * scaleFactor), + (int) (rect.y * scaleFactor), + (int) (rect.width * scaleFactor), + (int) (rect.height * scaleFactor)); + } + + /** + * Creates a new ARGB {@link BufferedImage} of the given width and height. + * + * @param width The width of the new image. + * @param height The height of the new image. + * @return The newly created image. + */ + public static BufferedImage newArgbBufferedImage(int width, int height) { + return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + } + + /** + * Smoothly scales the given {@link BufferedImage} to the given width and height using the + * {@link Image#SCALE_SMOOTH} algorithm (generally bicubic resampling or bilinear filtering). + * + * @param source The source image. + * @param width The destination width to scale to. + * @param height The destination height to scale to. + * @return A new, scaled image. + */ + public static BufferedImage scaledImage(BufferedImage source, int width, int height) { + Image scaledImage = source.getScaledInstance(width, height, Image.SCALE_SMOOTH); + BufferedImage scaledBufImage = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + Graphics g = scaledBufImage.createGraphics(); + g.drawImage(scaledImage, 0, 0, null); + g.dispose(); + return scaledBufImage; + } + + /** + * Applies a gaussion blur of the given radius to the given {@link BufferedImage} using a kernel + * convolution. + * + * @param source The source image. + * @param radius The blur radius, in pixels. + * @return A new, blurred image, or the source image if no blur is performed. + */ + public static BufferedImage blurredImage(BufferedImage source, double radius) { + if (radius == 0) { + return source; + } + + final int r = (int) Math.ceil(radius); + final int rows = r * 2 + 1; + final float[] kernelData = new float[rows * rows]; + + final double sigma = radius / 3; + final double sigma22 = 2 * sigma * sigma; + final double sqrtPiSigma22 = Math.sqrt(Math.PI * sigma22); + final double radius2 = radius * radius; + + double total = 0; + int index = 0; + double distance2; + + int x, y; + for (y = -r; y <= r; y++) { + for (x = -r; x <= r; x++) { + distance2 = 1.0 * x * x + 1.0 * y * y; + if (distance2 > radius2) { + kernelData[index] = 0; + } else { + kernelData[index] = (float) (Math.exp(-distance2 / sigma22) / sqrtPiSigma22); + } + total += kernelData[index]; + ++index; + } + } + + for (index = 0; index < kernelData.length; index++) { + kernelData[index] /= total; + } + + // We first pad the image so the kernel can operate at the edges. + BufferedImage paddedSource = paddedImage(source, r); + BufferedImage blurredPaddedImage = operatedImage(paddedSource, new ConvolveOp( + new Kernel(rows, rows, kernelData), ConvolveOp.EDGE_ZERO_FILL, null)); + return blurredPaddedImage.getSubimage(r, r, source.getWidth(), source.getHeight()); + } + + /** + * Inverts the alpha channel of the given {@link BufferedImage}. RGB data for the inverted area + * are undefined, so it's generally best to fill the resulting image with a color. + * + * @param source The source image. + * @return A new image with an alpha channel inverted from the original. + */ + public static BufferedImage invertedAlphaImage(BufferedImage source) { + final float[] scaleFactors = new float[]{1, 1, 1, -1}; + final float[] offsets = new float[]{0, 0, 0, 255}; + + return operatedImage(source, new RescaleOp(scaleFactors, offsets, null)); + } + + /** + * Applies a {@link BufferedImageOp} on the given {@link BufferedImage}. + * + * @param source The source image. + * @param op The operation to perform. + * @return A new image with the operation performed. + */ + public static BufferedImage operatedImage(BufferedImage source, BufferedImageOp op) { + BufferedImage newImage = newArgbBufferedImage(source.getWidth(), source.getHeight()); + Graphics2D g = (Graphics2D) newImage.getGraphics(); + g.drawImage(source, op, 0, 0); + return newImage; + } + + /** + * Fills the given {@link BufferedImage} with a {@link Paint}, preserving its alpha channel. + * + * @param source The source image. + * @param paint The paint to fill with. + * @return A new, painted/filled image. + */ + public static BufferedImage filledImage(BufferedImage source, Paint paint) { + BufferedImage newImage = newArgbBufferedImage(source.getWidth(), source.getHeight()); + Graphics2D g = (Graphics2D) newImage.getGraphics(); + g.drawImage(source, 0, 0, null); + g.setComposite(AlphaComposite.SrcAtop); + g.setPaint(paint); + g.fillRect(0, 0, source.getWidth(), source.getHeight()); + return newImage; + } + + /** + * Pads the given {@link BufferedImage} on all sides by the given padding amount. + * + * @param source The source image. + * @param padding The amount to pad on all sides, in pixels. + * @return A new, padded image, or the source image if no padding is performed. + */ + public static BufferedImage paddedImage(BufferedImage source, int padding) { + if (padding == 0) { + return source; + } + + BufferedImage newImage = newArgbBufferedImage( + source.getWidth() + padding * 2, source.getHeight() + padding * 2); + Graphics2D g = (Graphics2D) newImage.getGraphics(); + g.drawImage(source, padding, padding, null); + return newImage; + } + + /** + * Trims the transparent pixels from the given {@link BufferedImage} (returns a sub-image). + * + * @param source The source image. + * @return A new, trimmed image, or the source image if no trim is performed. + */ + public static BufferedImage trimmedImage(BufferedImage source) { + final int minAlpha = 1; + final int srcWidth = source.getWidth(); + final int srcHeight = source.getHeight(); + Raster raster = source.getRaster(); + int l = srcWidth, t = srcHeight, r = 0, b = 0; + + int alpha, x, y; + int[] pixel = new int[4]; + for (y = 0; y < srcHeight; y++) { + for (x = 0; x < srcWidth; x++) { + raster.getPixel(x, y, pixel); + alpha = pixel[3]; + if (alpha >= minAlpha) { + l = Math.min(x, l); + t = Math.min(y, t); + r = Math.max(x, r); + b = Math.max(y, b); + } + } + } + + if (l > r || t > b) { + // No pixels, couldn't trim + return source; + } + + return source.getSubimage(l, t, r - l + 1, b - t + 1); + } + + /** + * Draws the given {@link BufferedImage} to the canvas, at the given coordinates, with the given + * {@link Effect}s applied. Note that drawn effects may be outside the bounds of the source + * image. + * + * @param g The destination canvas. + * @param source The source image. + * @param x The x offset at which to draw the image. + * @param y The y offset at which to draw the image. + * @param effects The list of effects to apply. + */ + public static void drawEffects(Graphics2D g, BufferedImage source, int x, int y, + Effect[] effects) { + List<ShadowEffect> shadowEffects = new ArrayList<ShadowEffect>(); + List<FillEffect> fillEffects = new ArrayList<FillEffect>(); + + for (Effect effect : effects) { + if (effect instanceof ShadowEffect) { + shadowEffects.add((ShadowEffect) effect); + } else if (effect instanceof FillEffect) { + fillEffects.add((FillEffect) effect); + } + } + + Composite oldComposite = g.getComposite(); + for (ShadowEffect effect : shadowEffects) { + if (effect.inner) { + continue; + } + + // Outer shadow + g.setComposite(AlphaComposite.getInstance( + AlphaComposite.SRC_OVER, (float) effect.opacity)); + g.drawImage( + filledImage( + blurredImage(source, effect.radius), + effect.color), + (int) effect.xOffset, (int) effect.yOffset, null); + } + g.setComposite(oldComposite); + + // Inner shadow & fill effects. + final Rectangle imageRect = new Rectangle(0, 0, source.getWidth(), source.getHeight()); + BufferedImage out = newArgbBufferedImage(imageRect.width, imageRect.height); + Graphics2D g2 = (Graphics2D) out.getGraphics(); + + g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); + g2.drawImage(source, 0, 0, null); + g2.setComposite(AlphaComposite.SrcAtop); + + // Gradient fill + for (FillEffect effect : fillEffects) { + g2.setPaint(effect.paint); + g2.fillRect(0, 0, imageRect.width, imageRect.height); + } + + // Inner shadows + for (ShadowEffect effect : shadowEffects) { + if (!effect.inner) { + continue; + } + + BufferedImage innerShadowImage = newArgbBufferedImage( + imageRect.width, imageRect.height); + Graphics2D g3 = (Graphics2D) innerShadowImage.getGraphics(); + g3.drawImage(source, (int) effect.xOffset, (int) effect.yOffset, null); + g2.setComposite(AlphaComposite.getInstance( + AlphaComposite.SRC_ATOP, (float) effect.opacity)); + g2.drawImage( + filledImage( + blurredImage(invertedAlphaImage(innerShadowImage), effect.radius), + effect.color), + 0, 0, null); + } + + g.drawImage(out, x, y, null); + } + + /** + * Draws the given {@link BufferedImage} to the canvas, centered, wholly contained within the + * bounds defined by the destination rectangle, and with preserved aspect ratio. + * + * @param g The destination canvas. + * @param source The source image. + * @param dstRect The destination rectangle in the destination canvas into which to draw the + * image. + */ + public static void drawCenterInside(Graphics2D g, BufferedImage source, Rectangle dstRect) { + final int srcWidth = source.getWidth(); + final int srcHeight = source.getHeight(); + if (srcWidth * 1.0 / srcHeight > dstRect.width * 1.0 / dstRect.height) { + final int scaledWidth = dstRect.width; + final int scaledHeight = dstRect.width * srcHeight / srcWidth; + Image scaledImage = scaledImage(source, scaledWidth, scaledHeight); + g.drawImage(scaledImage, + dstRect.x, + dstRect.y + (dstRect.height - scaledHeight) / 2, + dstRect.x + dstRect.width, + dstRect.y + (dstRect.height - scaledHeight) / 2 + scaledHeight, + 0, + 0, + 0 + scaledWidth, + 0 + scaledHeight, + null); + } else { + final int scaledWidth = dstRect.height * srcWidth / srcHeight; + final int scaledHeight = dstRect.height; + Image scaledImage = scaledImage(source, scaledWidth, scaledHeight); + g.drawImage(scaledImage, + dstRect.x + (dstRect.width - scaledWidth) / 2, + dstRect.y, + dstRect.x + (dstRect.width - scaledWidth) / 2 + scaledWidth, + dstRect.y + dstRect.height, + 0, + 0, + 0 + scaledWidth, + 0 + scaledHeight, + null); + } + } + + /** + * Draws the given {@link BufferedImage} to the canvas, centered and cropped to fill the + * bounds defined by the destination rectangle, and with preserved aspect ratio. + * + * @param g The destination canvas. + * @param source The source image. + * @param dstRect The destination rectangle in the destination canvas into which to draw the + * image. + */ + public static void drawCenterCrop(Graphics2D g, BufferedImage source, Rectangle dstRect) { + final int srcWidth = source.getWidth(); + final int srcHeight = source.getHeight(); + if (srcWidth * 1.0 / srcHeight > dstRect.width * 1.0 / dstRect.height) { + final int scaledWidth = dstRect.height * srcWidth / srcHeight; + final int scaledHeight = dstRect.height; + Image scaledImage = scaledImage(source, scaledWidth, scaledHeight); + g.drawImage(scaledImage, + dstRect.x, + dstRect.y, + dstRect.x + dstRect.width, + dstRect.y + dstRect.height, + 0 + (scaledWidth - dstRect.width) / 2, + 0, + 0 + (scaledWidth - dstRect.width) / 2 + dstRect.width, + 0 + dstRect.height, + null); + } else { + final int scaledWidth = dstRect.width; + final int scaledHeight = dstRect.width * srcHeight / srcWidth; + Image scaledImage = scaledImage(source, scaledWidth, scaledHeight); + g.drawImage(scaledImage, + dstRect.x, + dstRect.y, + dstRect.x + dstRect.width, + dstRect.y + dstRect.height, + 0, + 0 + (scaledHeight - dstRect.height) / 2, + 0 + dstRect.width, + 0 + (scaledHeight - dstRect.height) / 2 + dstRect.height, + null); + } + } + + /** + * An effect to apply in + * {@link Util#drawEffects(java.awt.Graphics2D, java.awt.image.BufferedImage, int, int, Util.Effect[])} + */ + public static abstract class Effect { + } + + /** + * An inner or outer shadow. + */ + public static class ShadowEffect extends Effect { + public double xOffset; + public double yOffset; + public double radius; + public Color color; + public double opacity; + public boolean inner; + + public ShadowEffect(double xOffset, double yOffset, double radius, Color color, + double opacity, boolean inner) { + this.xOffset = xOffset; + this.yOffset = yOffset; + this.radius = radius; + this.color = color; + this.opacity = opacity; + this.inner = inner; + } + } + + /** + * A fill, defined by a paint. + */ + public static class FillEffect extends Effect { + public Paint paint; + + public FillEffect(Paint paint) { + this.paint = paint; + } + } +} diff --git a/assetstudio/res/launcher-stencil/circle/hdpi/back.png b/assetstudio/res/launcher-stencil/circle/hdpi/back.png Binary files differnew file mode 100644 index 0000000..8e3dbc1 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/hdpi/back.png diff --git a/assetstudio/res/launcher-stencil/circle/hdpi/fore1.png b/assetstudio/res/launcher-stencil/circle/hdpi/fore1.png Binary files differnew file mode 100644 index 0000000..79d75c0 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/hdpi/fore1.png diff --git a/assetstudio/res/launcher-stencil/circle/hdpi/fore2.png b/assetstudio/res/launcher-stencil/circle/hdpi/fore2.png Binary files differnew file mode 100644 index 0000000..594257a --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/hdpi/fore2.png diff --git a/assetstudio/res/launcher-stencil/circle/hdpi/fore3.png b/assetstudio/res/launcher-stencil/circle/hdpi/fore3.png Binary files differnew file mode 100644 index 0000000..65fb48b --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/hdpi/fore3.png diff --git a/assetstudio/res/launcher-stencil/circle/hdpi/mask.png b/assetstudio/res/launcher-stencil/circle/hdpi/mask.png Binary files differnew file mode 100644 index 0000000..99e787a --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/hdpi/mask.png diff --git a/assetstudio/res/launcher-stencil/circle/ldpi/back.png b/assetstudio/res/launcher-stencil/circle/ldpi/back.png Binary files differnew file mode 100644 index 0000000..d9a9fcc --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/ldpi/back.png diff --git a/assetstudio/res/launcher-stencil/circle/ldpi/fore1.png b/assetstudio/res/launcher-stencil/circle/ldpi/fore1.png Binary files differnew file mode 100644 index 0000000..ecc3bc5 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/ldpi/fore1.png diff --git a/assetstudio/res/launcher-stencil/circle/ldpi/fore2.png b/assetstudio/res/launcher-stencil/circle/ldpi/fore2.png Binary files differnew file mode 100644 index 0000000..c86b59c --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/ldpi/fore2.png diff --git a/assetstudio/res/launcher-stencil/circle/ldpi/fore3.png b/assetstudio/res/launcher-stencil/circle/ldpi/fore3.png Binary files differnew file mode 100644 index 0000000..1ae4d31 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/ldpi/fore3.png diff --git a/assetstudio/res/launcher-stencil/circle/ldpi/mask.png b/assetstudio/res/launcher-stencil/circle/ldpi/mask.png Binary files differnew file mode 100644 index 0000000..e537ad0 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/ldpi/mask.png diff --git a/assetstudio/res/launcher-stencil/circle/mdpi/back.png b/assetstudio/res/launcher-stencil/circle/mdpi/back.png Binary files differnew file mode 100644 index 0000000..e165038 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/mdpi/back.png diff --git a/assetstudio/res/launcher-stencil/circle/mdpi/fore1.png b/assetstudio/res/launcher-stencil/circle/mdpi/fore1.png Binary files differnew file mode 100644 index 0000000..c42af13 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/mdpi/fore1.png diff --git a/assetstudio/res/launcher-stencil/circle/mdpi/fore2.png b/assetstudio/res/launcher-stencil/circle/mdpi/fore2.png Binary files differnew file mode 100644 index 0000000..0c06821 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/mdpi/fore2.png diff --git a/assetstudio/res/launcher-stencil/circle/mdpi/fore3.png b/assetstudio/res/launcher-stencil/circle/mdpi/fore3.png Binary files differnew file mode 100644 index 0000000..01fe418 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/mdpi/fore3.png diff --git a/assetstudio/res/launcher-stencil/circle/mdpi/mask.png b/assetstudio/res/launcher-stencil/circle/mdpi/mask.png Binary files differnew file mode 100644 index 0000000..19f18bf --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/mdpi/mask.png diff --git a/assetstudio/res/launcher-stencil/circle/web/back.png b/assetstudio/res/launcher-stencil/circle/web/back.png Binary files differnew file mode 100644 index 0000000..191c677 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/web/back.png diff --git a/assetstudio/res/launcher-stencil/circle/web/fore1.png b/assetstudio/res/launcher-stencil/circle/web/fore1.png Binary files differnew file mode 100644 index 0000000..7ea8096 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/web/fore1.png diff --git a/assetstudio/res/launcher-stencil/circle/web/fore2.png b/assetstudio/res/launcher-stencil/circle/web/fore2.png Binary files differnew file mode 100644 index 0000000..5a76240 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/web/fore2.png diff --git a/assetstudio/res/launcher-stencil/circle/web/fore3.png b/assetstudio/res/launcher-stencil/circle/web/fore3.png Binary files differnew file mode 100644 index 0000000..1794bff --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/web/fore3.png diff --git a/assetstudio/res/launcher-stencil/circle/web/mask.png b/assetstudio/res/launcher-stencil/circle/web/mask.png Binary files differnew file mode 100644 index 0000000..8316d80 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/web/mask.png diff --git a/assetstudio/res/launcher-stencil/circle/xhdpi/back.png b/assetstudio/res/launcher-stencil/circle/xhdpi/back.png Binary files differnew file mode 100644 index 0000000..e655af6 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/xhdpi/back.png diff --git a/assetstudio/res/launcher-stencil/circle/xhdpi/fore1.png b/assetstudio/res/launcher-stencil/circle/xhdpi/fore1.png Binary files differnew file mode 100644 index 0000000..639ccba --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/xhdpi/fore1.png diff --git a/assetstudio/res/launcher-stencil/circle/xhdpi/fore2.png b/assetstudio/res/launcher-stencil/circle/xhdpi/fore2.png Binary files differnew file mode 100644 index 0000000..b922452 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/xhdpi/fore2.png diff --git a/assetstudio/res/launcher-stencil/circle/xhdpi/fore3.png b/assetstudio/res/launcher-stencil/circle/xhdpi/fore3.png Binary files differnew file mode 100644 index 0000000..5f1c15e --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/xhdpi/fore3.png diff --git a/assetstudio/res/launcher-stencil/circle/xhdpi/mask.png b/assetstudio/res/launcher-stencil/circle/xhdpi/mask.png Binary files differnew file mode 100644 index 0000000..6dc3bc7 --- /dev/null +++ b/assetstudio/res/launcher-stencil/circle/xhdpi/mask.png diff --git a/assetstudio/res/launcher-stencil/square/hdpi/back.png b/assetstudio/res/launcher-stencil/square/hdpi/back.png Binary files differnew file mode 100644 index 0000000..3e58211 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/hdpi/back.png diff --git a/assetstudio/res/launcher-stencil/square/hdpi/fore1.png b/assetstudio/res/launcher-stencil/square/hdpi/fore1.png Binary files differnew file mode 100644 index 0000000..e76d493 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/hdpi/fore1.png diff --git a/assetstudio/res/launcher-stencil/square/hdpi/fore2.png b/assetstudio/res/launcher-stencil/square/hdpi/fore2.png Binary files differnew file mode 100644 index 0000000..ab28d8d --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/hdpi/fore2.png diff --git a/assetstudio/res/launcher-stencil/square/hdpi/fore3.png b/assetstudio/res/launcher-stencil/square/hdpi/fore3.png Binary files differnew file mode 100644 index 0000000..59f5e8f --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/hdpi/fore3.png diff --git a/assetstudio/res/launcher-stencil/square/hdpi/mask.png b/assetstudio/res/launcher-stencil/square/hdpi/mask.png Binary files differnew file mode 100644 index 0000000..9c56fe6 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/hdpi/mask.png diff --git a/assetstudio/res/launcher-stencil/square/ldpi/back.png b/assetstudio/res/launcher-stencil/square/ldpi/back.png Binary files differnew file mode 100644 index 0000000..1a68be3 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/ldpi/back.png diff --git a/assetstudio/res/launcher-stencil/square/ldpi/fore1.png b/assetstudio/res/launcher-stencil/square/ldpi/fore1.png Binary files differnew file mode 100644 index 0000000..c46e1c2 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/ldpi/fore1.png diff --git a/assetstudio/res/launcher-stencil/square/ldpi/fore2.png b/assetstudio/res/launcher-stencil/square/ldpi/fore2.png Binary files differnew file mode 100644 index 0000000..3bc8315 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/ldpi/fore2.png diff --git a/assetstudio/res/launcher-stencil/square/ldpi/fore3.png b/assetstudio/res/launcher-stencil/square/ldpi/fore3.png Binary files differnew file mode 100644 index 0000000..0bfa4f7 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/ldpi/fore3.png diff --git a/assetstudio/res/launcher-stencil/square/ldpi/mask.png b/assetstudio/res/launcher-stencil/square/ldpi/mask.png Binary files differnew file mode 100644 index 0000000..04d6d1a --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/ldpi/mask.png diff --git a/assetstudio/res/launcher-stencil/square/mdpi/back.png b/assetstudio/res/launcher-stencil/square/mdpi/back.png Binary files differnew file mode 100644 index 0000000..f49e513 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/mdpi/back.png diff --git a/assetstudio/res/launcher-stencil/square/mdpi/fore1.png b/assetstudio/res/launcher-stencil/square/mdpi/fore1.png Binary files differnew file mode 100644 index 0000000..2837d41 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/mdpi/fore1.png diff --git a/assetstudio/res/launcher-stencil/square/mdpi/fore2.png b/assetstudio/res/launcher-stencil/square/mdpi/fore2.png Binary files differnew file mode 100644 index 0000000..566941f --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/mdpi/fore2.png diff --git a/assetstudio/res/launcher-stencil/square/mdpi/fore3.png b/assetstudio/res/launcher-stencil/square/mdpi/fore3.png Binary files differnew file mode 100644 index 0000000..9bcfc5e --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/mdpi/fore3.png diff --git a/assetstudio/res/launcher-stencil/square/mdpi/mask.png b/assetstudio/res/launcher-stencil/square/mdpi/mask.png Binary files differnew file mode 100644 index 0000000..90e5cd0 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/mdpi/mask.png diff --git a/assetstudio/res/launcher-stencil/square/web/back.png b/assetstudio/res/launcher-stencil/square/web/back.png Binary files differnew file mode 100644 index 0000000..2f008b7 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/web/back.png diff --git a/assetstudio/res/launcher-stencil/square/web/fore1.png b/assetstudio/res/launcher-stencil/square/web/fore1.png Binary files differnew file mode 100644 index 0000000..527ac47 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/web/fore1.png diff --git a/assetstudio/res/launcher-stencil/square/web/fore2.png b/assetstudio/res/launcher-stencil/square/web/fore2.png Binary files differnew file mode 100644 index 0000000..5e557f8 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/web/fore2.png diff --git a/assetstudio/res/launcher-stencil/square/web/fore3.png b/assetstudio/res/launcher-stencil/square/web/fore3.png Binary files differnew file mode 100644 index 0000000..58d85af --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/web/fore3.png diff --git a/assetstudio/res/launcher-stencil/square/web/mask.png b/assetstudio/res/launcher-stencil/square/web/mask.png Binary files differnew file mode 100644 index 0000000..2c80196 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/web/mask.png diff --git a/assetstudio/res/launcher-stencil/square/xhdpi/back.png b/assetstudio/res/launcher-stencil/square/xhdpi/back.png Binary files differnew file mode 100644 index 0000000..84caac0 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/xhdpi/back.png diff --git a/assetstudio/res/launcher-stencil/square/xhdpi/fore1.png b/assetstudio/res/launcher-stencil/square/xhdpi/fore1.png Binary files differnew file mode 100644 index 0000000..2d237e1 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/xhdpi/fore1.png diff --git a/assetstudio/res/launcher-stencil/square/xhdpi/fore2.png b/assetstudio/res/launcher-stencil/square/xhdpi/fore2.png Binary files differnew file mode 100644 index 0000000..cce5e0e --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/xhdpi/fore2.png diff --git a/assetstudio/res/launcher-stencil/square/xhdpi/fore3.png b/assetstudio/res/launcher-stencil/square/xhdpi/fore3.png Binary files differnew file mode 100644 index 0000000..3b91aa4 --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/xhdpi/fore3.png diff --git a/assetstudio/res/launcher-stencil/square/xhdpi/mask.png b/assetstudio/res/launcher-stencil/square/xhdpi/mask.png Binary files differnew file mode 100644 index 0000000..9e0bbdc --- /dev/null +++ b/assetstudio/res/launcher-stencil/square/xhdpi/mask.png |