Open Source & Free  

In the Shadow

In the Shadow

Header Image

Diamond asked us about an easy way to do dropshadows in Codename One to which I answered that it’s pretty easy thanks to our Gaussian blur support…​

We ended up with this code which is usable but probably not as intuitive for most:

Form hi = new Form("Drop Shadow", new BorderLayout(BorderLayout.CENTER_BEHAVIOR_CENTER));

FontImage mm = FontImage.createMaterial(FontImage.MATERIAL_PERSON, "Button", 30);
int[] rgb = mm.toImage().getRGB();
for(int iter = 0 ; iter < rgb.length ; iter++) {
    rgb[iter] = rgb[iter] & 0xff000000;
}
Image shadow = Image.createImage(rgb, mm.getWidth(), mm.getHeight());
if(Display.getInstance().isGaussianBlurSupported()) {
    shadow = Display.getInstance().gaussianBlurImage(shadow, 10);
}

Label top = new Label(mm, "Container");
Label bottom = new Label(shadow, "Container");
bottom.getAllStyles().setMargin(1, 0, 1, 0);
bottom.getAllStyles().setMarginUnit(Style.UNIT_TYPE_DIPS);
hi.add(BorderLayout.CENTER, LayeredLayout.encloseIn(bottom, top));

hi.show();

The effect is attractive and commonplace so I think it would be great to add it universally so we added two methods which will be a part of the coming update. These methods are in the Effects class and are both simple utility methods. Once creates a shadow and incorporates it into a new image at the given location. The other returns the shadow alone which you can shift/position as you see fit (e.g. if you have similarly shaped images this might also be useful in terms of CPU/RAM).

/**
 * Generates a shadow for the source image and returns a new larger image containing the shadow
 *
 * @param source the source image for whom the shadow should be generated
 * @param blurRadius a shadow is blurred using a gaussian blur when available, a value of 10 is often satisfactory
 * @param opacity the opacity of the shadow between 0 - 1 where 1 is completely opaque
 * @param xDistance the distance on the x axis from the main image body in pixels e.g. a negative value will represent a lightsource from the right (shadow on the left)
 * @param yDistance the distance on the y axis from the main image body in pixels e.g. a negative value will represent a lightsource from the bottom (shadow on top)
 * @return a new image whose size incorporates x/yDistance
 */
public static Image dropshadow(Image source, int blurRadius, float opacity, int xDistance, int yDistance);

/**
 * Generates a shadow for the source image and returns either the shadow itself or the image merged with the
 * shadow.
 *
 * @param source the source image for whom the shadow should be generated
 * @param blurRadius a shadow is blurred using a gaussian blur when available, a value of 10 is often satisfactory
 * @param opacity the opacity of the shadow between 0 - 1 where 1 is completely opaque
 * @return an image containing the shadow for source
 */
public static Image dropshadow(Image source, int blurRadius, float opacity);

This can result in simple code to do a drop shadow effect:

Form hi = new Form("Drop Shadow", new BorderLayout(BorderLayout.CENTER_BEHAVIOR_CENTER));

int twoMM = Display.getInstance().convertToPixels(2);
Image img = duke.scaledWidth(Display.getInstance().getDisplayWidth() / 2);
hi.add(BorderLayout.CENTER, new Label(Effects.dropshadow(img, 10, 0.8f, twoMM, twoMM), "Container"));

hi.show();
The variable duke is the image of the icon placed into the src directory

6 Comments

Leave a Reply