X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fimage%2Fimpl%2FShadow.java;fp=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fimage%2Fimpl%2FShadow.java;h=cb432fddf78849e2a6aab9491f2c7726ea45ca62;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/Shadow.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/Shadow.java new file mode 100644 index 000000000..cb432fddf --- /dev/null +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/Shadow.java @@ -0,0 +1,183 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.g2d.image.impl; + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.ConvolveOp; +import java.awt.image.Kernel; +import java.util.Arrays; +import java.util.EnumSet; + +import org.simantics.g2d.image.Image; +import org.simantics.scenegraph.Node; +import org.simantics.scenegraph.g2d.G2DParentNode; + +/** + * Reflects to a shadow of a symbol. + * + * @author Toni Kalajainen + */ +public class Shadow extends ImageProxy implements Image { + + public static final ShadowParameters SHADOW = new ShadowParameters(0.5, Color.BLACK, 2); + public static final class ShadowParameters { + public final double alpha; + public final Color color; + public final int size; + public ShadowParameters(double alpha, Color color, int size) { + this.alpha = alpha; + this.color = color; + this.size = size; + } + } + + public final ShadowParameters shadow; + Point2D size; + ConvolveOp horiz, vert; + int shadowSizeX, shadowSizeY; + EnumSet feats; + public ImageListener origListener; + + /** + * + * @param source + * @param shadow + * @param shadowOnly + */ + public Shadow(Image source, ShadowParameters shadow) + { + super(source); + this.shadow = shadow; + shadowSizeX = shadow.size; + shadowSizeY = shadow.size; + horiz = createBlurOp(shadow.size, 1); + vert = createBlurOp(1, shadow.size); + if (source.getFeatures().contains(Feature.Volatile)) { + feats = EnumSet.of(Feature.Volatile); + } else + feats = EnumSet.noneOf(Feature.class); + } + + public Shadow(Image source, ShadowParameters shadow, double width, double height) + { + this(source, shadow); + this.size = new Point2D.Double(width, height); + shadowSizeX = (int) Math.round( shadow.size * width / source.getBounds().getWidth() ); + shadowSizeY = (int) Math.round( shadow.size * height / source.getBounds().getHeight() ); + if (shadowSizeX<1) shadowSizeX = 1; + if (shadowSizeY<1) shadowSizeY = 1; + horiz = createBlurOp(shadowSizeX, 1); + vert = createBlurOp(1, shadowSizeY); + } + + @Override + public Rectangle2D getBounds() { + Rectangle2D rect = source.getBounds(); + return new Rectangle2D.Double(rect.getX() - shadowSizeX, rect.getY() - shadowSizeY, rect.getWidth() + shadowSizeX*2, rect.getHeight() + shadowSizeY*2); + } + + private BufferedImage createImage() { + Rectangle2D origBounds = source.getBounds(); + double width = size==null?origBounds.getWidth() :size.getX(); + double height = size==null?origBounds.getHeight():size.getY(); + BufferedImage subject = new BufferedImage( + (int)Math.ceil( width + shadowSizeX * 2 ), + (int)Math.ceil( height + shadowSizeY * 2 ), + BufferedImage.TYPE_INT_ARGB); + + Graphics2D g = subject.createGraphics(); + g.translate(shadowSizeX, shadowSizeY); + if (size!=null) + g.scale(size.getX()/origBounds.getWidth(), size.getY()/origBounds.getHeight()); + g.translate(-origBounds.getMinX(), -origBounds.getMinY()); + + Rectangle2D bounds = new Rectangle2D.Double(0, 0, subject.getWidth(), subject.getHeight()); +// GraphicsContextImpl gc = new GraphicsContextImpl(bounds, null); +// try { +// source.paint(gc); +// } finally { +// gc.dispose(); +// } + + g.dispose(); + return subject; + } + + private BufferedImage createShadowMask(BufferedImage image) { + BufferedImage mask = new BufferedImage(image.getWidth(), + image.getHeight(), + BufferedImage.TYPE_INT_ARGB); + + Graphics2D g2d = mask.createGraphics(); + g2d.drawImage(image, 0, 0, null); + g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, + (float)shadow.alpha)); + g2d.setColor(shadow.color); + g2d.fillRect(0, 0, image.getWidth(), image.getHeight()); + g2d.dispose(); + + return mask; + } + + public BufferedImage createShadow() { + BufferedImage i1 = createImage(); + BufferedImage i2 = new BufferedImage(i1.getWidth(), i1.getHeight(), BufferedImage.TYPE_INT_ARGB); + BufferedImage shadowMask = createShadowMask(i1); + horiz.filter(shadowMask, i2); + vert.filter(i2, shadowMask); + return shadowMask; + } + + private ConvolveOp createBlurOp(int width, int height) { + float[] data = new float[width * height]; + float value = 1.0f / (width * height); + Arrays.fill(data, value); + return new ConvolveOp(new Kernel(width, height, data)); + } + + + @Override + public Node init(G2DParentNode parent) { + return null; +// Graphics2D g = gc.getGraphics2D(); +// BufferedImage bi = createShadow(); +// +// Rectangle2D origBounds = source.getBounds(); +// if (size!=null) { +// g.translate(origBounds.getMinX(), origBounds.getMinY()); +// g.scale(origBounds.getWidth()/size.getX(), origBounds.getHeight()/size.getY()); +// g.translate(-shadowSizeX, -shadowSizeY); +// g.drawImage(bi, 0, 0, null); +// g.translate(shadowSizeX, shadowSizeY); +// g.scale(size.getX()/origBounds.getWidth(), size.getY()/origBounds.getHeight()); +// g.translate(-origBounds.getMinX(), -origBounds.getMinY()); +// } else { +// g.translate(-shadowSizeX, -shadowSizeY); +// g.translate(origBounds.getMinX(), origBounds.getMinY()); +// g.drawImage(bi, 0, 0, null); +// g.translate(shadowSizeX, shadowSizeY); +// g.translate(-origBounds.getMinX(), -origBounds.getMinY()); +// } + } + + @Override + public EnumSet getFeatures() { + return feats; + } + + +}