List of usage examples for java.awt.geom Area Area
public Area(Shape s)
From source file:org.eclipse.birt.chart.device.g2d.G2dRendererBase.java
@Override public void fillOval(OvalRenderEvent ore) throws ChartException { if (iv != null) { iv.modifyEvent(ore);/*from w w w.j a v a2 s . co m*/ } final Fill flBackground = validateMultipleFill(ore.getBackground()); if (isFullTransparent(flBackground)) { return; } final Bounds bo = ore.getBounds(); final Ellipse2D.Double e2d = new Ellipse2D.Double(bo.getLeft(), bo.getTop(), bo.getWidth(), bo.getHeight()); if (flBackground instanceof ColorDefinition) { final ColorDefinition cd = (ColorDefinition) flBackground; _g2d.setColor((Color) _ids.getColor(cd)); _g2d.fill(e2d); } else if (flBackground instanceof Gradient) { final Gradient g = (Gradient) flBackground; final ColorDefinition cdStart = g.getStartColor(); final ColorDefinition cdEnd = g.getEndColor(); // boolean bCyclic = g.isCyclic(); double dAngleInDegrees = g.getDirection(); final double dAngleInRadians = ((-dAngleInDegrees * Math.PI) / 180.0); if (dAngleInDegrees < -90 || dAngleInDegrees > 90) { throw new ChartException(ChartDeviceExtensionPlugin.ID, ChartException.RENDERING, "SwingRendererImpl.exception.gradient.angle", //$NON-NLS-1$ new Object[] { new Double(dAngleInDegrees) }, Messages.getResourceBundle(getULocale())); } Point2D.Double p2dStart, p2dEnd; if (dAngleInDegrees == 90) { p2dStart = new Point2D.Double(bo.getLeft(), bo.getTop() + bo.getHeight()); p2dEnd = new Point2D.Double(bo.getLeft(), bo.getTop()); } else if (dAngleInDegrees == -90) { p2dEnd = new Point2D.Double(bo.getLeft(), bo.getTop() + bo.getHeight()); p2dStart = new Point2D.Double(bo.getLeft(), bo.getTop()); } else if (dAngleInDegrees > 0) { p2dStart = new Point2D.Double(bo.getLeft(), bo.getTop() + bo.getHeight()); p2dEnd = new Point2D.Double(bo.getLeft() + bo.getWidth(), bo.getTop() + bo.getHeight() - bo.getWidth() * Math.abs(Math.tan(dAngleInRadians))); } else if (dAngleInDegrees < 0) { p2dStart = new Point2D.Double(bo.getLeft(), bo.getTop()); p2dEnd = new Point2D.Double(bo.getLeft() + bo.getWidth(), bo.getTop() + bo.getWidth() * Math.abs(Math.tan(dAngleInRadians))); } else { p2dStart = new Point2D.Double(bo.getLeft(), bo.getTop()); p2dEnd = new Point2D.Double(bo.getLeft() + bo.getWidth(), bo.getTop()); } _g2d.setPaint(new GradientPaint(p2dStart, (Color) _ids.getColor(cdStart), p2dEnd, (Color) _ids.getColor(cdEnd))); _g2d.fill(e2d); } else if (flBackground instanceof org.eclipse.birt.chart.model.attribute.Image) { Area ar2 = new Area(e2d); if (flBackground instanceof PatternImage) { fillWithPatternImage(ar2, flBackground); return; } java.awt.Image img = createImageFromModel(flBackground); if (img != null) { final Shape shClip = _g2d.getClip(); if (shClip != null) { Area ar1 = new Area(shClip); ar2.intersect(ar1); } _g2d.setClip(ar2); final Size szImage = _ids.getSize(img); int iXRepeat = (int) (Math.ceil(e2d.width / szImage.getWidth())); int iYRepeat = (int) (Math.ceil(e2d.height / szImage.getHeight())); ImageObserver io = (ImageObserver) _ids.getObserver(); for (int i = 0; i < iXRepeat; i++) { for (int j = 0; j < iYRepeat; j++) { _g2d.drawImage(img, (int) (e2d.x + i * szImage.getWidth()), (int) (e2d.y + j * szImage.getHeight()), io); } } _g2d.setClip(shClip); // RESTORE } } }
From source file:erigo.ctstream.CTstream.java
/** * Pop up the GUI//from www . jav a 2 s. c o m * * This method should be run in the event-dispatching thread. * * The GUI is created in one of two modes depending on whether Shaped * windows are supported on the platform: * * 1. If Shaped windows are supported then guiPanel (the container to * which all other components are added) is RED and capturePanel is * inset a small amount to this panel so that the RED border is seen * around the outer edge. A componentResized() method is defined * which creates the hollowed out region that was capturePanel. * 2. If Shaped windows are not supported then guiPanel is transparent * and capturePanel is translucent. In this case, the user can't * "reach through" capturePanel to interact with GUIs on the other * side. * * @param bShapedWindowSupportedI Does the underlying GraphicsDevice support the * PERPIXEL_TRANSPARENT translucency that is * required for Shaped windows? */ private void createAndShowGUI(boolean bShapedWindowSupportedI) { // No window decorations for translucent/transparent windows // (see note below) // JFrame.setDefaultLookAndFeelDecorated(true); // // Create GUI components // GridBagLayout framegbl = new GridBagLayout(); guiFrame = new JFrame("CTstream"); // To support a translucent window, the window must be undecorated // See notes in the class header up above about this; also see // http://alvinalexander.com/source-code/java/how-create-transparenttranslucent-java-jframe-mac-os-x guiFrame.setUndecorated(true); // Use MouseMotionListener to implement our own simple "window manager" for moving and resizing the window guiFrame.addMouseMotionListener(this); guiFrame.setBackground(new Color(0, 0, 0, 0)); guiFrame.getContentPane().setBackground(new Color(0, 0, 0, 0)); GridBagLayout gbl = new GridBagLayout(); guiPanel = new JPanel(gbl); // if Shaped windows are supported, make guiPanel red; // otherwise make it transparent if (bShapedWindowSupportedI) { guiPanel.setBackground(Color.RED); } else { guiPanel.setBackground(new Color(0, 0, 0, 0)); } guiFrame.setFont(new Font("Dialog", Font.PLAIN, 12)); guiPanel.setFont(new Font("Dialog", Font.PLAIN, 12)); GridBagLayout controlsgbl = new GridBagLayout(); // *** controlsPanel contains the UI controls at the top of guiFrame controlsPanel = new JPanel(controlsgbl); controlsPanel.setBackground(new Color(211, 211, 211, 255)); startStopButton = new JButton("Start"); startStopButton.addActionListener(this); startStopButton.setBackground(Color.GREEN); continueButton = new JButton("Continue"); continueButton.addActionListener(this); continueButton.setEnabled(false); screencapCheck = new JCheckBox("screen", bScreencap); screencapCheck.setBackground(controlsPanel.getBackground()); screencapCheck.addActionListener(this); webcamCheck = new JCheckBox("camera", bWebcam); webcamCheck.setBackground(controlsPanel.getBackground()); webcamCheck.addActionListener(this); audioCheck = new JCheckBox("audio", bAudio); audioCheck.setBackground(controlsPanel.getBackground()); audioCheck.addActionListener(this); textCheck = new JCheckBox("text", bText); textCheck.setBackground(controlsPanel.getBackground()); textCheck.addActionListener(this); JLabel fpsLabel = new JLabel("images/sec", SwingConstants.LEFT); fpsCB = new JComboBox<Double>(FPS_VALUES); int tempIndex = Arrays.asList(FPS_VALUES).indexOf(new Double(framesPerSec)); fpsCB.setSelectedIndex(tempIndex); fpsCB.addActionListener(this); // The popup doesn't display over the transparent region; // therefore, just display a few rows to keep it within controlsPanel fpsCB.setMaximumRowCount(3); JLabel imgQualLabel = new JLabel("image qual", SwingConstants.LEFT); // The slider will use range 0 - 1000 imgQualSlider = new JSlider(JSlider.HORIZONTAL, 0, 1000, (int) (imageQuality * 1000.0)); // NOTE: The JSlider's initial width was too large, so I'd like to set its preferred size // to try and constrain it some; also need to set its minimum size at the same time, // or else when the user makes the GUI frame smaller, the JSlider would pop down to // a really small minimum size. imgQualSlider.setPreferredSize(new Dimension(120, 30)); imgQualSlider.setMinimumSize(new Dimension(120, 30)); imgQualSlider.setBackground(controlsPanel.getBackground()); includeMouseCursorCheck = new JCheckBox("Include mouse cursor in screen capture", bIncludeMouseCursor); includeMouseCursorCheck.setBackground(controlsPanel.getBackground()); includeMouseCursorCheck.addActionListener(this); changeDetectCheck = new JCheckBox("Change detect", bChangeDetect); changeDetectCheck.setBackground(controlsPanel.getBackground()); changeDetectCheck.addActionListener(this); fullScreenCheck = new JCheckBox("Full Screen", bFullScreen); fullScreenCheck.setBackground(controlsPanel.getBackground()); fullScreenCheck.addActionListener(this); previewCheck = new JCheckBox("Preview", bPreview); previewCheck.setBackground(controlsPanel.getBackground()); previewCheck.addActionListener(this); // Specify a small size for the text area, so that we can shrink down the UI w/o the scrollbars popping up textArea = new JTextArea(3, 10); // Add a Document listener to the JTextArea; this is how we will listen for changes to the document docChangeListener = new DocumentChangeListener(this); textArea.getDocument().addDocumentListener(docChangeListener); textScrollPane = new JScrollPane(textArea); // *** capturePanel capturePanel = new JPanel(); if (!bShapedWindowSupportedI) { // Only make capturePanel translucent (ie, semi-transparent) if we aren't doing the Shaped window option capturePanel.setBackground(new Color(0, 0, 0, 16)); } else { capturePanel.setBackground(new Color(0, 0, 0, 0)); } capturePanel.setPreferredSize(new Dimension(500, 400)); boolean bMacOS = false; String OS = System.getProperty("os.name", "generic").toLowerCase(); if ((OS.indexOf("mac") >= 0) || (OS.indexOf("darwin") >= 0)) { bMacOS = true; } // Only have the CTstream UI stay on top of all other windows // if bStayOnTop is true (set by command line flag). This is needed // for the Mac, because on that platform the user can't "reach through" // the capture frame to windows behind it. if (bStayOnTop) { guiFrame.setAlwaysOnTop(true); } // // Add components to the GUI // int row = 0; GridBagConstraints gbc = new GridBagConstraints(); gbc.anchor = GridBagConstraints.WEST; gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0; gbc.weighty = 0; // // First row: the controls panel // // Add some extra horizontal padding around controlsPanel so the panel has some extra room // if we are running in web camera mode. gbc.insets = new Insets(0, 0, 0, 0); gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 100; gbc.weighty = 0; Utility.add(guiPanel, controlsPanel, gbl, gbc, 0, row, 1, 1); gbc.insets = new Insets(0, 0, 0, 0); gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0; gbc.weighty = 0; ++row; // Add controls to the controls panel int panelrow = 0; // (i) Start/Continue buttons GridBagLayout panelgbl = new GridBagLayout(); JPanel subPanel = new JPanel(panelgbl); GridBagConstraints panelgbc = new GridBagConstraints(); panelgbc.anchor = GridBagConstraints.WEST; panelgbc.fill = GridBagConstraints.NONE; panelgbc.weightx = 0; panelgbc.weighty = 0; subPanel.setBackground(controlsPanel.getBackground()); panelgbc.insets = new Insets(0, 0, 0, 5); Utility.add(subPanel, startStopButton, panelgbl, panelgbc, 0, 0, 1, 1); panelgbc.insets = new Insets(0, 0, 0, 0); Utility.add(subPanel, continueButton, panelgbl, panelgbc, 1, 0, 1, 1); gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.NONE; gbc.insets = new Insets(5, 0, 0, 0); Utility.add(controlsPanel, subPanel, controlsgbl, gbc, 0, panelrow, 1, 1); ++panelrow; gbc.anchor = GridBagConstraints.WEST; gbc.fill = GridBagConstraints.NONE; // (ii) select DataStreams to turn on panelgbl = new GridBagLayout(); subPanel = new JPanel(panelgbl); panelgbc = new GridBagConstraints(); panelgbc.anchor = GridBagConstraints.WEST; panelgbc.fill = GridBagConstraints.NONE; panelgbc.weightx = 0; panelgbc.weighty = 0; subPanel.setBackground(controlsPanel.getBackground()); panelgbc.insets = new Insets(0, 0, 0, 0); Utility.add(subPanel, screencapCheck, panelgbl, panelgbc, 0, 0, 1, 1); Utility.add(subPanel, webcamCheck, panelgbl, panelgbc, 1, 0, 1, 1); Utility.add(subPanel, audioCheck, panelgbl, panelgbc, 2, 0, 1, 1); Utility.add(subPanel, textCheck, panelgbl, panelgbc, 3, 0, 1, 1); gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.NONE; gbc.insets = new Insets(0, 0, 0, 0); Utility.add(controlsPanel, subPanel, controlsgbl, gbc, 0, panelrow, 1, 1); ++panelrow; // (iii) images/sec control panelgbl = new GridBagLayout(); subPanel = new JPanel(panelgbl); panelgbc = new GridBagConstraints(); panelgbc.anchor = GridBagConstraints.WEST; panelgbc.fill = GridBagConstraints.NONE; panelgbc.weightx = 0; panelgbc.weighty = 0; subPanel.setBackground(controlsPanel.getBackground()); panelgbc.insets = new Insets(2, 0, 0, 0); Utility.add(subPanel, fpsLabel, panelgbl, panelgbc, 0, 0, 1, 1); panelgbc.insets = new Insets(2, 10, 0, 10); Utility.add(subPanel, fpsCB, panelgbl, panelgbc, 1, 0, 1, 1); gbc.insets = new Insets(0, 0, 0, 0); gbc.anchor = GridBagConstraints.CENTER; Utility.add(controlsPanel, subPanel, controlsgbl, gbc, 0, panelrow, 1, 1); ++panelrow; // (iv) image quality slider panelgbl = new GridBagLayout(); subPanel = new JPanel(panelgbl); panelgbc = new GridBagConstraints(); panelgbc.anchor = GridBagConstraints.WEST; panelgbc.fill = GridBagConstraints.NONE; panelgbc.weightx = 0; panelgbc.weighty = 0; subPanel.setBackground(controlsPanel.getBackground()); JLabel sliderLabelLow = new JLabel("Low", SwingConstants.LEFT); JLabel sliderLabelHigh = new JLabel("High", SwingConstants.LEFT); panelgbc.insets = new Insets(-5, 0, 0, 0); Utility.add(subPanel, imgQualLabel, panelgbl, panelgbc, 0, 0, 1, 1); panelgbc.insets = new Insets(-5, 5, 0, 5); Utility.add(subPanel, sliderLabelLow, panelgbl, panelgbc, 1, 0, 1, 1); panelgbc.insets = new Insets(0, 0, 0, 0); Utility.add(subPanel, imgQualSlider, panelgbl, panelgbc, 2, 0, 1, 1); panelgbc.insets = new Insets(-5, 5, 0, 0); Utility.add(subPanel, sliderLabelHigh, panelgbl, panelgbc, 3, 0, 1, 1); gbc.insets = new Insets(0, 0, 0, 0); gbc.anchor = GridBagConstraints.CENTER; Utility.add(controlsPanel, subPanel, controlsgbl, gbc, 0, panelrow, 1, 1); ++panelrow; // (v) Include mouse cursor in screen capture image? gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0; gbc.weighty = 0; gbc.insets = new Insets(0, 15, 5, 15); Utility.add(controlsPanel, includeMouseCursorCheck, controlsgbl, gbc, 0, panelrow, 1, 1); gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0; gbc.weighty = 0; ++panelrow; // (vi) Change detect / Full screen / Preview checkboxes panelgbl = new GridBagLayout(); subPanel = new JPanel(panelgbl); panelgbc = new GridBagConstraints(); panelgbc.anchor = GridBagConstraints.WEST; panelgbc.fill = GridBagConstraints.NONE; panelgbc.weightx = 0; panelgbc.weighty = 0; subPanel.setBackground(controlsPanel.getBackground()); panelgbc.insets = new Insets(0, 0, 0, 0); Utility.add(subPanel, changeDetectCheck, panelgbl, panelgbc, 0, 0, 1, 1); Utility.add(subPanel, fullScreenCheck, panelgbl, panelgbc, 1, 0, 1, 1); Utility.add(subPanel, previewCheck, panelgbl, panelgbc, 2, 0, 1, 1); gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.NONE; gbc.insets = new Insets(-5, 0, 3, 0); Utility.add(controlsPanel, subPanel, controlsgbl, gbc, 0, panelrow, 1, 1); ++panelrow; // (vii) text field for the TextStream /* panelgbl = new GridBagLayout(); subPanel = new JPanel(panelgbl); panelgbc = new GridBagConstraints(); panelgbc.anchor = GridBagConstraints.CENTER; panelgbc.fill = GridBagConstraints.HORIZONTAL; panelgbc.weightx = 100; panelgbc.weighty = 100; subPanel.setBackground(controlsPanel.getBackground()); panelgbc.insets = new Insets(0, 0, 0, 0); Utility.add(subPanel, textScrollPane, panelgbl, panelgbc, 1, 0, 1, 1); gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 100; gbc.weighty = 100; gbc.insets = new Insets(0, 15, 3, 15); Utility.add(controlsPanel, subPanel, controlsgbl, gbc, 0, panelrow, 2, 1); ++panelrow; */ gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 100; gbc.weighty = 0; gbc.insets = new Insets(0, 15, 5, 15); Utility.add(controlsPanel, textScrollPane, controlsgbl, gbc, 0, panelrow, 1, 1); gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0; gbc.weighty = 0; ++panelrow; // // Second row: the translucent/transparent capture panel // if (bShapedWindowSupportedI) { // Doing the Shaped window; set capturePanel inside guiPanel // a bit so the red from guiPanel shows at the edges gbc.insets = new Insets(5, 5, 5, 5); } else { // No shaped window; have capturePanel fill the area gbc.insets = new Insets(0, 0, 0, 0); } gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 100; gbc.weighty = 100; Utility.add(guiPanel, capturePanel, gbl, gbc, 0, row, 1, 1); gbc.fill = GridBagConstraints.NONE; gbc.weightx = 0; gbc.weighty = 0; ++row; // // Add guiPanel to guiFrame // gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.BOTH; gbc.weightx = 100; gbc.weighty = 100; gbc.insets = new Insets(0, 0, 0, 0); Utility.add(guiFrame, guiPanel, framegbl, gbc, 0, 0, 1, 1); // // Add menu // JMenuBar menuBar = createMenu(); guiFrame.setJMenuBar(menuBar); // // If Shaped windows are supported, the region defined by capturePanel // will be "hollowed out" so that the user can reach through guiFrame // and interact with applications which are behind it. // // NOTE: This doesn't work on Mac OS (we've tried, but nothing seems // to work to allow a user to reach through guiFrame to interact // with windows behind). May be a limitation or bug on Mac OS: // https://bugs.openjdk.java.net/browse/JDK-8013450 // if (bShapedWindowSupportedI) { guiFrame.addComponentListener(new ComponentAdapter() { // As the window is resized, the shape is recalculated here. @Override public void componentResized(ComponentEvent e) { // Create a rectangle to cover the entire guiFrame Area guiShape = new Area(new Rectangle(0, 0, guiFrame.getWidth(), guiFrame.getHeight())); // Create another rectangle to define the hollowed out region of capturePanel guiShape.subtract(new Area(new Rectangle(capturePanel.getX(), capturePanel.getY() + 23, capturePanel.getWidth(), capturePanel.getHeight()))); guiFrame.setShape(guiShape); } }); } // // Final guiFrame configuration details and displaying the GUI // guiFrame.pack(); guiFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); guiFrame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { exit(false); } }); // Center on the screen guiFrame.setLocationRelativeTo(null); // // Set the taskbar/dock icon; note that Mac OS has its own way of doing it // if (bMacOS) { try { // JPW 2018/02/02: changed how to load images to work under Java 9 InputStream imageInputStreamLarge = getClass().getClassLoader() .getResourceAsStream("Icon_128x128.png"); BufferedImage bufferedImageLarge = ImageIO.read(imageInputStreamLarge); /** * * Java 9 note: running the following code under Java 9 on a Mac will produce the following warning: * * WARNING: An illegal reflective access operation has occurred * WARNING: Illegal reflective access by erigo.ctstream.CTstream (file:/Users/johnwilson/CT_versions/compiled_under_V8/CTstream.jar) to method com.apple.eawt.Application.getApplication() * WARNING: Please consider reporting this to the maintainers of erigo.ctstream.CTstream * WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations * WARNING: All illegal access operations will be denied in a future release * * This is because Java 9 has taken a step away from using reflection; see see the section titled * "Illegal Access To Internal APIs" at https://blog.codefx.org/java/java-9-migration-guide/. * * A good fix (but only available in Java 9+) is to use the following: * * java.awt.Taskbar taskbar = java.awt.Taskbar.getTaskbar(); * taskbar.setIconImage(bufferedImageLarge); * * Could use reflection to make calls in class com.apple.eawt.Application; for example, see * Bertil Chapuis' "dockicon.java" example code at https://gist.github.com/bchapuis/1562406 * * For now, we just won't do dock icons under Mac OS. * **/ } catch (Exception excepI) { System.err.println("Exception thrown trying to set icon: " + excepI); } } else { // The following has been tested under Windows 10 and Ubuntu 12.04 LTS try { // JPW 2018/02/02: changed how to load images to work under Java 9 InputStream imageInputStreamLarge = getClass().getClassLoader() .getResourceAsStream("Icon_128x128.png"); BufferedImage bufferedImageLarge = ImageIO.read(imageInputStreamLarge); InputStream imageInputStreamMed = getClass().getClassLoader().getResourceAsStream("Icon_64x64.png"); BufferedImage bufferedImageMed = ImageIO.read(imageInputStreamMed); InputStream imageInputStreamSmall = getClass().getClassLoader() .getResourceAsStream("Icon_32x32.png"); BufferedImage bufferedImageSmall = ImageIO.read(imageInputStreamSmall); List<BufferedImage> iconList = new ArrayList<BufferedImage>(); iconList.add(bufferedImageLarge); iconList.add(bufferedImageMed); iconList.add(bufferedImageSmall); guiFrame.setIconImages(iconList); } catch (Exception excepI) { System.err.println("Exception thrown trying to set icon: " + excepI); } } ctSettings = new CTsettings(this, guiFrame); guiFrame.setVisible(true); }
From source file:DefaultGraphics2D.java
/** * Intersects the current <code>Clip</code> with the interior of the * specified <code>Shape</code> and sets the <code>Clip</code> to the * resulting intersection. The specified <code>Shape</code> is transformed * with the current <code>Graphics2D</code> * <code>Transform</code> before * being intersected with the current <code>Clip</code>. This method is * used to make the current <code>Clip</code> smaller. To make the * <code>Clip</code> larger, use <code>setClip</code>. The <i>user clip</i> * modified by this method is independent of the clipping associated with * device bounds and visibility. If no clip has previously been set, or if the * clip has been cleared using/*w w w.j av a 2 s . co m*/ * {@link java.awt.Graphics#setClip(Shape) setClip} with a <code>null</code> * argument, the specified <code>Shape</code> becomes the new user clip. * * @param s * the <code>Shape</code> to be intersected with the current * <code>Clip</code>. If <code>s</code> is <code>null</code>, * this method clears the current <code>Clip</code>. */ public void clip(Shape s) { if (s != null) s = transform.createTransformedShape(s); if (clip != null) { Area newClip = new Area(clip); newClip.intersect(new Area(s)); clip = new GeneralPath(newClip); } else { clip = s; } }