diff options
Diffstat (limited to 'assetstudio')
61 files changed, 962 insertions, 0 deletions
diff --git a/assetstudio/.classpath b/assetstudio/.classpath new file mode 100644 index 0000000..ee79d96 --- /dev/null +++ b/assetstudio/.classpath @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry kind="src" path="src"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry kind="output" path="bin"/> + <classpathentry combineaccessrules="false" kind="src" path="/common"/> +</classpath> diff --git a/assetstudio/.gitignore b/assetstudio/.gitignore new file mode 100644 index 0000000..fe99505 --- /dev/null +++ b/assetstudio/.gitignore @@ -0,0 +1,2 @@ +bin + diff --git a/assetstudio/.project b/assetstudio/.project new file mode 100644 index 0000000..f9aa2ce --- /dev/null +++ b/assetstudio/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>assetstudio</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/assetstudio/.settings/org.eclipse.jdt.core.prefs b/assetstudio/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..e755df2 --- /dev/null +++ b/assetstudio/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,71 @@ +#Thu Jun 09 12:26:44 PDT 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=error +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=warning +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=disabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning diff --git a/assetstudio/Android.mk b/assetstudio/Android.mk new file mode 100644 index 0000000..a48c3a0 --- /dev/null +++ b/assetstudio/Android.mk @@ -0,0 +1,30 @@ +# +# 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. +# +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_JAVA_RESOURCE_DIRS := src + +# TODO: Replace common with the batik stuff +LOCAL_JAVA_LIBRARIES := \ + common + +LOCAL_MODULE := assetstudio + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_HOST_JAVA_LIBRARY) diff --git a/assetstudio/src/com/android/assetstudiolib/GraphicGenerator.java b/assetstudio/src/com/android/assetstudiolib/GraphicGenerator.java new file mode 100644 index 0000000..e53f0ab --- /dev/null +++ b/assetstudio/src/com/android/assetstudiolib/GraphicGenerator.java @@ -0,0 +1,52 @@ +/* + * 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 com.android.resources.Density; + +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.io.InputStream; + +import javax.imageio.ImageIO; + +/** + * The base Generator class. + */ +public class GraphicGenerator { + /** + * Options used for all generators. + */ + public static class Options { + } + + public static float getScaleFactor(Density density) { + return density.getDpiValue() / (float) Density.DEFAULT_DENSITY; + } + + /** + * Returns one of the built in stencil images, or null + * + * @param relativePath stencil path such as "launcher-stencil/square/web/back.png" + * @return the image, or null + * @throws IOException if an unexpected I/O error occurs + */ + public static BufferedImage getStencilImage(String relativePath) throws IOException { + InputStream is = GraphicGenerator.class.getResourceAsStream(relativePath); + return ImageIO.read(is); + } +} diff --git a/assetstudio/src/com/android/assetstudiolib/GraphicGeneratorContext.java b/assetstudio/src/com/android/assetstudiolib/GraphicGeneratorContext.java new file mode 100644 index 0000000..e0b00a6 --- /dev/null +++ b/assetstudio/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/src/com/android/assetstudiolib/LauncherIconGenerator.java b/assetstudio/src/com/android/assetstudiolib/LauncherIconGenerator.java new file mode 100644 index 0000000..b6715a4 --- /dev/null +++ b/assetstudio/src/com/android/assetstudiolib/LauncherIconGenerator.java @@ -0,0 +1,108 @@ +/* + * 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 com.android.resources.Density; + +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("/images/launcher_stencil/" + + options.shape.id + "/" + options.density.getResourceValue() + "/back.png"); + mForeImage = context.loadImageResource("/images/launcher_stencil/" + + options.shape.id + "/" + options.density.getResourceValue() + "/" + + options.style.id + ".png"); + mMaskImage = context.loadImageResource("/images/launcher_stencil/" + + options.shape.id + "/" + options.density.getResourceValue() + "/mask.png"); + } + + public BufferedImage generate() { + final float scaleFactor = GraphicGenerator.getScaleFactor(mOptions.density); + 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 Density density = Density.XHIGH; + + 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/src/com/android/assetstudiolib/MenuIconGenerator.java b/assetstudio/src/com/android/assetstudiolib/MenuIconGenerator.java new file mode 100644 index 0000000..07b7a6b --- /dev/null +++ b/assetstudio/src/com/android/assetstudiolib/MenuIconGenerator.java @@ -0,0 +1,92 @@ +/* + * 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 com.android.resources.Density; + +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 = GraphicGenerator.getScaleFactor(mOptions.density); + 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 Density density = Density.XHIGH; + } +} diff --git a/assetstudio/src/com/android/assetstudiolib/TextRenderUtil.java b/assetstudio/src/com/android/assetstudiolib/TextRenderUtil.java new file mode 100644 index 0000000..a103701 --- /dev/null +++ b/assetstudio/src/com/android/assetstudiolib/TextRenderUtil.java @@ -0,0 +1,110 @@ +/* + * 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.Font; +import java.awt.Graphics2D; +import java.awt.font.FontRenderContext; +import java.awt.font.TextAttribute; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.util.Hashtable; +import java.util.Map; + +/** + * A set of utility classes for rendering text to a {@link BufferedImage}, suitable for use as a + * source image to {@link GraphicGenerator} objects. + */ +public class TextRenderUtil { + /** + * Renders the given string with the provided {@link Options} to a {@link BufferedImage}. + * + * @param text The text to render. + * @param options The optional parameters for rendering the text. + * @return An image, suitable for use as an input to a {@link GraphicGenerator}. + */ + public static BufferedImage renderTextImage(String text, Options options) { + if (options == null) { + options = new Options(); + } + + BufferedImage tempImage = Util.newArgbBufferedImage(1, 1); + if (text == null || text.equals("")) { + return tempImage; + } + + Graphics2D tempG = (Graphics2D) tempImage.getGraphics(); + + Font font = options.font; + if (font == null) { + font = new Font(options.fontName, options.fontStyle, options.fontSize); + // Map<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>(); + // map.put(TextAttribute.TRACKING, 0.3); + // font = font.deriveFont(map); + } + + FontRenderContext frc = tempG.getFontRenderContext(); + + Rectangle2D bounds = font.getStringBounds(text, frc); + + BufferedImage image = Util.newArgbBufferedImage( + Math.max(1, (int) bounds.getWidth()), Math.max(1, (int) bounds.getHeight())); + Graphics2D g = (Graphics2D) image.getGraphics(); + g.setFont(font); + g.drawString(text, 0, (float) -bounds.getY()); + + return image; + } + + /** + * The parameters for text rendering. There are no required values so a <code>new + * Options()</code> object is considered valid. + */ + public static class Options { + // We use a large default font size to reduce the need to scale generated images up. + // TODO: Instead, a graphic generator should use a different source image for each density. + private static final int DEFAULT_FONT_SIZE = 512; + + /** + * The optional {@link Font} to use. If null, a {@link Font} object will be generated using + * the other options. + */ + public Font font = null; + + /** + * The optional font name. Defaults to {@link Font#SERIF}. + * + * @see Font#Font(String, int, int) + */ + public String fontName = Font.SERIF; + + /** + * The optional font styling (bold and/or italic). Defaults to no styling. + * + * @see Font#Font(String, int, int) + */ + public int fontStyle = 0; + + /** + * The optional font size, in points. Defaults to a very large font size, to prevent + * up-scaling rendered text. + * + * @see Font#Font(String, int, int) + */ + public int fontSize = DEFAULT_FONT_SIZE; + } +} diff --git a/assetstudio/src/com/android/assetstudiolib/Util.java b/assetstudio/src/com/android/assetstudiolib/Util.java new file mode 100644 index 0000000..1a6b00e --- /dev/null +++ b/assetstudio/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 = Math.max(1, dstRect.width); + final int scaledHeight = Math.max(1, 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 = Math.max(1, dstRect.height * srcWidth / srcHeight); + final int scaledHeight = Math.max(1, 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/src/images/launcher_stencil/circle/hdpi/back.png b/assetstudio/src/images/launcher_stencil/circle/hdpi/back.png Binary files differnew file mode 100644 index 0000000..8e3dbc1 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/hdpi/back.png diff --git a/assetstudio/src/images/launcher_stencil/circle/hdpi/fore1.png b/assetstudio/src/images/launcher_stencil/circle/hdpi/fore1.png Binary files differnew file mode 100644 index 0000000..79d75c0 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/hdpi/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/circle/hdpi/fore2.png b/assetstudio/src/images/launcher_stencil/circle/hdpi/fore2.png Binary files differnew file mode 100644 index 0000000..594257a --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/hdpi/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/circle/hdpi/fore3.png b/assetstudio/src/images/launcher_stencil/circle/hdpi/fore3.png Binary files differnew file mode 100644 index 0000000..65fb48b --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/hdpi/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/circle/hdpi/mask.png b/assetstudio/src/images/launcher_stencil/circle/hdpi/mask.png Binary files differnew file mode 100644 index 0000000..99e787a --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/hdpi/mask.png diff --git a/assetstudio/src/images/launcher_stencil/circle/ldpi/back.png b/assetstudio/src/images/launcher_stencil/circle/ldpi/back.png Binary files differnew file mode 100644 index 0000000..d9a9fcc --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/ldpi/back.png diff --git a/assetstudio/src/images/launcher_stencil/circle/ldpi/fore1.png b/assetstudio/src/images/launcher_stencil/circle/ldpi/fore1.png Binary files differnew file mode 100644 index 0000000..ecc3bc5 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/ldpi/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/circle/ldpi/fore2.png b/assetstudio/src/images/launcher_stencil/circle/ldpi/fore2.png Binary files differnew file mode 100644 index 0000000..c86b59c --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/ldpi/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/circle/ldpi/fore3.png b/assetstudio/src/images/launcher_stencil/circle/ldpi/fore3.png Binary files differnew file mode 100644 index 0000000..1ae4d31 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/ldpi/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/circle/ldpi/mask.png b/assetstudio/src/images/launcher_stencil/circle/ldpi/mask.png Binary files differnew file mode 100644 index 0000000..e537ad0 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/ldpi/mask.png diff --git a/assetstudio/src/images/launcher_stencil/circle/mdpi/back.png b/assetstudio/src/images/launcher_stencil/circle/mdpi/back.png Binary files differnew file mode 100644 index 0000000..e165038 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/mdpi/back.png diff --git a/assetstudio/src/images/launcher_stencil/circle/mdpi/fore1.png b/assetstudio/src/images/launcher_stencil/circle/mdpi/fore1.png Binary files differnew file mode 100644 index 0000000..c42af13 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/mdpi/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/circle/mdpi/fore2.png b/assetstudio/src/images/launcher_stencil/circle/mdpi/fore2.png Binary files differnew file mode 100644 index 0000000..0c06821 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/mdpi/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/circle/mdpi/fore3.png b/assetstudio/src/images/launcher_stencil/circle/mdpi/fore3.png Binary files differnew file mode 100644 index 0000000..01fe418 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/mdpi/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/circle/mdpi/mask.png b/assetstudio/src/images/launcher_stencil/circle/mdpi/mask.png Binary files differnew file mode 100644 index 0000000..19f18bf --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/mdpi/mask.png diff --git a/assetstudio/src/images/launcher_stencil/circle/web/back.png b/assetstudio/src/images/launcher_stencil/circle/web/back.png Binary files differnew file mode 100644 index 0000000..191c677 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/web/back.png diff --git a/assetstudio/src/images/launcher_stencil/circle/web/fore1.png b/assetstudio/src/images/launcher_stencil/circle/web/fore1.png Binary files differnew file mode 100644 index 0000000..7ea8096 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/web/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/circle/web/fore2.png b/assetstudio/src/images/launcher_stencil/circle/web/fore2.png Binary files differnew file mode 100644 index 0000000..5a76240 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/web/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/circle/web/fore3.png b/assetstudio/src/images/launcher_stencil/circle/web/fore3.png Binary files differnew file mode 100644 index 0000000..1794bff --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/web/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/circle/web/mask.png b/assetstudio/src/images/launcher_stencil/circle/web/mask.png Binary files differnew file mode 100644 index 0000000..8316d80 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/web/mask.png diff --git a/assetstudio/src/images/launcher_stencil/circle/xhdpi/back.png b/assetstudio/src/images/launcher_stencil/circle/xhdpi/back.png Binary files differnew file mode 100644 index 0000000..e655af6 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/xhdpi/back.png diff --git a/assetstudio/src/images/launcher_stencil/circle/xhdpi/fore1.png b/assetstudio/src/images/launcher_stencil/circle/xhdpi/fore1.png Binary files differnew file mode 100644 index 0000000..639ccba --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/xhdpi/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/circle/xhdpi/fore2.png b/assetstudio/src/images/launcher_stencil/circle/xhdpi/fore2.png Binary files differnew file mode 100644 index 0000000..b922452 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/xhdpi/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/circle/xhdpi/fore3.png b/assetstudio/src/images/launcher_stencil/circle/xhdpi/fore3.png Binary files differnew file mode 100644 index 0000000..5f1c15e --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/xhdpi/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/circle/xhdpi/mask.png b/assetstudio/src/images/launcher_stencil/circle/xhdpi/mask.png Binary files differnew file mode 100644 index 0000000..6dc3bc7 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/circle/xhdpi/mask.png diff --git a/assetstudio/src/images/launcher_stencil/square/hdpi/back.png b/assetstudio/src/images/launcher_stencil/square/hdpi/back.png Binary files differnew file mode 100644 index 0000000..3e58211 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/hdpi/back.png diff --git a/assetstudio/src/images/launcher_stencil/square/hdpi/fore1.png b/assetstudio/src/images/launcher_stencil/square/hdpi/fore1.png Binary files differnew file mode 100644 index 0000000..e76d493 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/hdpi/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/square/hdpi/fore2.png b/assetstudio/src/images/launcher_stencil/square/hdpi/fore2.png Binary files differnew file mode 100644 index 0000000..ab28d8d --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/hdpi/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/square/hdpi/fore3.png b/assetstudio/src/images/launcher_stencil/square/hdpi/fore3.png Binary files differnew file mode 100644 index 0000000..59f5e8f --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/hdpi/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/square/hdpi/mask.png b/assetstudio/src/images/launcher_stencil/square/hdpi/mask.png Binary files differnew file mode 100644 index 0000000..9c56fe6 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/hdpi/mask.png diff --git a/assetstudio/src/images/launcher_stencil/square/ldpi/back.png b/assetstudio/src/images/launcher_stencil/square/ldpi/back.png Binary files differnew file mode 100644 index 0000000..1a68be3 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/ldpi/back.png diff --git a/assetstudio/src/images/launcher_stencil/square/ldpi/fore1.png b/assetstudio/src/images/launcher_stencil/square/ldpi/fore1.png Binary files differnew file mode 100644 index 0000000..c46e1c2 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/ldpi/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/square/ldpi/fore2.png b/assetstudio/src/images/launcher_stencil/square/ldpi/fore2.png Binary files differnew file mode 100644 index 0000000..3bc8315 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/ldpi/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/square/ldpi/fore3.png b/assetstudio/src/images/launcher_stencil/square/ldpi/fore3.png Binary files differnew file mode 100644 index 0000000..0bfa4f7 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/ldpi/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/square/ldpi/mask.png b/assetstudio/src/images/launcher_stencil/square/ldpi/mask.png Binary files differnew file mode 100644 index 0000000..04d6d1a --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/ldpi/mask.png diff --git a/assetstudio/src/images/launcher_stencil/square/mdpi/back.png b/assetstudio/src/images/launcher_stencil/square/mdpi/back.png Binary files differnew file mode 100644 index 0000000..f49e513 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/mdpi/back.png diff --git a/assetstudio/src/images/launcher_stencil/square/mdpi/fore1.png b/assetstudio/src/images/launcher_stencil/square/mdpi/fore1.png Binary files differnew file mode 100644 index 0000000..2837d41 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/mdpi/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/square/mdpi/fore2.png b/assetstudio/src/images/launcher_stencil/square/mdpi/fore2.png Binary files differnew file mode 100644 index 0000000..566941f --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/mdpi/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/square/mdpi/fore3.png b/assetstudio/src/images/launcher_stencil/square/mdpi/fore3.png Binary files differnew file mode 100644 index 0000000..9bcfc5e --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/mdpi/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/square/mdpi/mask.png b/assetstudio/src/images/launcher_stencil/square/mdpi/mask.png Binary files differnew file mode 100644 index 0000000..90e5cd0 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/mdpi/mask.png diff --git a/assetstudio/src/images/launcher_stencil/square/web/back.png b/assetstudio/src/images/launcher_stencil/square/web/back.png Binary files differnew file mode 100644 index 0000000..2f008b7 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/web/back.png diff --git a/assetstudio/src/images/launcher_stencil/square/web/fore1.png b/assetstudio/src/images/launcher_stencil/square/web/fore1.png Binary files differnew file mode 100644 index 0000000..527ac47 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/web/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/square/web/fore2.png b/assetstudio/src/images/launcher_stencil/square/web/fore2.png Binary files differnew file mode 100644 index 0000000..5e557f8 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/web/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/square/web/fore3.png b/assetstudio/src/images/launcher_stencil/square/web/fore3.png Binary files differnew file mode 100644 index 0000000..58d85af --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/web/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/square/web/mask.png b/assetstudio/src/images/launcher_stencil/square/web/mask.png Binary files differnew file mode 100644 index 0000000..2c80196 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/web/mask.png diff --git a/assetstudio/src/images/launcher_stencil/square/xhdpi/back.png b/assetstudio/src/images/launcher_stencil/square/xhdpi/back.png Binary files differnew file mode 100644 index 0000000..84caac0 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/xhdpi/back.png diff --git a/assetstudio/src/images/launcher_stencil/square/xhdpi/fore1.png b/assetstudio/src/images/launcher_stencil/square/xhdpi/fore1.png Binary files differnew file mode 100644 index 0000000..2d237e1 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/xhdpi/fore1.png diff --git a/assetstudio/src/images/launcher_stencil/square/xhdpi/fore2.png b/assetstudio/src/images/launcher_stencil/square/xhdpi/fore2.png Binary files differnew file mode 100644 index 0000000..cce5e0e --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/xhdpi/fore2.png diff --git a/assetstudio/src/images/launcher_stencil/square/xhdpi/fore3.png b/assetstudio/src/images/launcher_stencil/square/xhdpi/fore3.png Binary files differnew file mode 100644 index 0000000..3b91aa4 --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/xhdpi/fore3.png diff --git a/assetstudio/src/images/launcher_stencil/square/xhdpi/mask.png b/assetstudio/src/images/launcher_stencil/square/xhdpi/mask.png Binary files differnew file mode 100644 index 0000000..9e0bbdc --- /dev/null +++ b/assetstudio/src/images/launcher_stencil/square/xhdpi/mask.png |