diff options
author | Sven Gothel <[email protected]> | 2013-09-20 12:29:49 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-09-20 12:29:49 +0200 |
commit | 939d6304d464e69b1d1d2a104c3da5536d3bf326 (patch) | |
tree | 966863d592970b10a3cd65cab9ca1b4871182787 /src | |
parent | c427ed22244df44b71a0f1f000b0f93e56c283c2 (diff) |
AWT Printing: Fix non vertical-flipped printing, i.e. cut-off top-row's tile upper area, cleanup.
TestTiledPrintingGearsSwingAWT2: Provoked !flipped bug where top-row was positioned too low
due to using full size tile-height.
Cutting of the unused top-row's upper area corrects this issue.
vertical-flip mode does not expose this situation, since flipping
shifts the payload to the upper tile area.
TestTiledPrintingGearsSwingAWT2: Also tests an alternative transparent overlapping mode
without layout.
Diffstat (limited to 'src')
4 files changed, 427 insertions, 22 deletions
diff --git a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java index 0b24fadae..0aab049a0 100644 --- a/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java +++ b/src/jogl/classes/jogamp/opengl/awt/AWTTilePainter.java @@ -196,6 +196,7 @@ public class AWTTilePainter { final Rectangle2D dImageSizeOrig = new Rectangle2D.Double(0, 0, width, height); // Retrieve scaled image-size and clip-bounds + // Note: Clip bounds lie within image-size! final Rectangle2D dImageSizeScaled, dClipScaled; { final AffineTransform scaledATI; @@ -212,13 +213,15 @@ public class AWTTilePainter { s0 = saveAT.createTransformedShape(dClipOrig); // user in dClipScaled = scaledATI.createTransformedShape(s0).getBounds2D(); // scaled out } - } + } final Rectangle iClipScaled = getRoundedRect(dClipScaled); final Rectangle iImageSizeScaled = getRoundedRect(dImageSizeScaled); - scaledYOffset = iClipScaled.y; renderer.setImageSize(iImageSizeScaled.width, iImageSizeScaled.height); renderer.clipImageSize(iClipScaled.width, iClipScaled.height); final int clipH = Math.min(iImageSizeScaled.height, iClipScaled.height); + // Clip bounds lie within image-size! + // GL y-offset is lower-left origin, AWT y-offset upper-left. + scaledYOffset = iClipScaled.y; renderer.setTileOffset(iClipScaled.x, iImageSizeScaled.height - ( iClipScaled.y + clipH )); // Scale actual Grahics2D matrix @@ -294,10 +297,11 @@ public class AWTTilePainter { final DimensionImmutable cis = renderer.getClippedImageSize(); final int tWidth = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_WIDTH); final int tHeight = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_HEIGHT); - final int pX = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS); - final int pY = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS); - final int pYOff = renderer.getParam(TileRenderer.TR_TILE_Y_OFFSET); - final int pYf = cis.getHeight() - ( pY - pYOff + tHeight ) + scaledYOffset; + final int tY = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_Y_POS); + final int tYOff = renderer.getParam(TileRenderer.TR_TILE_Y_OFFSET); + final int imgYOff = flipVertical ? 0 : renderer.getParam(TileRenderer.TR_TILE_HEIGHT) - tHeight; // imgYOff will be cut-off via sub-image + final int pX = renderer.getParam(TileRendererBase.TR_CURRENT_TILE_X_POS); // tileX == pX + final int pY = cis.getHeight() - ( tY - tYOff + tHeight ) + scaledYOffset; // Copy temporary data into raster of BufferedImage for faster // blitting Note that we could avoid this copy in the cases @@ -309,7 +313,7 @@ public class AWTTilePainter { _counter, renderer.getParam(TileRenderer.TR_CURRENT_COLUMN), renderer.getParam(TileRenderer.TR_CURRENT_ROW), tWidth, tHeight, - pX, pY, pYOff, pX, pYf).replace(' ', '_'); + pX, tY, tYOff, pX, pY).replace(' ', '_'); System.err.println("XXX file "+fname); final File fout = new File(fname); try { @@ -340,7 +344,7 @@ public class AWTTilePainter { _counter, renderer.getParam(TileRenderer.TR_CURRENT_COLUMN), renderer.getParam(TileRenderer.TR_CURRENT_ROW), tWidth, tHeight, - pX, pY, pYOff, pX, pYf).replace(' ', '_'); + pX, tY, tYOff, pX, pY).replace(' ', '_'); System.err.println("XXX file "+fname); final File fout = new File(fname); try { @@ -351,17 +355,15 @@ public class AWTTilePainter { _counter++; } // Draw resulting image in one shot - final Shape oClip = g2d.getClip(); - // g2d.clipRect(pX, pYf, tWidth, tHeight); - final BufferedImage outImage = dstImage.getSubimage(0, 0, tWidth, tHeight); // instead of clipping - final boolean drawDone = g2d.drawImage(outImage, pX, pYf, null); // Null ImageObserver since image data is ready. - // final boolean drawDone = g2d.drawImage(dstImage, pX, pYf, dstImage.getWidth(), dstImage.getHeight(), null); // Null ImageObserver since image data is ready. + final BufferedImage outImage = dstImage.getSubimage(0, imgYOff, tWidth, tHeight); + final boolean drawDone = g2d.drawImage(outImage, pX, pY, null); // Null ImageObserver since image data is ready. if( verbose ) { - System.err.println("XXX tile-post.X clippedImageSize "+cis); - System.err.println("XXX tile-post.X pYf "+cis.getHeight()+" - ( "+pY+" - "+pYOff+" + "+tHeight+" ) "+scaledYOffset+" = "+ pYf); - System.err.println("XXX tile-post.X clip "+oClip+" + "+pX+" / [pY "+pY+", pYOff "+pYOff+", pYf "+pYf+"] "+tWidth+"x"+tHeight+" -> "+g2d.getClip()); + final Shape oClip = g2d.getClip(); + System.err.println("XXX tile-post.X tile 0 / "+imgYOff+" "+tWidth+"x"+tHeight+", clippedImgSize "+cis); + System.err.println("XXX tile-post.X pYf "+cis.getHeight()+" - ( "+tY+" - "+tYOff+" + "+tHeight+" ) "+scaledYOffset+" = "+ pY); + System.err.println("XXX tile-post.X clip "+oClip+" + "+pX+" / [pY "+tY+", pYOff "+tYOff+", pYf "+pY+"] -> "+g2d.getClip()); g2d.setColor(Color.BLACK); - g2d.drawRect(pX, pYf, tWidth, tHeight); + g2d.drawRect(pX, pY, tWidth, tHeight); if( null != oClip ) { final Rectangle r = oClip.getBounds(); g2d.setColor(Color.YELLOW); @@ -370,9 +372,8 @@ public class AWTTilePainter { System.err.println("XXX tile-post.X "+renderer); System.err.println("XXX tile-post.X dst-img "+dstImage.getWidth()+"x"+dstImage.getHeight()); System.err.println("XXX tile-post.X out-img "+outImage.getWidth()+"x"+outImage.getHeight()); - System.err.println("XXX tile-post.X y-flip "+flipVertical+" -> "+pX+"/"+pYf+", drawDone "+drawDone); + System.err.println("XXX tile-post.X y-flip "+flipVertical+" -> "+pX+"/"+pY+", drawDone "+drawDone); } - // g2d.setClip(oClip); } @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java index 476513207..b4f5ad988 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT.java @@ -68,6 +68,7 @@ import com.jogamp.newt.event.awt.AWTWindowAdapter; import com.jogamp.opengl.test.junit.jogl.demos.es1.RedSquareES1; import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; import com.jogamp.opengl.test.junit.util.QuitAdapter; import com.jogamp.opengl.util.Animator; @@ -306,9 +307,13 @@ public class TestTiledPrintingGearsSwingAWT extends TiledPrintingAWTBase { for(int i=0; i<args.length; i++) { if(args[i].equals("-time")) { i++; - try { - duration = Integer.parseInt(args[i]); - } catch (Exception ex) { ex.printStackTrace(); } + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + i++; + width = MiscUtils.atoi(args[i], width); + } else if(args[i].equals("-height")) { + i++; + height = MiscUtils.atoi(args[i], height); } else if(args[i].equals("-600dpi")) { allow600dpi = true; } else if(args[i].equals("-wait")) { diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java new file mode 100644 index 000000000..f619ec9a1 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TestTiledPrintingGearsSwingAWT2.java @@ -0,0 +1,340 @@ +/** + * Copyright 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.tile; + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Label; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.print.PageFormat; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; + +import javax.media.opengl.GLCapabilities; +import javax.media.opengl.GLProfile; +import javax.media.opengl.awt.GLJPanel; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.os.Platform; +import com.jogamp.newt.event.TraceKeyAdapter; +import com.jogamp.newt.event.TraceWindowAdapter; +import com.jogamp.newt.event.awt.AWTKeyAdapter; +import com.jogamp.newt.event.awt.AWTWindowAdapter; +import com.jogamp.opengl.test.junit.jogl.demos.gl2.Gears; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.MiscUtils; +import com.jogamp.opengl.test.junit.util.QuitAdapter; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestTiledPrintingGearsSwingAWT2 extends TiledPrintingAWTBase { + + static boolean waitForKey = false; + static GLProfile glp; + static int width, height; + + @BeforeClass + public static void initClass() { + if(GLProfile.isAvailable(GLProfile.GL2)) { + glp = GLProfile.get(GLProfile.GL2); + Assert.assertNotNull(glp); + width = 560; // 640; + height = 420; // 480; + } else { + setTestSupported(false); + } + // Runtime.getRuntime().traceInstructions(true); + // Runtime.getRuntime().traceMethodCalls(true); + } + + @AfterClass + public static void releaseClass() { + } + + protected void runTestGL(GLCapabilities caps, final boolean addLayout, boolean layered, boolean useAnim) throws InterruptedException, InvocationTargetException { + final Dimension glc_sz = new Dimension(width, height); + final GLJPanel glJPanel1 = new GLJPanel(caps); + Assert.assertNotNull(glJPanel1); + glJPanel1.setMinimumSize(glc_sz); + glJPanel1.setPreferredSize(glc_sz); + glJPanel1.setBounds(0, 0, glc_sz.width, glc_sz.height); + glJPanel1.addGLEventListener(new Gears()); + + final JComponent tPanel, demoPanel; + if( layered ) { + glJPanel1.setOpaque(true); + final JButton tb = new JButton("On Top"); + tb.setBounds(width/2, height/2, 200, 50); + if( addLayout ) { + tPanel = null; + final Dimension lsz = new Dimension(width, height); + demoPanel = new JLayeredPane(); + demoPanel.setMinimumSize(lsz); + demoPanel.setPreferredSize(lsz); + demoPanel.setBounds(0, 0, lsz.width, lsz.height); + demoPanel.setBorder(BorderFactory.createTitledBorder("Layered Pane")); + demoPanel.add(glJPanel1, JLayeredPane.DEFAULT_LAYER); + demoPanel.add(tb, Integer.valueOf(2)); + } else { + tPanel = new TransparentPanel(); + tPanel.setBounds(0, 0, width, height); + tPanel.setLayout(null); + tPanel.add(tb); + demoPanel = glJPanel1; + } + } else { + tPanel = null; + if( addLayout ) { + demoPanel = new JPanel(); + demoPanel.add(glJPanel1); + } else { + demoPanel = glJPanel1; + } + } + + final JFrame frame = new JFrame("Swing Print"); + Assert.assertNotNull(frame); + + final ActionListener print72DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 72, 0); + } }; + final ActionListener print150DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 150, -1); + } }; + final ActionListener print300DPIAction = new ActionListener() { + public void actionPerformed(ActionEvent e) { + doPrintManual(frame, 300, -1); + } }; + final Button print72DPIButton = new Button("72dpi"); + print72DPIButton.addActionListener(print72DPIAction); + final Button print150DPIButton = new Button("150dpi"); + print150DPIButton.addActionListener(print150DPIAction); + final Button print300DPIButton = new Button("300dpi"); + print300DPIButton.addActionListener(print300DPIAction); + + final JPanel printPanel = new JPanel(); + printPanel.add(print72DPIButton); + printPanel.add(print150DPIButton); + printPanel.add(print300DPIButton); + final JPanel southPanel = new JPanel(); + southPanel.add(new Label("South")); + final JPanel eastPanel = new JPanel(); + eastPanel.add(new Label("East")); + final JPanel westPanel = new JPanel(); + westPanel.add(new Label("West")); + + final Animator animator = useAnim ? new Animator() : null; + if( null != animator ) { + animator.add(glJPanel1); + } + QuitAdapter quitAdapter = new QuitAdapter(); + + new AWTKeyAdapter(new TraceKeyAdapter(quitAdapter)).addTo(glJPanel1); + new AWTWindowAdapter(new TraceWindowAdapter(quitAdapter)).addTo(frame); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Container fcont = frame.getContentPane(); + if( addLayout ) { + fcont.setLayout(new BorderLayout()); + fcont.add(printPanel, BorderLayout.NORTH); + fcont.add(demoPanel, BorderLayout.CENTER); + fcont.add(southPanel, BorderLayout.SOUTH); + fcont.add(eastPanel, BorderLayout.EAST); + fcont.add(westPanel, BorderLayout.WEST); + fcont.validate(); + frame.pack(); + } else { + frame.setSize(glc_sz); + fcont.setLayout(null); + if( null != tPanel ) { + fcont.add(tPanel); + } + fcont.add(demoPanel); + } + frame.setVisible(true); + } } ) ; + + Assert.assertEquals(true, AWTRobotUtil.waitForVisible(frame, true)); + Assert.assertEquals(true, AWTRobotUtil.waitForRealized(glJPanel1, true)); + + if( null != animator ) { + animator.setUpdateFPSFrames(60, System.err); + animator.start(); + Assert.assertEquals(true, animator.isAnimating()); + } + + final long t0 = System.currentTimeMillis(); + long t1 = t0; + boolean printDone = false; + while( !quitAdapter.shouldQuit() && ( 0 == duration || ( t1 - t0 ) < duration ) ) { + Thread.sleep(200); + if( !printDone ) { + printDone = true; + { + // No AA needed for 150 dpi and greater :) + final PrintableBase p = doPrintAuto(frame, PageFormat.PORTRAIT, null, false, 150, -1); + waitUntilPrintJobsIdle(p); + } + } + t1 = System.currentTimeMillis(); + } + + Assert.assertNotNull(frame); + Assert.assertNotNull(glJPanel1); + + if( null != animator ) { + animator.stop(); + Assert.assertEquals(false, animator.isAnimating()); + } + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame.setVisible(false); + }}); + Assert.assertEquals(false, frame.isVisible()); + javax.swing.SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + final Frame _frame = frame; + _frame.remove(demoPanel); + _frame.dispose(); + }}); + } + + @Test + public void test01_norm_layout0_layered0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false /* addLayout */, false /* layered */, false /* useAnim */); + } + + @Test + public void test02_norm_layout1_layered0() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, true /* addLayout */, false /* layered */, false /* useAnim */); + } + + @Test + public void test03_norm_layout0_layered1() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, false /* addLayout */, true /* layered */, false /* useAnim */); + } + + @Test + public void test04_norm_layout1_layered1() throws InterruptedException, InvocationTargetException { + GLCapabilities caps = new GLCapabilities(glp); + runTestGL(caps, true /* addLayout */, true /* layered */, false /* useAnim */); + } + + @Test + public void test11_bitm_layout0_layered0() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, false /* addLayout */, false /* layered */, false /* useAnim */); + } + + @Test + public void test12_bitm_layout1_layered0() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, true /* addLayout */, false /* layered */, false /* useAnim */); + } + + @Test + public void test13_bitm_layout0_layered1() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, false /* addLayout */, true /* layered */, false /* useAnim */); + } + + @Test + public void test14_bitm_layout1_layered1() throws InterruptedException, InvocationTargetException { + if( Platform.OSType.WINDOWS != Platform.getOSType() ) { + return; + } + GLCapabilities caps = new GLCapabilities(glp); + caps.setBitmap(true); + runTestGL(caps, true /* addLayout */, true /* layered */, false /* useAnim */); + } + + static long duration = 500; // ms + + public static void main(String args[]) { + for(int i=0; i<args.length; i++) { + if(args[i].equals("-time")) { + i++; + duration = MiscUtils.atol(args[i], duration); + } else if(args[i].equals("-width")) { + i++; + width = MiscUtils.atoi(args[i], width); + } else if(args[i].equals("-height")) { + i++; + height = MiscUtils.atoi(args[i], height); + } else if(args[i].equals("-wait")) { + waitForKey = true; + } + } + if(waitForKey) { + BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); + System.err.println("Press enter to continue"); + try { + System.err.println(stdin.readLine()); + } catch (IOException e) { } + } + org.junit.runner.JUnitCore.main(TestTiledPrintingGearsSwingAWT2.class.getName()); + } +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java new file mode 100644 index 000000000..d68f878fa --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/tile/TransparentPanel.java @@ -0,0 +1,59 @@ +package com.jogamp.opengl.test.junit.jogl.tile; + +import java.awt.*; +import javax.swing.*; +import java.lang.reflect.Method; + +public class TransparentPanel extends JPanel { + public TransparentPanel() { + super.setOpaque(false); + setMixingCutoutShape(new Rectangle()); + } + + @Override + public void setOpaque(boolean isOpaque) { + // Don't let this panel become opaque + } + + /** + * Helper utility needed to implement TransparentPanel. + * This class provides the ability to cut out the background of a lightweight + * panel so that it can be layered on top of a heavyweight component and have + * the heavyweight component show through. For more infromation, see: + * + * http://today.java.net/article/2009/11/02/transparent-panel-mixing-heavyweight-and-lightweight-components + */ + private static Method mSetComponentMixing; + + /** + * Set the cut out shape on a given Component. + * + * @param c The Component on which to set the cut out shape. + * @param s The shape to cut out of the given Component. + */ + public void setMixingCutoutShape(Shape s) + { + // Get the cut out shape method + if (mSetComponentMixing == null) { + try { + Class<?> awtUtilitiesClass = + Class.forName("com.sun.awt.AWTUtilities"); + mSetComponentMixing = + awtUtilitiesClass.getMethod( + "setComponentMixingCutoutShape", + Component.class, Shape.class); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + // Cut out the shape + if (mSetComponentMixing != null) { + try { + mSetComponentMixing.invoke( null, this, s ); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } +} |