aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/awt/geom
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@gcc.gnu.org>2004-09-02 05:10:34 +0000
committerGraydon Hoare <graydon@gcc.gnu.org>2004-09-02 05:10:34 +0000
commit57579172585eae4fd6f57c0dbd55ea998ddfb63f (patch)
treea420c1005dbef38d790847b62b0d57eb9bc758cb /libjava/java/awt/geom
parent1e8964cf94aa8b0e7176434d7b31fbf040416764 (diff)
downloadgcc-57579172585eae4fd6f57c0dbd55ea998ddfb63f.zip
gcc-57579172585eae4fd6f57c0dbd55ea998ddfb63f.tar.gz
gcc-57579172585eae4fd6f57c0dbd55ea998ddfb63f.tar.bz2
[multiple changes]
2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextAreaUI.java (create): New method. * javax/swing/text/DefaultHighlighter.java (DefaultHighlightPainter.debugRect): Removed. * javax/swing/text/StyleContext.java (DEFAULT_STYLE): New field. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicLookAndFeel.java (initComponentDefaults): Add keybindings for selection.backward and selection-forward for text components. * javax/swing/plaf/basic/BasicTextUI.java (paintSafely): Paint highlight only when something is actually selected. * javax/swing/text/DefaultCaret.java (handleHighlight): New method. (setSelectionVisible): Don't do anything when nothing changes. Handle highlight. (moveDot): Reimplemented. Handle highlight. (setDot): Set mark too. Handle highlight. (getSelectionPainter): New method. * javax/swing/text/DefaultEditorKit.java (defaultActions): Added new actions for text selection. * javax/swing/text/DefaultHighlighter.java (DefaultHighlightPainter): New inner class. (DefaultPainter): New field. (paint): Implemented. * javax/swing/text/PlainView.java (paint): Don't draw background here again. * javax/swing/text/Utilities.java (getTabbedTextWidth): Use width of ' ' instead of 'm' for tabsize. (drawTabbedText): Likewise. 2004-08-31 Graydon Hoare <graydon@redhat.com> * javax/swing/JComponent.java (resetKeyboardActions): Add null checks. 2004-08-31 Graydon Hoare <graydon@redhat.com> * javax/swing/DefaultButtonModel.java: Skip group notification when no group is set. 2004-08-31 Graydon Hoare <graydon@redhat.com> * javax/swing/JColorChooser.java: Make a couple inner classes static, for jikes. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (RottView.modelToView): New method. (UpdateHandler): Renamed from EventHandler. (updateHandler): Renamed from eventHandler. (modelToView): Implemented. * javax/swing/text/AbstractDocument.java (BranchElement.getElement): Return null for non-existing indeces. (BranchElement.getElementIndex): Return 0 in some corner cases. * javax/swing/text/FieldView.java (modelToView): New method. * javax/swing/text/PlainView.java (modelToView): Made public. 2004-08-31 Kim Ho <kho@redhat.com> * Makefile.am: New files. * Makefile.in: Regenerate. * gcj/Makefile.in: Regenerate. * include/Makefile.in: Regenerate. * java/awt/Color.java: Fix documentation. (RGBtoHSB): Use floats for conversions. * javax/swing/ButtonGroup.java: Run Jalopy. (setSelected): Reimplement. * javax/swing/DefaultButtonModel.java: Run Jalopy. (changeState): Let ButtonGroup know that the button is changing state. * javax/swing/JColorChooser.java: Implement. * javax/swing/JLabel.java: Run Jalopy. * javax/swing/JSpinner.java: Run Jalopy. (setValue): New method. * javax/swing/JTabbedPane.java: Run Jalopy. (removeTabAt): Call correct remove method. * javax/swing/SpinnerNumberModel.java: Run Jalopy. (getPreviousValue): Compare minimum value. * javax/swing/Timer.java: Run Jalopy. (run): Comment out println. * javax/swing/ToolTipManager.java: (mouseMoved): Get new tooltip text for location. * javax/swing/colorchooser/AbstractColorChooserPanel.java: Jalopy and Javadoc. * javax/swing/colorchooser/ColorChooserComponentFactory.java: Implement. * javax/swing/colorchooser/DefaultColorSelectionModel.java: Run Jalopy. (setSelectedColor): Fire ChangeEvent. * javax/swing/colorchooser/DefaultHSBChooserPanel.java: New file. Implement. * javax/swing/colorchooser/DefaultPreviewPanel.java: Ditto. * javax/swing/colorchooser/DefaultRGBChooserPanel.java: Ditto. * javax/swing/colorchooser/DefaultSwatchChooserPanel.java: Ditto. * javax/swing/plaf/basic/BasicArrowButton.java: (getArrow): Fix size of upward pointing button. * javax/swing/plaf/basic/BasicColorChooserUI.java: Implement. * javax/swing/plaf/basic/BasicSliderUI.java: (getWidthOfWidestLabel): Use preferred dimensions. (getHeightOfTallestLabel): Ditto. * javax/swing/plaf/basic/BasicSpinnerUI.java: Run Jalopy. (mousePressed): Disable changes to spinner if it is not enabled. * testsuite/Makefile.in: Regenerate. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTableHeaderUI.java, javax/swing/plaf/basic/BasicTableUI.java: Added copyright notice. 2004-08-31 Olga Rodimina <rodimina@redhat.com> * Makefile.am: Added new files. * Makefile.in: Regenerate. * javax/swing/ComboBoxEditor.java: Added javadocs. * javax/swing/ComboBoxModel.java: Likewise. * javax/swing/DefaultComboBoxModel.java: Implemented. * javax/swing/DefaultListCellRenderer.java: Added javadocs and ran through jalopy to fix formatting style. (getListCellRendererComponent): Use appropriate border if renderer has focus and use noFocusBorder when it doesn't. * javax/swing/JComboBox.java: Implemented. * javax/swing/JList.java: (locationToIndex): New Method. Implemented. (indexToLocation): New Method. * javax/swing/JPopupMenu.java: (visible): New field. (isVisible): Changed to use new field above. (setVisible): Likewise. * javax/swing/MutableComboBoxModel.java: Added javadocs. * javax/swing/plaf/basic/BasicArrowButton.java: (shadow): Changed default color to Color.gray. * javax/swing/plaf/basic/BasicComboBoxUI.java: New File. UI delegate for JComboBox. * javax/swing/plaf/basic/BasicComboPopup.java: New File. Popup menu containing list of JComboBox's items. * javax/swing/plaf/basic/BasicComboBoxEditor.java: New File. * javax/swing/plaf/basic/BasicComboBoxRenderer.java: New File. * javax/swing/plaf/basic/BasicComboBoxUI.java: New File. * javax/swing/plaf/basic/BasicComboPopup.java: New File. * javax/swing/plaf/basic/BasicPopupMenuUI.java: (popupMenuWillBecomeVisible): Set selected path to the first element only if it is of type MenuElement. Also fix formatting style. * javax/swing/plaf/basic/ComboPopup.java: Added javadocs and missing methods signatures. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/AbstractDocument.java (createBranchElement): Use new constructor of BranchElement. (createLeafElement): Renamed arguments. (getRootElements): Implemented. (BranchElement.start): Removed. (BranchElement.end): Likewise. (BranchElement.BranchElement): Fixed arguments. (BranchElement.getEndOffset): Reimplemented. (BranchElement.getStartOffset): Likewis. * javax/swing/text/DefaultCaret.java (paint): Draw simple vertical line as caret instead of a rectangle. * javax/swing/text/JTextComponent.java (setText): Use doc directly. * javax/swing/text/PlainView.java (nextTabStop): Implemented. * javax/swing/text/Utilities.java (drawTabbedText): nextTabStop() returns an absolute x position. (getTabbedTextWidth): Likewise. 2004-08-31 Graydon Hoare <graydon@redhat.com> * java/awt/Component.java (isFocusTraversable): Predicate on isLightweight() (setFocusable): Set isFocusTraversableOverridden. (requestFocus): Predicate peer dispatch on !isLightweight() (requestFocusInWindow): Likewise. (dispatchEventImpl): Coordinate with KeyboardFocusManager. * java/awt/Container.java (dispatchEventImpl): Predicate on event mask. (LightweightDispatcher): Remove focus machinery. * java/awt/DefaultFocusTraversalPolicy.java (accept): Expand predicate to include isFocusable(). * java/awt/DefaultKeyboardFocusManager.java: Globally change c.dispatchEvent(e) to redispatchEvent(c,e) * java/awt/KeyboardFocusManager.java (redispatchEvent): Synchronize on event to prevent feedback. * javax/swing/AbstractButton.java (ButtonFocusListener): Remove class. (init): Set focusPainted, focusable. * javax/swing/ActionMap.java (get): Check parent for null. * javax/swing/InputMap.java (get): Likewise. * javax/swing/JComponent.java (inputMap_whenFocused): New InputMap. (inputMap_whenAncestorOfFocused): Likewise. (inputMap_whenInFocusedWindow): Likewise. (getActionForKeyStroke): Rewrite. (getConditionForKeystroke): Likewise. (ActionListenerProxy): New private class. (setInputMap): Implement. (getInputMap): Likewise. (setActionMap): Likewise. (getActionMap): Likewise. (processComponentKeyEvent): New empty method. (processKeyEvent): Implement. (processKeyBinding): Likewise. (resetKeyboardActions): Rewrite. * javax/swing/KeyStroke.java: Rewrite. * javax/swing/SwingUtilities.java (notifyAction): Implement. (replaceUIActionMap): Likewise. (replaceUIInputMap): Likewise. * javax/swing/plaf/basic/BasicButtonListener.java (focusGained): Implement. (focusLost): Repaint if focusPainted(). (installKeyboardActions): Install pressed / released actions. (uninstallKeyboardActions): Implement. * javax/swing/plaf/basic/BasicButtonUI.java (focusColor): New field. (installDefaults): Load focus color, install input map. (installKeyboardActions): Implement. (uninstallKeyboardActions): Likewise. (paintFocus): Rewrite. * javax/swing/plaf/basic/BasicLookAndFeel.java (Button.focus): New default, midPurple. * javax/swing/plaf/basic/BasicTextUI.java (kit): Make static. (installUI): Get doc from kit, load defaults. (getKeymapName): Implement. (createKeymap): Likewise. (installKeyboardActions): Likewise. (getInputMap): Likewise. (getActionMap): Likewise. (createActionMap): Likewise. * javax/swing/text/AbstractDocument.java (getStartPosition): Implement. (getEndPosition): Likewise. * javax/swing/text/DefaultEditorKit.java (CopyAction): New class. (CutAction): Likewise. (DefaultKeyTypedAction): Likewise. (InsertBreakAction): Likewise. (InsertContentAction): Likewise. (InsertTabAction): Likewise. (PasteAction): Likewise. (defaultActions): New static table. (createCaret): Implement. (getActions): Likewise. * javax/swing/text/JTextComponent.java (KeymapWrapper): New private class. (KeymapActionMap): Likewise. (DefaultKeymap): New class. (keymaps): New static table. (keymap): New field. (getKeymap): Implement. (removeKeymap): Likewise. (addKeymap): Likewise. (setKeymap): Likewise. (loadKeymap): Likewise. (getActions): Likewise. (margin): New field. (JTextComponent): Build and install default keymap. * javax/swing/text/TextAction.java (textAction): Call super properly. (getTextComponent): Implement. * javax/swing/text/Utilities.java (drawTabbedText): Adjust position by ascent. 2004-08-31 David Jee <djee@redhat.com> PR AWT/17156 * gnu/java/awt/peer/gtk/GtkMenuItemPeer.java (setEnabled): Make it a native method. * java/awt/DefaultKeyboardFocusManager.java (postProcessKeyEvent): Only post event if the menu item is active. * java/awt/MenuItem.java: Private field 'enabled' should be true by default. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuItemPeer.c (setEnabled): New function. 2004-08-31 David Jee <djee@redhat.com> PR AWT/17059 * gnu/java/awt/peer/gtk/GtkMenuBarPeer.java (nativeSetHelpMenu): New native method declaration. (addHelpMenu): Call nativeSetHelpMenu(). (addMenu): Remove. * java/awt/MenuBar.java (setHelpMenu): Call addNotify() on the new help menu. (add): Call addNotify() on the new menu. (addNotify): Set the help menu if one exists. * java/awt/peer/MenuBarPeer.java (addMenu): Remove. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuBarPeer.c (nativeSetHelpMenu): New method. 2004-08-31 Graydon Hoare <graydon@redhat.com> * Makefile.am: Add new files. * Makefile.in: Regenerate. * javax/swing/Box.java: Fix setting of layout in ctor. * javax/swing/JScrollPane.java: Scroll headers as well. * javax/swing/JTable.java: Reimplement. * javax/swing/JViewPort.java: Only add non-null children. * javax/swing/ScrollPaneLayout.java: Correct header calculations. * javax/swing/Timer.java: Fix stopping null waker. * javax/swing/plaf/basic/BasicTableHeaderUI.java: New file. * javax/swing/plaf/basic/BasicTableUI.java: New file. * javax/swing/table/DefaultTableCellRenderer.java: Configure. * javax/swing/table/DefaultTableColumnModel.java: Flesh out. * javax/swing/table/DefaultTableModel.java: Clean up. * javax/swing/table/JTableHeader.java: Implement. 2004-08-31 Mark Wielaard <mark@klomp.org> * javax/swing/JSpinner.java (getChangeListeners): Remove double semi-colon. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c: Declare variables at top of functions/block. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c: Likewise. 2004-08-31 Mark Wielaard <mark@klomp.org> * java/lang/Rectangle.java (intersects): Check r.width and r.height first. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/PlainView.java (selectedColor): New field. (unselectedColor): Likewise. (font): Likewise. (updateMetrics): New method. (lineToRect): Likewise. (modelToView): Likewise. (drawSelectedText): Use color from JTextComponent ad draw with Utilities class. (drawUnselectedText): Likewise. (paint): Initialize helper fields. * javax/swing/text/View.java (getChildAllocation): New method. (getViewIndex): Likewise. (getToolTipText): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/Utilities.java (drawTabbedText): Reimplemented. (getTabbedTextWidth): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (installDefaults): Install caret and highlighter. (modelToView): Use Bias.Forward when calling sibling. * javax/swing/text/AbstractDocument.java (ElementEdit): Implements DocumentEvent.ElementChange. (ElementEdit.ElementEdit): New method. (ElementEdit.getChildrenAdded): Likewise. (ElementEdit.getChildrenRemoved): Likewise. (ElementEdit.getElement): Likewise. (ElementEdit.getIndex): Likewise. * javax/swing/text/DefaultCaret.java (color): Removed. (textComponent): Renamed from parent, made private. (selectionVisible): Renamed from vis_sel, made private. (blinkRate): Renamed from blink, made private. (magicCaretPosition): Renamed from magic, made private. (visible): Renamed from vis, made private. (dot): Made private. (mark): Likewise. (deinstall): Remove as MouseMotionListener. (install): Initialize textComponent first. Add as MouseMotionListener. (paint): Reimplemented. * javax/swing/text/JTextComponent.java (setCaret): Deinstall old caret, install new one and fire property change after setting property. (setHighlighter): Deinstall old highlighter, install new one and fire property change after setting property. (setCaretColor): Fire property change after setting property. (setDisabledTextColor): Likewise. (setSelectedTextColor): Likewise. (setSelectionColor): Likewise. (modelToView): New method. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/AbstractDocument.java (getText): Simplified. * javax/swing/text/Segment.java (current): New field. (current): Reimplemented. (first): Likewise. (getIndex): Likewise. (last): Likewise. (next): Likewise. (previous): Likewise. (setIndex): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicButtonUI.java (defaultTextIconGap): Made protected. (defaultTextShiftOffset): Likewise. (textShiftOffset): New field. (clearTextShiftOffset): New method. (getTextShiftOffset): Likewise. (setTextShiftOffset): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (installUI): Add eventHandler as property listener. (uninstallUI): remove eventHandler as propert listener. (installDefaults): Added comment. (installListeners): Likewise. (installKeyboardActions): Likewise. (uninstallDefaults): Likewise. (uninstallListeners): Likewise. (uninstallKeyboardActions): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/AbstractDocument.java: Fixed some typos in comments. (insertString): Reimplemented. (remove): Likewise. (replace): New method. (children): Dont use fully qualified class name. (DefaultDocumentEvent.offset): Renamed from off. (DefaultDocumentEvent.length): Renamed from len. (DefaultDocumentEvent.type): New field. (DefaultDocumentEvent.DefaultDocumentEvent): New constructor. (DefaultDocumentEvent.getType): Implemented. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (RootView.textComponent): Removed. (RootView.RootView): Don't initialize textComponent. (RootView.getViewFactory): New method. (EventHandler): New inner class. (rootView): Initialize at instance creation. (eventHandler): New field. (installUI): Don't create view hierarchy directly, call modelChanged() instead. (modelChanged): New method. * javax/swing/text/JTextComponent.java (setDocument): Fire property change event. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicTextUI.java (RootView.paint): Removed debug output. (paintSafely): Draw highlighter before text. (paintBackground): Use background color of text component. * javax/swing/plaf/basic/BasicToggleButtonUI.java: Reformatted. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicToolBarUI.java (BasicToolBarUI): Fixed arguments for constructor. (createUI): Fixed creation of object. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/DefaultListSelectionModel.java (fireValueChanged): Renamed from fireSelectionValueChanged, made protected. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/text/TabSet.java (TabSet): Implements java.io.Serializable. * javax/swing/text/TabStop.java (TabStop): Implements java.io.Serializable. (TabStop): Made public. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/JComponent.java (setUI): Fire PropertyChange. * javax/swing/JLabel.java (text): Renamed from labelText. (horizontalAlignment): New default vlaue. (icon): Renamed from activeIcon. (displayedMnemonic): Renamed from mnemonicKey, added default value. (displayedMnemonicIndex): Renamed from underlineChar. (setDisplayedMnemonic): Reimplemented. * javax/swing/JRadioButton.java (JRadioButton): New constructors. * javax/swing/JTextField.java (JTextField): Throw exception if colums < 0, initialitialz this.columns directly and initialize document with text conditionally. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicFormattedTextFieldUI.java, javax/swing/plaf/basic/BasicPasswordFieldUI.java, javax/swing/plaf/basic/BasicTextAreaUI.java: New files. * javax/swing/text/FieldView.java (paint): Just call super method for now. * Makefile.am: Added new files. * Makefile.in: Regenerated. 2004-08-31 Ka-Hing Cheung <kahing@javabsp.org> * javax/swing/AbstractSpinnerModel.java, javax/swing/JSpinner.java, javax/swing/SpinnerNumberModel.java, javax/swing/plaf/basic/BasicSpinnerUI.java: New files. * javax/swing/plaf/basic/BasicLookAndFeel.java (initClassDefaults): Added defaults for BasicSpinnerUI. 2004-08-31 Michael Koch <konqueror@gmx.de> * Makefile.am: Added new files. * Makefile.in: Regenerated. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/TransferHandler.java, javax/swing/plaf/basic/ComboPopup.java: New files * Makefile.am: Added javax/swing/TransferHandler.java and javax/swing/plaf/basic/ComboPopup.java * Makefile.in: Regenerated. 2004-08-31 Roman Kennke <roman@ontographics.com> * javax/swing/text/Utilities.java: New file. 2004-08-31 Michael Koch <konqueror@gmx.de> * Makefile.am: Added javax/swing/text/Utilities.java. * Makefile.in: Regenerated. 2004-08-31 Graydon Hoare <graydon@redhat.com> * javax/swing/text/SimpleAttributeSet.java: New file. * javax/swing/text/StyleConstants.java: New file. * javax/swing/text/StyleContext.java: New file. * javax/swing/text/TabSet.java: New file. * javax/swing/text/TabStop.java: New file. * javax/swing/text/AbstactDocument.java: (AbstractElement): Implement attribute support. * javax/swing/text/AttributeSet.java (NameAttribute): New static field. (ResolveAttribute): New static field. * Makefile.am: Update for new files. * Makefile.in: Regenerate. 2004-08-31 Craig Black <craig.black@aonix.com> * gnu/java/awt/peer/gtk/GdkGraphics.java (drawImage): Add support for scaling pixmaps. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c (copyAndScalePixmap): New native method. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> PR AWT/16121 * jni/gtk-peer/gthread-jni.c: Include stdio.h. Eliminate type-punning compiler warnings using unions. (throw): Replace bzero with memset. 2004-08-31 Andreas Tobler <a.tobler@schweiz.ch> Thomas Fitzsimmons <fitzsim@redhat.com> * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c: Move NSA_PB macros to gtkpeer.h. Include gtkpeer.h. * jni/gtk-peer/gtkpeer.h: Move NSA_PB macros here. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (nativeSetIconImageFromDecoder): Use NSA_GET_PB_PTR macro. 2004-08-31 Mark Wielaard <mark@klomp.org> * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkPixbufDecoder.c: #include gdk.h, not gtk.h. #include jni.h, native_state.h, string.h and stdlib.h, not gtkpeer.h. (*vm): New static variable. (areaPreparedID): Make static. (areaUpdatedID): Likewise. (area_prepared): Get and use JNIEnv through stored JavaVM *vm. (area_prepared): Likewise. (area_updated): Likewise. (closed): Likewise. (initStaticState): Initialize *vm javaVM. (pumpBytes): Use given env, not global gdk_env. 2004-08-31 Mark Wielaard <mark@klomp.org> * java/awt/geom/CubicCurve2D.java (solveCubic): Removed duplicate comments. 2004-08-31 Sven de Marothy <sven@physto.se> * java/awt/geom/CubicCurve2D.java: Reindent. (contains): Implemented. (intersects): Implemented. * java/awt/geom/QuadCurve2D.java: Likewise. * java/awt/geom/GeneralPath.java: Reindent and document. Fully (re)implemented using separate xpoints and ypoints float[] coords. * java/awt/geom/RoundRectangle2D.java: Several bugfixes (Bug #6007). 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/JMenuItem.java (getMenuDragMouseListeners): New method. (getMenuKeyListeners): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/AbstractButton.java (model): Made protected. (actionListener): Likewise. (changeListener): Likewise. (itemListener): Likewise. (multiClickThreshhold): New field. (getActionListeners): New method. (getChangeListeners): Likewise. (getItemListeners): Likewise. (fireItemStateChanged): Simplified implementation. (fireActionPerformed): Likewise. (fireStateChanged): Likewise. (getMultiClickThreshhold): New method. (setMultiClickThreshhold): Likewise. 2004-08-31 Tom Tromey <tromey@redhat.com> * java/awt/image/Kernel.java (clone): Use super.clone(). 2004-08-31 David Jee <djee@redhat.com> PR AWT/16682 * gnu/java/awt/peer/gtk/GtkFramePeer.java (nativeSetIconImage): Rename to nativeSetIconImageFromDecoder. (nativeSetIconImageFromData): New native method declaration. (setIconImage): Handle images not produced from GdkPixbufDecoder. * gnu/java/awt/peer/gtk/GtkImage.java (getPixelCache): New method. (getColorModel): New method. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (nativeSetIconImage): Rename to nativeSetIconImageFromDecoder. (free_pixbuf_data): New helper function. (nativeSetIconImageFromData): New function. 2004-08-31 Graydon Hoare <graydon@redhat.com> PR SWING/16576 * javax/swing/JLayeredPane.java (setLayer): Permit changing layer after addition. (setPosition): Permit over-length positions. (layerToRange): Compare intValue()s. * javax/swing/Box.java (createHorizontalBox): Implement. (createRigidArea): Likewise. (createVerticalBox): Likewise. 2004-08-31 Kim Ho <kho@redhat.com> * java/awt/Component.java: (processMouseEvent): Consume event after listeners process it. (processMouseMotionEvent): ditto. (processMouseWheelEvent): ditto. * java/awt/Container.java: (acquireComponentForMouseEvent): Do not dispatch to events that have been removed from the Container. (handleEvent): Consume the MouseEvents. * javax/swing/RepaintManager.java: (paintDirtyRegions): Do not add to list of damaged areas if the component has no root. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/plaf/basic/BasicMenuItemUI.java: Clean ip imports. 2004-08-31 Mark Wielaard <mark@klomp.org> * gnu/java/awt/peer/gtk/GtkToolkit.java (getFontPeer): Don't return null when a MissingResourceException is thrown. Should never happen. 2004-08-31 Mark Wielaard <mark@klomp.org> * java/awt/EventQueue.java (postEvent): Throw NullPointerException when argument is null. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (Java_gnu_java_awt_peer_gtk_GtkComponentPeer_addExposeFilter): Define hid at start of function. (Java_gnu_java_awt_peer_gtk_GtkComponentPeer_removeExposeFilter): Likewise. 2004-08-31 Mark Wielaard <mark@klomp.org> * gnu/java/awt/EmbeddedWindow.java: Reindent. * javax/swing/JButton.java: Reindent. * javax/swing/JCheckBox.java: Reindent. 2004-08-31 Mark Wielaard <mark@klomp.org> * Makefile.am (gtk_c_source_files): Added jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c. (gtk_awt_peer_sources): Added gnu/java/awt/peer/gtk/GThreadMutex.java and gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java. * Makefile.in: Regenerated. 2004-08-31 Archie Cobbs <archie@dellroad.org> * jni/gtk-peer/gthread-jni.c: don't #include nonexistent files 2004-08-31 Steven Augart <augart@watson.ibm.com> * jni/gtk-peer/gthread-jni.c (c-font-lock-extra-types): Added jfieldID, jmethodID. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c (Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit): Initialize gdk_env before calling any gdk or gtk function. * gnu/java/awt/peer/gtk/GtkMainThread.java (gtkInitCalled): New field. (GtkMainThread): Call wait() in while loop waiting for gtkInitCalled. (run): Set gtkInitCalled. 2004-08-31 Steven Augart <augart@watson.ibm.com> * gnu/java/awt/peer/gtk/GtkMainThread.java (run): Pass the value of the gnu.classpath.awt.gtk.portable.native.sync system property to C. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c (Java_gnu_java_awt_peer_gtk_GtkMainThread_gtkInit): New argument, portableNativeSync. Delegate PORTABLE_NATIVE_SYNC work to init_glib_threads. (init_glib_threads): New function. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gthread-jni.c: Define MIN_, MAX_ and NORM_ PRIORITY when not already defined in header file. 2004-08-31 Mark Wielaard <mark@klomp.org> * jni/gtk-peer/gthread-jni.c (setup_cache): Call ExceptionOccurred, not ExceptionCheck, when we don't have JNI 1.2. 2004-08-31 Steven Augart <augart@watson.ibm.com> * gnu/native/jni/gtk-peer/gthread-jni.c: Indentation fixes. Implemented missing functions for GTK2. Added error handling. Renamed static functions out of the g_ namespace. Added TRACE_API_CALLS, EXPLAIN_TROUBLE, EXPLAIN_BROKEN, EXPLAIN_BADLY_BROKEN, and DELETE_LOCAL_REFS options. Rewrote global-reference code. Eliminated cascading errors. (mutex_trylock_jni_impl) Fully implemented. (cond_timed_wait_jni_impl) Went from millisecond to microsecond resolution. (setup_cache) New function. (mutex_cond_wait_jni_impl, mutex_cond_timed_wait_jni_impl) Fixed bug where they were not unlocking the GMutex associated with the condition variable during the wait on that condition variable. * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c, native/jni/gtk-peer/gthread-jni.c, native/jni/gtk-peer/gthread-jni.h (g_thread_jni_functions): Renamed to ... (portable_native_sync_jni_functions): this name. (gdk_vm): Renamed to... (the_vm): this name. * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMainThread.c (gdk_vm): Removed duplicate definition. (gtkInit): Removed stray message to stdout. (gtkInit): Use g_malloc and g_free instead of malloc and free. (gtkInit): Fix a const assignment bug. (gtkInit): Simplified code. * gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java, native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.c, native/jni/gtk-peer/gnu_java_awt_peer_gtk_GThreadNativeMethodRunner.h, gnu/java/awt/peer/gtk/GThreadMutex.java: New files. 2004-08-31 Mark Wielaard <mark@klomp.org> * javax/swing/Box.java: Put FIXME comment above class declaration. * javax/swing/JButton.java: Remove illegal L&F HTML from comments. * javax/swing/JCheckBox.java: Likewise. * javax/swing/JDialog.java: Likewise. * javax/swing/JRadioButton.java: Likewise. * javax/swing/JToggleButton.java: Likewise. * javax/swing/UIManager.java: Likewise. * javax/swing/border/TitledBorder.java: Likewise. * javax/swing/plaf/basic/BasicLabelUI.java: Likewise. * javax/swing/plaf/basic/BasicLookAndFeel.java: Likewise. * javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java: Likewise. * javax/swing/plaf/basic/BasicProgressBarUI.java: Likewise. * javax/swing/plaf/basic/BasicScrollBarUI.java: Likewise. * javax/swing/plaf/basic/BasicSeparatorUI.java: Likewise. * javax/swing/text/JTextComponent.java: Likewise. 2004-08-31 David Jee <djee@redhat.com> PR AWT/16682 * gnu/java/awt/peer/gtk/GtkFramePeer.java (setIconImage): Add a FIXME for unhandled cases. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> PR AWT/16040 * gnu/awt/LightweightRedirector.java: Call getModifiersEx, not getModifiers. Replace old button masks with new ones. * gnu/awt/xlib/XEventLoop.java: Likewise. * gnu/java/awt/peer/gtk/GtkButtonPeer.java: Likewise. * gnu/java/awt/peer/gtk/GtkComponentPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c: Likewise. * gnu/java/awt/peer/gtk/GtkListPeer.java: Likewise. * gnu/java/awt/peer/gtk/GtkTextFieldPeer.java: Likewise. * java/awt/AWTKeyStroke.java: Remove old modifier masks. * java/awt/Component.java: Replace old modifier masks with new ones. * java/awt/Container.java: Call getModifiersEx, not getModifiers. * java/awt/DefaultKeyboardFocusManager.java: Likewise. Remove old modifier masks. * javax/swing/JMenuItem.java: Replace old button masks with new ones. * javax/swing/KeyStroke.java: Call getModifiersEx, not getModifiers. * javax/swing/SwingUtilities.java: Likewise. * javax/swing/plaf/basic/BasicButtonListener.java: Likewise. * javax/swing/plaf/basic/BasicInternalFrameUI.java: Likewise. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c: Replace old mask macros with new ones. * jni/gtk-peer/gtkpeer.h: Replace old button and modifier mask macros with new ones representing new masks. 2004-08-31 Craig Black <craig.black@aonix.com> * gnu/java/awt/peer/gtk/GdkGraphics.java (drawRoundRect): Implemented. (fillRoundRect): Implemented. * gnu/java/awt/peer/gtk/GdkGraphics2D.java (drawRoundRect): Reimplemented to match GdkGraphics. (fillRoundRect): Reimplemented to match GdkGraphics. 2004-08-31 Mark Wielaard <mark@klomp.org> * Makefile.in: Regenerated. 2004-08-31 Michael Koch <konqueror@gmx.de> * gnu/java/awt/EmbeddedWindow.java (addNotify): Use AccessController to allow execution of privileged code. 2004-08-31 Michael Koch <konqueror@gmx.de> * gnu/java/awt/EmbeddedWindow.java (static): Removed. (addNotify): Set peer via reflection. (setWindowPeer): Removed. * gnu/java/awt/natEmbeddedWindow.cc: Removed. * Makefile.am (nat_source_files): Removed gnu/java/awt/natEmbeddedWindow.cc. 2004-08-31 Bryce McKinlay <mckinlay@redhat.com> * Makefile.am: Add gnu/java/security/action/GetPropertyAction.java and gnu/java/security/action/SetAccessibleAction.java. 2004-08-31 Bryce McKinlay <mckinlay@redhat.com> * gnu/java/security/action/GetPropertyAction.java (setParameters): Renamed from 'setName'. New 2-argument form with default value. (run): Pass default 'value' parameter to System.getProperty(). * gnu/java/security/action/SetAccessibleAction.java: Fix javadoc typos. 2004-08-31 Bryce McKinlay <mckinlay@redhat.com> * gnu/java/security/action/GetPropertyAction.java: New class. * gnu/java/security/action/SetAccessibleAction.java: New class. 2004-08-31 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkFramePeer.java (setIconImage): Check if image is null. 2004-08-31 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkFramePeer.java (create): Set the icon image. (nativeSetIconImage): New native method declaration. (setIconImage): Implement. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (nativeSetIconImage): New function. 2004-08-31 Dalibor Topic <robilad@kaffe.org> * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkFileDialogPeer.c (filenameFilterCallback): Declare local variable accepted before use. 2004-08-31 Dalibor Topic <robilad@kaffe.org> * gnu/java/awt/ComponentDataBlitOp.java: Cleaned up imports. 2004-08-31 Tom Tromey <tromey@redhat.com> * gnu/java/awt/peer/GLightweightPeer.java, gnu/java/awt/peer/gtk/GdkGraphics2D.java, gnu/java/awt/peer/gtk/GtkComponentPeer.java, javax/swing/JScrollPane.java: Removed redundant imports. 2004-08-31 David Jee <djee@redhat.com> * java/awt/DefaultKeyboardFocusManager.java (postProcessKeyEvent): Only activate MenuShortcuts on KEY_PRESSED event. Fix shift modifier checking. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c (accel_attach): Remove. (setupAccelGroup): Remove calls to accel_attach. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkArg.java: Remove file. * gnu/java/awt/peer/gtk/GtkArgList.java: Remove file. * Makefile.am (gtk_awt_peer_sources): Remove GtkArg.java and GtkArgList.java. (gtk_c_files): Use CAIRO_CFLAGS and PANGOFT2_CFLAGS, not _LIBS. * Makefile.in: Regenerate. * gnu/java/awt/peer/gtk/GtkButtonPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkButtonPeer.c (create(String)): New method. (create): Call new create method. (getArgs): Remove method. * gnu/java/awt/peer/gtk/GtkCheckboxPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c (nativeCreate): Rename to create. (gtkSetLabel): Rename to gtkButtonSetLabel. (gtkToggleButtonSetActive): New method. (create): Call gtkToggleButtonSetActive and gtkButtonSetLabel. (setState): Replace set call with gtkToggleButtonSetActive. (setLabel): Replace gtkSetLabel call with gtkButtonSetLabel. (getArgs): Remove method. * gnu/java/awt/peer/gtk/GtkComponentPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (gtkWidgetSetSensitive): New method. (gtkWidgetSetParent): Likewise. (GtkComponentPeer): Call setParent, setComponentBounds and setVisibleAndEnabled. (setParent): New method. (setComponentBounds): New method. (setVisibleAndEnabled): New method. (setEnabled): Call gtkWidgetSetSensitive. (getArgs): Remove method. Remove all set methods. * gnu/java/awt/peer/gtk/GtkDialogPeer.java (create): Call gtkWindowSetModal, setTitle and setResizable. (getArgs): Remove method. * gnu/java/awt/peer/gtk/GtkFileDialogPeer.java (setComponentBounds): New method. * gnu/java/awt/peer/gtk/GtkFramePeer.java (setResizable): Replace set call with gtkWindowSetResizable. (getArgs): Remove method. (create): Call setTitle and setResizable. * gnu/java/awt/peer/gtk/GtkWindowPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (gtkWindowSetTitle): New method. (gtkWindowSetResizable): New method. (gtkWindowSetModal): New method. (setParent): New method. (setVisibleAndEnabled): New method. (getArgs): Remove method. (setTitle): Call gtkWindowSetTitle. (setResizable): Call gtkWindowSetResizable. * jni/gtk-peer/gtkpeer.h [DEBUG_LOCKING]: New define to turn on and off locking instrumentation. 2004-08-31 Kim Ho <kho@redhat.com> * Makefile.am: Add new file. * Makefile.in: Regenerate. * gcj/Makefile.in: Regenerate * include/Makefile.in: * java/awt/Container.java: (acquireComponentForMouseEvent): Respect the event mask when looking for candidate. * javax/swing/JComponent.java: Remove toolTip field. (createToolTip): Create a tooltip on demand. (setToolTipText): Register with the ToolTipManager. (getToolTipText(MouseEvent)): Return getToolTipText(). * javax/swing/JToolTip.java: Implement. * javax/swing/Timer.java: Jalopy. (restart): Call stop, then start. (stop): Interrupt the timer rather than wait for the timer to come to a stop naturally. * javax/swing/ToolTipManager.java: Implement. * javax/swing/plaf/basic/BasicLookAndFeel.java: Change ToolTip.background color. * javax/swing/plaf/basic/BasicToolTipUI.java: Implement. * testsuite/Makefile.in: Regenerate 2004-08-31 Jerry Quinn <jlquinn@optonline.net> * java/awt/image/DirectColorModel.java (DirectColorModel): Fix constructor param comments. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> * java/awt/Component.java: Document AWT 1.0 event handler methods. 2004-08-31 Roman Kennke <roman@ontographics.com> * javax/swing/Box.java: (createGlue): Implemented (createHorizontalGlue): Implemented (createHorizontalStrut): Implemented (createVerticalGlue): Implemented (createVerticalStrut): Implemented 2004-08-31 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkChoicePeer.java (GtkChoicePeer): Do not automatically select first item. (getHistory): Remove. (nativeGetSelected): New method. (nativeRemoveAll): New method. (add): Use nativeGetSelected() instead of getHistory(). (remove): Likewise. (removeAll): Call nativeRemoveAll(). * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkChoicePeer.c (create): Migrate to GtkComboBox. (append): Likewise. (nativeAdd): Likewise. (nativeRemove): Likewise. (select): Likewise. (nativeRemoveAll): New method. (nativeGetSelected): New method. (selection_changed): New method. (getHistory): Remove. (item_activate): Remove. (item_removed): Remove. (connect_choice_item_selectable_hook): Remove. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GtkTextFieldPeer.java (create): Use tf variable in setEditable call. * gnu/java/awt/peer/gtk/GtkTextFieldPeer.java, jni/gtk-peer/gnu_java_awt_peer_gtk_GtkTextFieldPeer.c (gtkWidgetSetBackground): New method. (gtkWidgetSetForeground): Likewise. (create): Set peer's editable state based on awtComponent's. * java/awt/Button.java (Button()): Use empty string rather than null in no-label constructor. 2004-08-31 Roman Kennke <roman@ontographics.com> * javax/swing/BoxLayout.java: Reimplement. 2004-08-31 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics.java, gnu_java_awt_peer_gtk_GdkGraphics.c (initState(GtkComponentPeer)): Don't return array of colour values. (GdkGraphics(int,int)): Set default font to size 12. (GdkGraphics(GtkComponentPeer)): Set graphics colour to component's foreground colour. * gnu/java/awt/peer/gtk/GdkGraphics2D.java, gnu_java_awt_peer_gtk_GdkGraphics2D.c (initState(GtkComponentPeer)): Don't return array of colour values. (GdkGraphics2D(GtkComponentPeer)): Set foreground and background colours to component's colours. (current_colors_of_widget): Remove function. * gnu/java/awt/peer/gtk/GtkOffScreenImage.java (getGraphics): Return a new graphics object. * java/awt/Font.java (toString): Fix format. * java/awt/Graphics.java (toString): Likewise. 2004-08-31 Craig Black <craig.black@aonix.com> * native/jni/gtk-peer/gnu_java_awt_peer_gtk_GtkMenuPeer.c (addTearOff): New function. * gnu/java/awt/peer/gtk/GtkMenuPeer.java (addTearOff): New native method. (init): Call addTearOff() when menu.isTearOff(). 2004-08-31 Bryce McKinlay <mckinlay@redhat.com> * gnu/java/awt/ClasspathToolkit.java (createImageProducer): New. Default implementation. * gnu/java/awt/peer/gtk/GtkToolkit.java (createImageProducer): New. Implement using GdkPixbufDecoder. 2004-08-31 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkComponentPeer.java (GtkComponentPeer): Use gtkWidgetGetPreferredDimensions() for setting the size of GtkFileDialogPeers. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (gtkWidgetGetPreferredDimensions): For widgets extending GtkWindow, use their default sizes rather than their natural requisitions. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/JFormattedTextField.java (JFormattedTextField): Implemented. * javax/swing/text/DefaultEditorKit.java (BeepAction): New inner class. * javax/swing/text/Segment.java (partialReturn): New field. (setPartialReturn): New method. (isPartialReturn): Likewise. * javax/swing/text/View.java (createFragment): Fixed typo. (getStartOffset): New method. (getEndOffset): Likewise. 2004-08-31 Michael Koch <konqueror@gmx.de> * javax/swing/table/DefaultTableColumnModel.java (serialVersionUID): Made private. (listenerList): Initialize. (changeEvent): Initialize. * javax/swing/table/JTableHeader.java (JTableHeader): New constructors. (createDefaultColumnModel): New method. * javax/swing/table/TableColumn.java (setHeaderRenderer): Simplified code. (setCellRenderer): Likewise. (setWidth): Likewise. From-SVN: r86956
Diffstat (limited to 'libjava/java/awt/geom')
-rw-r--r--libjava/java/awt/geom/CubicCurve2D.java667
-rw-r--r--libjava/java/awt/geom/GeneralPath.java839
-rw-r--r--libjava/java/awt/geom/QuadCurve2D.java578
-rw-r--r--libjava/java/awt/geom/RoundRectangle2D.java346
4 files changed, 1534 insertions, 896 deletions
diff --git a/libjava/java/awt/geom/CubicCurve2D.java b/libjava/java/awt/geom/CubicCurve2D.java
index 096e7ad..56b90e9 100644
--- a/libjava/java/awt/geom/CubicCurve2D.java
+++ b/libjava/java/awt/geom/CubicCurve2D.java
@@ -1,5 +1,5 @@
/* CubicCurve2D.java -- represents a parameterized cubic curve in 2-D space
- Copyright (C) 2002, 2003 Free Software Foundation
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -35,7 +35,6 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-
package java.awt.geom;
import java.awt.Rectangle;
@@ -53,12 +52,14 @@ import java.util.NoSuchElementException;
* @author Eric Blake (ebb9@email.byu.edu)
* @author Graydon Hoare (graydon@redhat.com)
* @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
*
* @since 1.2
*/
-public abstract class CubicCurve2D
- implements Shape, Cloneable
+public abstract class CubicCurve2D implements Shape, Cloneable
{
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+
/**
* Constructs a new CubicCurve2D. Typical users will want to
* construct instances of a subclass, such as {@link
@@ -68,87 +69,74 @@ public abstract class CubicCurve2D
{
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s start
* point.
*/
public abstract double getX1();
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s start
* point.
*/
public abstract double getY1();
-
/**
* Returns the curve&#x2019;s start point.
*/
public abstract Point2D getP1();
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s first
* control point.
*/
public abstract double getCtrlX1();
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s first
* control point.
*/
public abstract double getCtrlY1();
-
/**
* Returns the curve&#x2019;s first control point.
*/
public abstract Point2D getCtrlP1();
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s second
* control point.
*/
public abstract double getCtrlX2();
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s second
* control point.
*/
public abstract double getCtrlY2();
-
/**
* Returns the curve&#x2019;s second control point.
*/
public abstract Point2D getCtrlP2();
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s end
* point.
*/
public abstract double getX2();
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s end
* point.
*/
public abstract double getY2();
-
/**
* Returns the curve&#x2019;s end point.
*/
public abstract Point2D getP2();
-
/**
* Changes the curve geometry, separately specifying each coordinate
* value.
@@ -183,7 +171,6 @@ public abstract class CubicCurve2D
public abstract void setCurve(double x1, double y1, double cx1, double cy1,
double cx2, double cy2, double x2, double y2);
-
/**
* Changes the curve geometry, specifying coordinate values in an
* array.
@@ -206,13 +193,11 @@ public abstract class CubicCurve2D
*/
public void setCurve(double[] coords, int offset)
{
- setCurve(coords[offset++], coords[offset++],
- coords[offset++], coords[offset++],
- coords[offset++], coords[offset++],
+ setCurve(coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++], coords[offset++],
coords[offset++], coords[offset++]);
}
-
/**
* Changes the curve geometry, specifying coordinate values in
* separate Point objects.
@@ -232,11 +217,10 @@ public abstract class CubicCurve2D
*/
public void setCurve(Point2D p1, Point2D c1, Point2D c2, Point2D p2)
{
- setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(),
- c2.getX(), c2.getY(), p2.getX(), p2.getY());
+ setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(), c2.getX(), c2.getY(),
+ p2.getX(), p2.getY());
}
-
/**
* Changes the curve geometry, specifying coordinate values in an
* array of Point objects.
@@ -258,12 +242,10 @@ public abstract class CubicCurve2D
*/
public void setCurve(Point2D[] pts, int offset)
{
- setCurve(pts[offset].getX(), pts[offset++].getY(),
- pts[offset].getX(), pts[offset++].getY(),
- pts[offset].getX(), pts[offset++].getY(),
+ setCurve(pts[offset].getX(), pts[offset++].getY(), pts[offset].getX(),
+ pts[offset++].getY(), pts[offset].getX(), pts[offset++].getY(),
pts[offset].getX(), pts[offset++].getY());
}
-
/**
* Changes the curve geometry to that of another curve.
@@ -276,7 +258,6 @@ public abstract class CubicCurve2D
c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2());
}
-
/**
* Calculates the squared flatness of a cubic curve, directly
* specifying each coordinate value. The flatness is the maximal
@@ -309,7 +290,6 @@ public abstract class CubicCurve2D
Line2D.ptSegDistSq(x1, y1, x2, y2, cx2, cy2));
}
-
/**
* Calculates the flatness of a cubic curve, directly specifying
* each coordinate value. The flatness is the maximal distance of a
@@ -340,7 +320,6 @@ public abstract class CubicCurve2D
return Math.sqrt(getFlatnessSq(x1, y1, cx1, cy1, cx2, cy2, x2, y2));
}
-
/**
* Calculates the squared flatness of a cubic curve, specifying the
* coordinate values in an array. The flatness is the maximal
@@ -374,13 +353,11 @@ public abstract class CubicCurve2D
*/
public static double getFlatnessSq(double[] coords, int offset)
{
- return getFlatnessSq(coords[offset++], coords[offset++],
- coords[offset++], coords[offset++],
- coords[offset++], coords[offset++],
+ return getFlatnessSq(coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++], coords[offset++],
coords[offset++], coords[offset++]);
}
-
/**
* Calculates the flatness of a cubic curve, specifying the
* coordinate values in an array. The flatness is the maximal
@@ -420,7 +397,6 @@ public abstract class CubicCurve2D
coords[offset++], coords[offset++]));
}
-
/**
* Calculates the squared flatness of this curve. The flatness is
* the maximal distance of a control point to the line between start
@@ -441,7 +417,6 @@ public abstract class CubicCurve2D
getCtrlX2(), getCtrlY2(), getX2(), getY2());
}
-
/**
* Calculates the flatness of this curve. The flatness is the
* maximal distance of a control point to the line between start and
@@ -458,12 +433,10 @@ public abstract class CubicCurve2D
*/
public double getFlatness()
{
- return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(),
- getCtrlY1(), getCtrlX2(), getCtrlY2(),
- getX2(), getY2()));
+ return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
+ getCtrlX2(), getCtrlY2(), getX2(), getY2()));
}
-
/**
* Subdivides this curve into two halves.
*
@@ -482,9 +455,11 @@ public abstract class CubicCurve2D
public void subdivide(CubicCurve2D left, CubicCurve2D right)
{
// Use empty slots at end to share single array.
- double[] d = new double[] { getX1(), getY1(), getCtrlX1(), getCtrlY1(),
- getCtrlX2(), getCtrlY2(), getX2(), getY2(),
- 0, 0, 0, 0, 0, 0 };
+ double[] d = new double[]
+ {
+ getX1(), getY1(), getCtrlX1(), getCtrlY1(), getCtrlX2(),
+ getCtrlY2(), getX2(), getY2(), 0, 0, 0, 0, 0, 0
+ };
subdivide(d, 0, d, 0, d, 6);
if (left != null)
left.setCurve(d, 0);
@@ -492,7 +467,6 @@ public abstract class CubicCurve2D
right.setCurve(d, 6);
}
-
/**
* Subdivides a cubic curve into two halves.
*
@@ -510,13 +484,12 @@ public abstract class CubicCurve2D
* of <code>src</code>, or <code>null</code> if the caller is not
* interested in the right half.
*/
- public static void subdivide(CubicCurve2D src,
- CubicCurve2D left, CubicCurve2D right)
+ public static void subdivide(CubicCurve2D src, CubicCurve2D left,
+ CubicCurve2D right)
{
src.subdivide(left, right);
}
-
/**
* Subdivides a cubic curve into two halves, passing all coordinates
* in an array.
@@ -563,18 +536,29 @@ public abstract class CubicCurve2D
* index where the start point&#x2019;s <i>x</i> coordinate will be
* stored.
*/
- public static void subdivide(double[] src, int srcOff,
- double[] left, int leftOff,
- double[] right, int rightOff)
+ public static void subdivide(double[] src, int srcOff, double[] left,
+ int leftOff, double[] right, int rightOff)
{
// To understand this code, please have a look at the image
// "CubicCurve2D-3.png" in the sub-directory "doc-files".
- double src_C1_x, src_C1_y, src_C2_x, src_C2_y;
- double left_P1_x, left_P1_y;
- double left_C1_x, left_C1_y, left_C2_x, left_C2_y;
- double right_C1_x, right_C1_y, right_C2_x, right_C2_y;
- double right_P2_x, right_P2_y;
- double Mid_x, Mid_y; // Mid = left.P2 = right.P1
+ double src_C1_x;
+ double src_C1_y;
+ double src_C2_x;
+ double src_C2_y;
+ double left_P1_x;
+ double left_P1_y;
+ double left_C1_x;
+ double left_C1_y;
+ double left_C2_x;
+ double left_C2_y;
+ double right_C1_x;
+ double right_C1_y;
+ double right_C2_x;
+ double right_C2_y;
+ double right_P2_x;
+ double right_P2_y;
+ double Mid_x; // Mid = left.P2 = right.P1
+ double Mid_y; // Mid = left.P2 = right.P1
left_P1_x = src[srcOff];
left_P1_y = src[srcOff + 1];
@@ -599,31 +583,30 @@ public abstract class CubicCurve2D
Mid_y = (left_C2_y + right_C1_y) / 2;
if (left != null)
- {
- left[leftOff] = left_P1_x;
- left[leftOff + 1] = left_P1_y;
- left[leftOff + 2] = left_C1_x;
- left[leftOff + 3] = left_C1_y;
- left[leftOff + 4] = left_C2_x;
- left[leftOff + 5] = left_C2_y;
- left[leftOff + 6] = Mid_x;
- left[leftOff + 7] = Mid_y;
- }
+ {
+ left[leftOff] = left_P1_x;
+ left[leftOff + 1] = left_P1_y;
+ left[leftOff + 2] = left_C1_x;
+ left[leftOff + 3] = left_C1_y;
+ left[leftOff + 4] = left_C2_x;
+ left[leftOff + 5] = left_C2_y;
+ left[leftOff + 6] = Mid_x;
+ left[leftOff + 7] = Mid_y;
+ }
if (right != null)
- {
- right[rightOff] = Mid_x;
- right[rightOff + 1] = Mid_y;
- right[rightOff + 2] = right_C1_x;
- right[rightOff + 3] = right_C1_y;
- right[rightOff + 4] = right_C2_x;
- right[rightOff + 5] = right_C2_y;
- right[rightOff + 6] = right_P2_x;
- right[rightOff + 7] = right_P2_y;
- }
+ {
+ right[rightOff] = Mid_x;
+ right[rightOff + 1] = Mid_y;
+ right[rightOff + 2] = right_C1_x;
+ right[rightOff + 3] = right_C1_y;
+ right[rightOff + 4] = right_C2_x;
+ right[rightOff + 5] = right_C2_y;
+ right[rightOff + 6] = right_P2_x;
+ right[rightOff + 7] = right_P2_y;
+ }
}
-
/**
* Finds the non-complex roots of a cubic equation, placing the
* results into the same array as the equation coefficients. The
@@ -670,7 +653,6 @@ public abstract class CubicCurve2D
return solveCubic(eqn, eqn);
}
-
/**
* Finds the non-complex roots of a cubic equation. The following
* equation is being solved:
@@ -727,9 +709,19 @@ public abstract class CubicCurve2D
// The Java implementation is very similar to the GSL code, but
// not a strict one-to-one copy. For example, GSL would sort the
// result.
-
- double a, b, c, q, r, Q, R;
- double c3, Q3, R2, CR2, CQ3;
+
+ double a;
+ double b;
+ double c;
+ double q;
+ double r;
+ double Q;
+ double R;
+ double c3;
+ double Q3;
+ double R2;
+ double CR2;
+ double CQ3;
// If the cubic coefficient is zero, we have a quadratic equation.
c3 = eqn[3];
@@ -755,219 +747,267 @@ public abstract class CubicCurve2D
CQ3 = 2916 * q * q * q;
if (R == 0 && Q == 0)
- {
- // The GNU Scientific Library would return three identical
- // solutions in this case.
- res[0] = -a/3;
- return 1;
- }
-
- if (CR2 == CQ3)
- {
- /* this test is actually R2 == Q3, written in a form suitable
- for exact computation with integers */
-
- /* Due to finite precision some double roots may be missed, and
- considered to be a pair of complex roots z = x +/- epsilon i
- close to the real axis. */
-
- double sqrtQ = Math.sqrt(Q);
-
- if (R > 0)
{
- res[0] = -2 * sqrtQ - a/3;
- res[1] = sqrtQ - a/3;
+ // The GNU Scientific Library would return three identical
+ // solutions in this case.
+ res[0] = -a / 3;
+ return 1;
}
- else
+
+ if (CR2 == CQ3)
{
- res[0] = -sqrtQ - a/3;
- res[1] = 2 * sqrtQ - a/3;
+ /* this test is actually R2 == Q3, written in a form suitable
+ for exact computation with integers */
+ /* Due to finite precision some double roots may be missed, and
+ considered to be a pair of complex roots z = x +/- epsilon i
+ close to the real axis. */
+ double sqrtQ = Math.sqrt(Q);
+
+ if (R > 0)
+ {
+ res[0] = -2 * sqrtQ - a / 3;
+ res[1] = sqrtQ - a / 3;
+ }
+ else
+ {
+ res[0] = -sqrtQ - a / 3;
+ res[1] = 2 * sqrtQ - a / 3;
+ }
+ return 2;
}
- return 2;
- }
if (CR2 < CQ3) /* equivalent to R2 < Q3 */
- {
- double sqrtQ = Math.sqrt(Q);
- double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
- double theta = Math.acos(R / sqrtQ3);
- double norm = -2 * sqrtQ;
- res[0] = norm * Math.cos(theta / 3) - a / 3;
- res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a/3;
- res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a/3;
-
- // The GNU Scientific Library sorts the results. We don't.
- return 3;
- }
+ {
+ double sqrtQ = Math.sqrt(Q);
+ double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
+ double theta = Math.acos(R / sqrtQ3);
+ double norm = -2 * sqrtQ;
+ res[0] = norm * Math.cos(theta / 3) - a / 3;
+ res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a / 3;
+ res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a / 3;
+
+ // The GNU Scientific Library sorts the results. We don't.
+ return 3;
+ }
double sgnR = (R >= 0 ? 1 : -1);
- double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0/3.0);
- double B = Q / A ;
- res[0] = A + B - a/3;
+ double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0);
+ double B = Q / A;
+ res[0] = A + B - a / 3;
return 1;
}
-
/**
- * Determines whether a position lies inside the area that is bounded
+ * Determines whether a position lies inside the area bounded
* by the curve and the straight line connecting its end points.
*
* <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
* alt="A drawing of the area spanned by the curve" />
*
* <p>The above drawing illustrates in which area points are
- * considered &#x201c;contained&#x201d; in a CubicCurve2D.
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
*/
public boolean contains(double x, double y)
{
- // XXX Implement.
- throw new Error("not implemented");
- }
+ if (! getBounds2D().contains(x, y))
+ return false;
+ return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0);
+ }
/**
- * Determines whether a point lies inside the area that is bounded
+ * Determines whether a point lies inside the area bounded
* by the curve and the straight line connecting its end points.
*
* <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
* alt="A drawing of the area spanned by the curve" />
*
* <p>The above drawing illustrates in which area points are
- * considered &#x201c;contained&#x201d; in a CubicCurve2D.
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
*/
public boolean contains(Point2D p)
{
return contains(p.getX(), p.getY());
}
-
+ /**
+ * Determines whether any part of a rectangle is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; in a CubicCurve2D.
+ * @see #contains(double, double)
+ */
public boolean intersects(double x, double y, double w, double h)
{
- // XXX Implement.
- throw new Error("not implemented");
- }
+ if (! getBounds2D().contains(x, y, w, h))
+ return false;
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return true;
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Determines whether any part of a Rectangle2D is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ * @see #intersects(double, double, double, double)
+ */
public boolean intersects(Rectangle2D r)
{
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
-
+ /**
+ * Determine whether a rectangle is entirely inside the area that is bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ * @see #contains(double, double)
+ */
public boolean contains(double x, double y, double w, double h)
{
- // XXX Implement.
- throw new Error("not implemented");
- }
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return false;
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+ return false;
+ }
+
+ /**
+ * Determine whether a Rectangle2D is entirely inside the area that is
+ * bounded by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a CubicCurve2D.
+ * @see #contains(double, double)
+ */
public boolean contains(Rectangle2D r)
{
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
-
/**
* Determines the smallest rectangle that encloses the
- * curve&#x2019;s start, end and control points. As the illustration
- * below shows, the invisible control points may cause the bounds to
- * be much larger than the area that is actually covered by the
- * curve.
- *
- * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180"
- * alt="An illustration of the bounds of a CubicCurve2D" />
+ * curve&#x2019;s start, end and control points.
*/
public Rectangle getBounds()
{
return getBounds2D().getBounds();
}
-
public PathIterator getPathIterator(final AffineTransform at)
{
return new PathIterator()
- {
- /** Current coordinate. */
- private int current = 0;
-
- public int getWindingRule()
- {
- return WIND_NON_ZERO;
- }
-
- public boolean isDone()
- {
- return current >= 2;
- }
-
- public void next()
- {
- current++;
- }
-
- public int currentSegment(float[] coords)
{
- int result;
- switch (current)
- {
- case 0:
- coords[0] = (float) getX1();
- coords[1] = (float) getY1();
- result = SEG_MOVETO;
- break;
- case 1:
- coords[0] = (float) getCtrlX1();
- coords[1] = (float) getCtrlY1();
- coords[2] = (float) getCtrlX2();
- coords[3] = (float) getCtrlY2();
- coords[4] = (float) getX2();
- coords[5] = (float) getY2();
- result = SEG_CUBICTO;
- break;
- default:
- throw new NoSuchElementException("cubic iterator out of bounds");
- }
- if (at != null)
- at.transform(coords, 0, coords, 0, 3);
- return result;
- }
-
- public int currentSegment(double[] coords)
- {
- int result;
- switch (current)
- {
- case 0:
- coords[0] = getX1();
- coords[1] = getY1();
- result = SEG_MOVETO;
- break;
- case 1:
- coords[0] = getCtrlX1();
- coords[1] = getCtrlY1();
- coords[2] = getCtrlX2();
- coords[3] = getCtrlY2();
- coords[4] = getX2();
- coords[5] = getY2();
- result = SEG_CUBICTO;
- break;
- default:
- throw new NoSuchElementException("cubic iterator out of bounds");
- }
- if (at != null)
- at.transform(coords, 0, coords, 0, 3);
- return result;
- }
- };
+ /** Current coordinate. */
+ private int current = 0;
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current >= 2;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = (float) getX1();
+ coords[1] = (float) getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = (float) getCtrlX1();
+ coords[1] = (float) getCtrlY1();
+ coords[2] = (float) getCtrlX2();
+ coords[3] = (float) getCtrlY2();
+ coords[4] = (float) getX2();
+ coords[5] = (float) getY2();
+ result = SEG_CUBICTO;
+ break;
+ default:
+ throw new NoSuchElementException("cubic iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 3);
+ return result;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = getX1();
+ coords[1] = getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = getCtrlX1();
+ coords[1] = getCtrlY1();
+ coords[2] = getCtrlX2();
+ coords[3] = getCtrlY2();
+ coords[4] = getX2();
+ coords[5] = getY2();
+ result = SEG_CUBICTO;
+ break;
+ default:
+ throw new NoSuchElementException("cubic iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 3);
+ return result;
+ }
+ };
}
-
public PathIterator getPathIterator(AffineTransform at, double flatness)
{
return new FlatteningPathIterator(getPathIterator(at), flatness);
}
-
/**
* Create a new curve with the same contents as this one.
*
@@ -976,15 +1016,118 @@ public abstract class CubicCurve2D
public Object clone()
{
try
- {
- return super.clone();
- }
+ {
+ return super.clone();
+ }
catch (CloneNotSupportedException e)
- {
- throw (Error) new InternalError().initCause(e); // Impossible
- }
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
}
+ /**
+ * Helper method used by contains() and intersects() methods, that
+ * returns the number of curve/line intersections on a given axis
+ * extending from a certain point.
+ *
+ * @param x x coordinate of the origin point
+ * @param y y coordinate of the origin point
+ * @param useYaxis axis used, if true the positive Y axis is used,
+ * false uses the positive X axis.
+ *
+ * This is an implementation of the line-crossings algorithm,
+ * Detailed in an article on Eric Haines' page:
+ * http://www.acm.org/tog/editors/erich/ptinpoly/
+ *
+ * A special-case not adressed in this code is self-intersections
+ * of the curve, e.g. if the axis intersects the self-itersection,
+ * the degenerate roots of the polynomial will erroneously count as
+ * a single intersection of the curve, and not two.
+ */
+ private int getAxisIntersections(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ int nCrossings = 0;
+ double a0;
+ double a1;
+ double a2;
+ double a3;
+ double b0;
+ double b1;
+ double b2;
+ double b3;
+ double[] r = new double[4];
+ int nRoots;
+
+ a0 = a3 = 0.0;
+
+ if (useYaxis)
+ {
+ a0 = getY1() - y;
+ a1 = getCtrlY1() - y;
+ a2 = getCtrlY2() - y;
+ a3 = getY2() - y;
+ b0 = getX1() - x;
+ b1 = getCtrlX1() - x;
+ b2 = getCtrlX2() - x;
+ b3 = getX2() - x;
+ }
+ else
+ {
+ a0 = getX1() - x;
+ a1 = getCtrlX1() - x;
+ a2 = getCtrlX2() - x;
+ a3 = getX2() - x;
+ b0 = getY1() - y;
+ b1 = getCtrlY1() - y;
+ b2 = getCtrlY2() - y;
+ b3 = getY2() - y;
+ }
+
+ /* If the axis intersects a start/endpoint, shift it up by some small
+ amount to guarantee the line is 'inside'
+ If this is not done, bad behaviour may result for points on that axis.*/
+ if (a0 == 0.0 || a3 == 0.0)
+ {
+ double small = getFlatness() * (1E-10);
+ if (a0 == 0.0)
+ a0 += small;
+ if (a3 == 0.0)
+ a3 += small;
+ }
+
+ if (useYaxis)
+ {
+ if (Line2D.linesIntersect(b0, a0, b3, a3, 0.0, 0.0, distance, 0.0))
+ nCrossings++;
+ }
+ else
+ {
+ if (Line2D.linesIntersect(a0, b0, a3, b3, 0.0, 0.0, 0.0, distance))
+ nCrossings++;
+ }
+
+ r[0] = a0;
+ r[1] = 3 * (a1 - a0);
+ r[2] = 3 * (a2 + a0 - 2 * a1);
+ r[3] = a3 - 3 * a2 + 3 * a1 - a0;
+
+ if ((nRoots = solveCubic(r)) != 0)
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ double crossing = -(t * t * t) * (b0 - 3 * b1 + 3 * b2 - b3)
+ + 3 * t * t * (b0 - 2 * b1 + b2)
+ + 3 * t * (b1 - b0) + b0;
+ if (crossing > 0.0 && crossing <= distance)
+ nCrossings++;
+ }
+ }
+
+ return (nCrossings);
+ }
/**
* A two-dimensional curve that is parameterized with a cubic
@@ -996,57 +1139,48 @@ public abstract class CubicCurve2D
* @author Eric Blake (ebb9@email.byu.edu)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
- public static class Double
- extends CubicCurve2D
+ public static class Double extends CubicCurve2D
{
/**
* The <i>x</i> coordinate of the curve&#x2019;s start point.
*/
public double x1;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s start point.
*/
public double y1;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s first control point.
*/
public double ctrlx1;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s first control point.
*/
public double ctrly1;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s second control point.
*/
public double ctrlx2;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s second control point.
*/
public double ctrly2;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s end point.
*/
public double x2;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s end point.
*/
public double y2;
-
/**
* Constructs a new CubicCurve2D that stores its coordinate values
* in double-precision floating-point format. All points are
@@ -1056,7 +1190,6 @@ public abstract class CubicCurve2D
{
}
-
/**
* Constructs a new CubicCurve2D that stores its coordinate values
* in double-precision floating-point format, specifying the
@@ -1089,8 +1222,8 @@ public abstract class CubicCurve2D
* @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
* point.
*/
- public Double(double x1, double y1, double cx1, double cy1,
- double cx2, double cy2, double x2, double y2)
+ public Double(double x1, double y1, double cx1, double cy1, double cx2,
+ double cy2, double x2, double y2)
{
this.x1 = x1;
this.y1 = y1;
@@ -1102,7 +1235,6 @@ public abstract class CubicCurve2D
this.y2 = y2;
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s start
* point.
@@ -1112,7 +1244,6 @@ public abstract class CubicCurve2D
return x1;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s start
* point.
@@ -1122,7 +1253,6 @@ public abstract class CubicCurve2D
return y1;
}
-
/**
* Returns the curve&#x2019;s start point.
*/
@@ -1131,7 +1261,6 @@ public abstract class CubicCurve2D
return new Point2D.Double(x1, y1);
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s first
* control point.
@@ -1141,7 +1270,6 @@ public abstract class CubicCurve2D
return ctrlx1;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s first
* control point.
@@ -1151,7 +1279,6 @@ public abstract class CubicCurve2D
return ctrly1;
}
-
/**
* Returns the curve&#x2019;s first control point.
*/
@@ -1160,7 +1287,6 @@ public abstract class CubicCurve2D
return new Point2D.Double(ctrlx1, ctrly1);
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s second
* control point.
@@ -1170,7 +1296,6 @@ public abstract class CubicCurve2D
return ctrlx2;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s second
* control point.
@@ -1180,7 +1305,6 @@ public abstract class CubicCurve2D
return ctrly2;
}
-
/**
* Returns the curve&#x2019;s second control point.
*/
@@ -1189,7 +1313,6 @@ public abstract class CubicCurve2D
return new Point2D.Double(ctrlx2, ctrly2);
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s end
* point.
@@ -1199,7 +1322,6 @@ public abstract class CubicCurve2D
return x2;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s end
* point.
@@ -1209,7 +1331,6 @@ public abstract class CubicCurve2D
return y2;
}
-
/**
* Returns the curve&#x2019;s end point.
*/
@@ -1218,7 +1339,6 @@ public abstract class CubicCurve2D
return new Point2D.Double(x2, y2);
}
-
/**
* Changes the curve geometry, separately specifying each coordinate
* value.
@@ -1263,7 +1383,6 @@ public abstract class CubicCurve2D
this.y2 = y2;
}
-
/**
* Determines the smallest rectangle that encloses the
* curve&#x2019;s start, end and control points. As the
@@ -1284,7 +1403,6 @@ public abstract class CubicCurve2D
}
}
-
/**
* A two-dimensional curve that is parameterized with a cubic
* function and stores coordinate values in single-precision
@@ -1295,57 +1413,48 @@ public abstract class CubicCurve2D
* @author Eric Blake (ebb9@email.byu.edu)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
- public static class Float
- extends CubicCurve2D
+ public static class Float extends CubicCurve2D
{
/**
* The <i>x</i> coordinate of the curve&#x2019;s start point.
*/
public float x1;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s start point.
*/
public float y1;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s first control point.
*/
public float ctrlx1;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s first control point.
*/
public float ctrly1;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s second control point.
*/
public float ctrlx2;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s second control point.
*/
public float ctrly2;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s end point.
*/
public float x2;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s end point.
*/
public float y2;
-
/**
* Constructs a new CubicCurve2D that stores its coordinate values
* in single-precision floating-point format. All points are
@@ -1355,7 +1464,6 @@ public abstract class CubicCurve2D
{
}
-
/**
* Constructs a new CubicCurve2D that stores its coordinate values
* in single-precision floating-point format, specifying the
@@ -1388,8 +1496,8 @@ public abstract class CubicCurve2D
* @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
* point.
*/
- public Float(float x1, float y1, float cx1, float cy1,
- float cx2, float cy2, float x2, float y2)
+ public Float(float x1, float y1, float cx1, float cy1, float cx2,
+ float cy2, float x2, float y2)
{
this.x1 = x1;
this.y1 = y1;
@@ -1401,7 +1509,6 @@ public abstract class CubicCurve2D
this.y2 = y2;
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s start
* point.
@@ -1411,7 +1518,6 @@ public abstract class CubicCurve2D
return x1;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s start
* point.
@@ -1421,7 +1527,6 @@ public abstract class CubicCurve2D
return y1;
}
-
/**
* Returns the curve&#x2019;s start point.
*/
@@ -1430,7 +1535,6 @@ public abstract class CubicCurve2D
return new Point2D.Float(x1, y1);
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s first
* control point.
@@ -1440,7 +1544,6 @@ public abstract class CubicCurve2D
return ctrlx1;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s first
* control point.
@@ -1450,7 +1553,6 @@ public abstract class CubicCurve2D
return ctrly1;
}
-
/**
* Returns the curve&#x2019;s first control point.
*/
@@ -1459,7 +1561,6 @@ public abstract class CubicCurve2D
return new Point2D.Float(ctrlx1, ctrly1);
}
-
/**
* Returns the <i>s</i> coordinate of the curve&#x2019;s second
* control point.
@@ -1469,7 +1570,6 @@ public abstract class CubicCurve2D
return ctrlx2;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s second
* control point.
@@ -1479,7 +1579,6 @@ public abstract class CubicCurve2D
return ctrly2;
}
-
/**
* Returns the curve&#x2019;s second control point.
*/
@@ -1488,7 +1587,6 @@ public abstract class CubicCurve2D
return new Point2D.Float(ctrlx2, ctrly2);
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s end
* point.
@@ -1498,7 +1596,6 @@ public abstract class CubicCurve2D
return x2;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s end
* point.
@@ -1508,7 +1605,6 @@ public abstract class CubicCurve2D
return y2;
}
-
/**
* Returns the curve&#x2019;s end point.
*/
@@ -1517,7 +1613,6 @@ public abstract class CubicCurve2D
return new Point2D.Float(x2, y2);
}
-
/**
* Changes the curve geometry, separately specifying each coordinate
* value as a double-precision floating-point number.
@@ -1562,7 +1657,6 @@ public abstract class CubicCurve2D
this.y2 = (float) y2;
}
-
/**
* Changes the curve geometry, separately specifying each coordinate
* value as a single-precision floating-point number.
@@ -1594,8 +1688,8 @@ public abstract class CubicCurve2D
* @param y2 the <i>y</i> coordinate of the curve&#x2019;s new end
* point.
*/
- public void setCurve(float x1, float y1, float cx1, float cy1,
- float cx2, float cy2, float x2, float y2)
+ public void setCurve(float x1, float y1, float cx1, float cy1, float cx2,
+ float cy2, float x2, float y2)
{
this.x1 = x1;
this.y1 = y1;
@@ -1607,7 +1701,6 @@ public abstract class CubicCurve2D
this.y2 = y2;
}
-
/**
* Determines the smallest rectangle that encloses the
* curve&#x2019;s start, end and control points. As the
diff --git a/libjava/java/awt/geom/GeneralPath.java b/libjava/java/awt/geom/GeneralPath.java
index 05d98c7..40182ea 100644
--- a/libjava/java/awt/geom/GeneralPath.java
+++ b/libjava/java/awt/geom/GeneralPath.java
@@ -1,50 +1,80 @@
/* GeneralPath.java -- represents a shape built from subpaths
- Copyright (C) 2002, 2003 Free Software Foundation
-
-This file is part of GNU Classpath.
-
-GNU Classpath is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GNU Classpath is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Classpath; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA.
-
-Linking this library statically or dynamically with other modules is
-making a combined work based on this library. Thus, the terms and
-conditions of the GNU General Public License cover the whole
-combination.
-
-As a special exception, the copyright holders of this library give you
-permission to link this library with independent modules to produce an
-executable, regardless of the license terms of these independent
-modules, and to copy and distribute the resulting executable under
-terms of your choice, provided that you also meet, for each linked
-independent module, the terms and conditions of the license of that
-module. An independent module is a module which is not derived from
-or based on this library. If you modify this library, you may extend
-this exception to your version of the library, but you are not
-obligated to do so. If you do not wish to do so, delete this
-exception statement from your version. */
-
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
+
+ This file is part of GNU Classpath.
+
+ GNU Classpath is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GNU Classpath is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Classpath; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+
+ Linking this library statically or dynamically with other modules is
+ making a combined work based on this library. Thus, the terms and
+ conditions of the GNU General Public License cover the whole
+ combination.
+
+ As a special exception, the copyright holders of this library give you
+ permission to link this library with independent modules to produce an
+ executable, regardless of the license terms of these independent
+ modules, and to copy and distribute the resulting executable under
+ terms of your choice, provided that you also meet, for each linked
+ independent module, the terms and conditions of the license of that
+ module. An independent module is a module which is not derived from
+ or based on this library. If you modify this library, you may extend
+ this exception to your version of the library, but you are not
+ obligated to do so. If you do not wish to do so, delete this
+ exception statement from your version. */
package java.awt.geom;
import java.awt.Rectangle;
import java.awt.Shape;
+
/**
- * STUBS ONLY
- * XXX Implement and document. Note that Sun's implementation only expects
- * float precision, not double.
+ * A general geometric path, consisting of any number of subpaths
+ * constructed out of straight lines and cubic or quadratic Bezier
+ * curves.
+ *
+ * <p>The inside of the curve is defined for drawing purposes by a winding
+ * rule. Either the WIND_EVEN_ODD or WIND_NON_ZERO winding rule can be chosen.
+ *
+ * <p><img src="doc-files/GeneralPath-1.png" width="300" height="210"
+ * alt="A drawing of a GeneralPath" />
+ * <p>The EVEN_ODD winding rule defines a point as inside a path if:
+ * A ray from the point towards infinity in an arbitrary direction
+ * intersects the path an odd number of times. Points <b>A</b> and
+ * <b>C</b> in the image are considered to be outside the path.
+ * (both intersect twice)
+ * Point <b>B</b> intersects once, and is inside.
+ *
+ * <p>The NON_ZERO winding rule defines a point as inside a path if:
+ * The path intersects the ray in an equal number of opposite directions.
+ * Point <b>A</b> in the image is outside (one intersection in the
+ * &#x2019;up&#x2019;
+ * direction, one in the &#x2019;down&#x2019; direction) Point <b>B</b> in
+ * the image is inside (one intersection &#x2019;down&#x2019;)
+ * Point <b>C</b> in the image is outside (two intersections
+ * &#x2019;down&#x2019;)
+ *
+ * @see Line2D
+ * @see CubicCurve2D
+ * @see QuadCurve2D
+ *
+ * @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
+ *
+ * @since 1.2
*/
public final class GeneralPath implements Shape, Cloneable
{
@@ -52,35 +82,63 @@ public final class GeneralPath implements Shape, Cloneable
public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO;
/** Initial size if not specified. */
- private static final int INIT_SIZE = 20;
+ private static final int INIT_SIZE = 10;
+
+ /** A big number, but not so big it can't survive a few float operations */
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
/** The winding rule. */
private int rule;
+
/**
- * The path type in points. Note that points[index] maps to
- * types[index >> 1]; the control points of quad and cubic paths map as
+ * The path type in points. Note that xpoints[index] and ypoints[index] maps
+ * to types[index]; the control points of quad and cubic paths map as
* well but are ignored.
*/
private byte[] types;
+
/**
* The list of all points seen. Since you can only append floats, it makes
- * sense for this to be a float[]. I have no idea why Sun didn't choose to
+ * sense for these to be float[]. I have no idea why Sun didn't choose to
* allow a general path of double precision points.
+ * Note: Storing x and y coords seperately makes for a slower transforms,
+ * But it speeds up and simplifies box-intersection checking a lot.
*/
- private float[] points;
+ private float[] xpoints;
+ private float[] ypoints;
+
/** The index of the most recent moveto point, or null. */
private int subpath = -1;
+
/** The next available index into points. */
private int index;
+ /**
+ * Constructs a GeneralPath with the default (NON_ZERO)
+ * winding rule and initial capacity (20).
+ */
public GeneralPath()
{
this(WIND_NON_ZERO, INIT_SIZE);
}
+
+ /**
+ * Constructs a GeneralPath with a specific winding rule
+ * and the default initial capacity (20).
+ * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD)
+ */
public GeneralPath(int rule)
{
this(rule, INIT_SIZE);
}
+
+ /**
+ * Constructs a GeneralPath with a specific winding rule
+ * and the initial capacity. The initial capacity should be
+ * the approximate number of path segments to be used.
+ * @param rule the winding rule (WIND_NON_ZERO or WIND_EVEN_ODD)
+ * @param capacity the inital capacity, in path segments
+ */
public GeneralPath(int rule, int capacity)
{
if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
@@ -88,68 +146,112 @@ public final class GeneralPath implements Shape, Cloneable
this.rule = rule;
if (capacity < INIT_SIZE)
capacity = INIT_SIZE;
- types = new byte[capacity >> 1];
- points = new float[capacity];
+ types = new byte[capacity];
+ xpoints = new float[capacity];
+ ypoints = new float[capacity];
}
+
+ /**
+ * Constructs a GeneralPath from an arbitrary shape object.
+ * The Shapes PathIterator path and winding rule will be used.
+ * @param s the shape
+ */
public GeneralPath(Shape s)
{
- types = new byte[INIT_SIZE >> 1];
- points = new float[INIT_SIZE];
+ types = new byte[INIT_SIZE];
+ xpoints = new float[INIT_SIZE];
+ ypoints = new float[INIT_SIZE];
PathIterator pi = s.getPathIterator(null);
setWindingRule(pi.getWindingRule());
append(pi, false);
}
+ /**
+ * Adds a new point to a path.
+ */
public void moveTo(float x, float y)
{
subpath = index;
- ensureSize(index + 2);
- types[index >> 1] = PathIterator.SEG_MOVETO;
- points[index++] = x;
- points[index++] = y;
+ ensureSize(index + 1);
+ types[index] = PathIterator.SEG_MOVETO;
+ xpoints[index] = x;
+ ypoints[index++] = y;
}
+
+ /**
+ * Appends a straight line to the current path.
+ * @param x x coordinate of the line endpoint.
+ * @param y y coordinate of the line endpoint.
+ */
public void lineTo(float x, float y)
{
- ensureSize(index + 2);
- types[index >> 1] = PathIterator.SEG_LINETO;
- points[index++] = x;
- points[index++] = y;
+ ensureSize(index + 1);
+ types[index] = PathIterator.SEG_LINETO;
+ xpoints[index] = x;
+ ypoints[index++] = y;
}
+
+ /**
+ * Appends a quadratic Bezier curve to the current path.
+ * @param x1 x coordinate of the control point
+ * @param y1 y coordinate of the control point
+ * @param x2 x coordinate of the curve endpoint.
+ * @param y2 y coordinate of the curve endpoint.
+ */
public void quadTo(float x1, float y1, float x2, float y2)
{
- ensureSize(index + 4);
- types[index >> 1] = PathIterator.SEG_QUADTO;
- points[index++] = x1;
- points[index++] = y1;
- points[index++] = x2;
- points[index++] = y2;
- }
- public void curveTo(float x1, float y1, float x2, float y2,
- float x3, float y3)
- {
- ensureSize(index + 6);
- types[index >> 1] = PathIterator.SEG_CUBICTO;
- points[index++] = x1;
- points[index++] = y1;
- points[index++] = x2;
- points[index++] = y2;
- points[index++] = x3;
- points[index++] = y3;
+ ensureSize(index + 2);
+ types[index] = PathIterator.SEG_QUADTO;
+ xpoints[index] = x1;
+ ypoints[index++] = y1;
+ xpoints[index] = x2;
+ ypoints[index++] = y2;
}
+
+ /**
+ * Appends a cubic Bezier curve to the current path.
+ * @param x1 x coordinate of the first control point
+ * @param y1 y coordinate of the first control point
+ * @param x2 x coordinate of the second control point
+ * @param y2 y coordinate of the second control point
+ * @param x3 x coordinate of the curve endpoint.
+ * @param y3 y coordinate of the curve endpoint.
+ */
+ public void curveTo(float x1, float y1, float x2, float y2, float x3,
+ float y3)
+ {
+ ensureSize(index + 3);
+ types[index] = PathIterator.SEG_CUBICTO;
+ xpoints[index] = x1;
+ ypoints[index++] = y1;
+ xpoints[index] = x2;
+ ypoints[index++] = y2;
+ xpoints[index] = x3;
+ ypoints[index++] = y3;
+ }
+
+ /**
+ * Closes the current subpath by drawing a line
+ * back to the point of the last moveTo.
+ */
public void closePath()
{
- ensureSize(index + 2);
- types[index >> 1] = PathIterator.SEG_CLOSE;
- points[index++] = points[subpath];
- points[index++] = points[subpath + 1];
+ ensureSize(index + 1);
+ types[index] = PathIterator.SEG_CLOSE;
+ xpoints[index] = xpoints[subpath];
+ ypoints[index++] = ypoints[subpath];
}
+ /**
+ * Appends the segments of a Shape to the path. If <code>connect</code> is
+ * true, the new path segments are connected to the existing one with a line.
+ * The winding rule of the Shape is ignored.
+ */
public void append(Shape s, boolean connect)
{
append(s.getPathIterator(null), connect);
}
-
/**
* Appends the segments of a PathIterator to this GeneralPath.
* Optionally, the initial {@link PathIterator#SEG_MOVETO} segment
@@ -158,7 +260,7 @@ public final class GeneralPath implements Shape, Cloneable
*
* @param iter the PathIterator specifying which segments shall be
* appended.
- *
+ *
* @param connect <code>true</code> for substituting the initial
* {@link PathIterator#SEG_MOVETO} segment by a {@link
* PathIterator#SEG_LINETO}, or <code>false</code> for not
@@ -171,50 +273,55 @@ public final class GeneralPath implements Shape, Cloneable
{
// A bad implementation of this method had caused Classpath bug #6076.
float[] f = new float[6];
- while (!iter.isDone())
- {
- switch (iter.currentSegment(f))
+ while (! iter.isDone())
{
- case PathIterator.SEG_MOVETO:
- if (!connect || (index == 0))
- {
- moveTo(f[0], f[1]);
- break;
- }
-
- if ((index >= 2) && (types[(index - 2) >> 2] == PathIterator.SEG_CLOSE)
- && (f[0] == points[index - 2]) && (f[1] == points[index - 1]))
- break;
-
- // Fall through.
-
- case PathIterator.SEG_LINETO:
- lineTo(f[0], f[1]);
- break;
-
- case PathIterator.SEG_QUADTO:
- quadTo(f[0], f[1], f[2], f[3]);
- break;
-
- case PathIterator.SEG_CUBICTO:
- curveTo(f[0], f[1], f[2], f[3], f[4], f[5]);
- break;
-
- case PathIterator.SEG_CLOSE:
- closePath();
- break;
+ switch (iter.currentSegment(f))
+ {
+ case PathIterator.SEG_MOVETO:
+ if (! connect || (index == 0))
+ {
+ moveTo(f[0], f[1]);
+ break;
+ }
+ if ((index >= 1) && (types[index - 1] == PathIterator.SEG_CLOSE)
+ && (f[0] == xpoints[index - 1])
+ && (f[1] == ypoints[index - 1]))
+ break;
+
+ // Fall through.
+ case PathIterator.SEG_LINETO:
+ lineTo(f[0], f[1]);
+ break;
+ case PathIterator.SEG_QUADTO:
+ quadTo(f[0], f[1], f[2], f[3]);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ curveTo(f[0], f[1], f[2], f[3], f[4], f[5]);
+ break;
+ case PathIterator.SEG_CLOSE:
+ closePath();
+ break;
+ }
+
+ connect = false;
+ iter.next();
}
-
- connect = false;
- iter.next();
- }
}
-
+ /**
+ * Returns the path&#x2019;s current winding rule.
+ */
public int getWindingRule()
{
return rule;
}
+
+ /**
+ * Sets the path&#x2019;s winding rule, which controls which areas are
+ * considered &#x2019;inside&#x2019; or &#x2019;outside&#x2019; the path
+ * on drawing. Valid rules are WIND_EVEN_ODD for an even-odd winding rule,
+ * or WIND_NON_ZERO for a non-zero winding rule.
+ */
public void setWindingRule(int rule)
{
if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO)
@@ -222,22 +329,48 @@ public final class GeneralPath implements Shape, Cloneable
this.rule = rule;
}
+ /**
+ * Returns the current appending point of the path.
+ */
public Point2D getCurrentPoint()
{
if (subpath < 0)
return null;
- return new Point2D.Float(points[index - 2], points[index - 1]);
+ return new Point2D.Float(xpoints[index - 1], ypoints[index - 1]);
}
+
+ /**
+ * Resets the path. All points and segments are destroyed.
+ */
public void reset()
{
subpath = -1;
index = 0;
}
+ /**
+ * Applies a transform to the path.
+ */
public void transform(AffineTransform xform)
{
- xform.transform(points, 0, points, 0, index >> 1);
+ double nx;
+ double ny;
+ double[] m = new double[6];
+ xform.getMatrix(m);
+ for (int i = 0; i < index; i++)
+ {
+ nx = m[0] * xpoints[i] + m[2] * ypoints[i] + m[4];
+ ny = m[1] * xpoints[i] + m[3] * ypoints[i] + m[5];
+ xpoints[i] = (float) nx;
+ ypoints[i] = (float) ny;
+ }
}
+
+ /**
+ * Creates a transformed version of the path.
+ * @param xform the transform to apply
+ * @return a new transformed GeneralPath
+ */
public Shape createTransformedShape(AffineTransform xform)
{
GeneralPath p = new GeneralPath(this);
@@ -245,85 +378,174 @@ public final class GeneralPath implements Shape, Cloneable
return p;
}
+ /**
+ * Returns the path&#x2019;s bounding box.
+ */
public Rectangle getBounds()
{
return getBounds2D().getBounds();
}
+
+ /**
+ * Returns the path&#x2019;s bounding box, in <code>float</code> precision
+ */
public Rectangle2D getBounds2D()
{
- // XXX Implement.
- throw new Error("not implemented");
+ float x1;
+ float y1;
+ float x2;
+ float y2;
+
+ if (index > 0)
+ {
+ x1 = x2 = xpoints[0];
+ y1 = y2 = ypoints[0];
+ }
+ else
+ x1 = x2 = y1 = y2 = 0.0f;
+
+ for (int i = 0; i < index; i++)
+ {
+ x1 = Math.min(xpoints[i], x1);
+ y1 = Math.min(ypoints[i], y1);
+ x2 = Math.max(xpoints[i], x2);
+ y2 = Math.max(ypoints[i], y2);
+ }
+ return (new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1));
}
+ /**
+ * Evaluates if a point is within the GeneralPath,
+ * The NON_ZERO winding rule is used, regardless of the
+ * set winding rule.
+ * @param x x coordinate of the point to evaluate
+ * @param y y coordinate of the point to evaluate
+ * @return true if the point is within the path, false otherwise
+ */
public boolean contains(double x, double y)
{
- // XXX Implement.
- throw new Error("not implemented");
+ return (getWindingNumber(x, y) != 0);
}
+
+ /**
+ * Evaluates if a Point2D is within the GeneralPath,
+ * The NON_ZERO winding rule is used, regardless of the
+ * set winding rule.
+ * @param p The Point2D to evaluate
+ * @return true if the point is within the path, false otherwise
+ */
public boolean contains(Point2D p)
{
return contains(p.getX(), p.getY());
}
+
+ /**
+ * Evaluates if a rectangle is completely contained within the path.
+ * This method will return false in the cases when the box
+ * intersects an inner segment of the path.
+ * (i.e.: The method is accurate for the EVEN_ODD winding rule)
+ */
public boolean contains(double x, double y, double w, double h)
{
- // XXX Implement.
- throw new Error("not implemented");
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, false, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, true, h) != 0 /* right */
+ || getAxisIntersections(x, y, true, h) != 0) /* left */
+ return false;
+
+ /* No intersections, is any point inside? */
+ if (getWindingNumber(x, y) != 0)
+ return true;
+
+ return false;
}
+
+ /**
+ * Evaluates if a rectangle is completely contained within the path.
+ * This method will return false in the cases when the box
+ * intersects an inner segment of the path.
+ * (i.e.: The method is accurate for the EVEN_ODD winding rule)
+ * @param r the rectangle
+ * @return <code>true</code> if the rectangle is completely contained
+ * within the path, <code>false</code> otherwise
+ */
public boolean contains(Rectangle2D r)
{
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
+ /**
+ * Evaluates if a rectangle intersects the path.
+ * @param x x coordinate of the rectangle
+ * @param y y coordinate of the rectangle
+ * @param w width of the rectangle
+ * @param h height of the rectangle
+ * @return <code>true</code> if the rectangle intersects the path,
+ * <code>false</code> otherwise
+ */
public boolean intersects(double x, double y, double w, double h)
{
- // XXX Implement.
- throw new Error("not implemented");
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, false, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, true, h) != 0 /* right */
+ || getAxisIntersections(x, y, true, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if (getWindingNumber(x, y) != 0)
+ return true;
+
+ return false;
}
+
+ /**
+ * Evaluates if a Rectangle2D intersects the path.
+ * @param r The rectangle
+ * @return <code>true</code> if the rectangle intersects the path,
+ * <code>false</code> otherwise
+ */
public boolean intersects(Rectangle2D r)
{
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
-
/**
* A PathIterator that iterates over the segments of a GeneralPath.
*
* @author Sascha Brawer (brawer@dandelis.ch)
*/
- private static class GeneralPathIterator
- implements PathIterator
+ private static class GeneralPathIterator implements PathIterator
{
/**
* The number of coordinate values for each segment type.
*/
- private static final int[] NUM_COORDS =
- {
- /* 0: SEG_MOVETO */ 2,
- /* 1: SEG_LINETO */ 2,
- /* 2: SEG_QUADTO */ 4,
- /* 3: SEG_CUBICTO */ 6,
- /* 4: SEG_CLOSE */ 0
- };
-
+ private static final int[] NUM_COORDS = {
+ /* 0: SEG_MOVETO */ 1,
+ /* 1: SEG_LINETO */ 1,
+ /* 2: SEG_QUADTO */ 2,
+ /* 3: SEG_CUBICTO */ 3,
+ /* 4: SEG_CLOSE */ 0};
/**
* The GeneralPath whose segments are being iterated.
*/
private final GeneralPath path;
-
/**
* The affine transformation used to transform coordinates.
*/
private final AffineTransform transform;
-
/**
* The current position of the iterator.
*/
private int pos;
-
/**
* Constructs a new iterator for enumerating the segments of a
* GeneralPath.
@@ -338,7 +560,6 @@ public final class GeneralPath implements Shape, Cloneable
this.transform = transform;
}
-
/**
* Returns the current winding rule of the GeneralPath.
*/
@@ -347,7 +568,6 @@ public final class GeneralPath implements Shape, Cloneable
return path.rule;
}
-
/**
* Determines whether the iterator has reached the last segment in
* the path.
@@ -357,7 +577,6 @@ public final class GeneralPath implements Shape, Cloneable
return pos >= path.index;
}
-
/**
* Advances the iterator position by one segment.
*/
@@ -365,70 +584,72 @@ public final class GeneralPath implements Shape, Cloneable
{
int seg;
- /* Increment pos by the number of coordinate values. Note that
- * we store two values even for a SEG_CLOSE segment, which is
- * why we increment pos at least by 2.
+ /*
+ * Increment pos by the number of coordinate pairs.
*/
- seg = path.types[pos >> 1];
+ seg = path.types[pos];
if (seg == SEG_CLOSE)
- pos += 2;
+ pos++;
else
- pos += NUM_COORDS[seg];
+ pos += NUM_COORDS[seg];
}
-
/**
* Returns the current segment in float coordinates.
*/
public int currentSegment(float[] coords)
{
- int seg, numCoords;
+ int seg;
+ int numCoords;
- seg = path.types[pos >> 1];
+ seg = path.types[pos];
numCoords = NUM_COORDS[seg];
if (numCoords > 0)
- {
- if (transform == null)
- System.arraycopy(path.points, pos, coords, 0, numCoords);
- else
- transform.transform(/* src */ path.points, /* srcOffset */ pos,
- /* dest */ coords, /* destOffset */ 0,
- /* numPoints */ numCoords >> 1);
- }
+ {
+ for (int i = 0; i < numCoords; i++)
+ {
+ coords[i << 1] = path.xpoints[pos + i];
+ coords[(i << 1) + 1] = path.ypoints[pos + i];
+ }
+
+ if (transform != null)
+ transform.transform( /* src */
+ coords, /* srcOffset */
+ 0, /* dest */ coords, /* destOffset */
+ 0, /* numPoints */ numCoords);
+ }
return seg;
}
-
/**
* Returns the current segment in double coordinates.
*/
public int currentSegment(double[] coords)
{
- int seg, numCoords;
+ int seg;
+ int numCoords;
- seg = path.types[pos >> 1];
+ seg = path.types[pos];
numCoords = NUM_COORDS[seg];
if (numCoords > 0)
- {
- if (transform == null)
{
- // System.arraycopy throws an exception if the source and destination
- // array are not of the same primitive type.
- for (int i = 0; i < numCoords; i++)
- coords[i] = (double) path.points[pos + i];
+ for (int i = 0; i < numCoords; i++)
+ {
+ coords[i << 1] = (double) path.xpoints[pos + i];
+ coords[(i << 1) + 1] = (double) path.ypoints[pos + i];
+ }
+ if (transform != null)
+ transform.transform( /* src */
+ coords, /* srcOffset */
+ pos, /* dest */ coords, /* destOffset */
+ 0, /* numPoints */ numCoords);
}
- else
- transform.transform(/* src */ path.points, /* srcOffset */ pos,
- /* dest */ coords, /* destOffset */ 0,
- /* numPoints */ numCoords >> 1);
- }
return seg;
}
}
-
/**
- * Creates a PathIterator for iterating along the segments of this path.
+ * Creates a PathIterator for iterating along the segments of the path.
*
* @param at an affine transformation for projecting the returned
* points, or <code>null</code> to let the created iterator return
@@ -439,15 +660,17 @@ public final class GeneralPath implements Shape, Cloneable
return new GeneralPathIterator(this, at);
}
-
+ /**
+ * Creates a new FlatteningPathIterator for the path
+ */
public PathIterator getPathIterator(AffineTransform at, double flatness)
{
return new FlatteningPathIterator(getPathIterator(at), flatness);
}
/**
- * Create a new shape of the same run-time type with the same contents as
- * this one.
+ * Creates a new shape of the same run-time type with the same contents
+ * as this one.
*
* @return the clone
*
@@ -461,17 +684,261 @@ public final class GeneralPath implements Shape, Cloneable
return new GeneralPath(this);
}
+ /**
+ * Helper method - ensure the size of the data arrays,
+ * otherwise, reallocate new ones twice the size
+ */
private void ensureSize(int size)
{
if (subpath < 0)
throw new IllegalPathStateException("need initial moveto");
- if (size <= points.length)
+ if (size <= xpoints.length)
return;
- byte[] b = new byte[points.length];
- System.arraycopy(types, 0, b, 0, index >> 1);
+ byte[] b = new byte[types.length << 1];
+ System.arraycopy(types, 0, b, 0, index);
types = b;
- float[] f = new float[points.length << 1];
- System.arraycopy(points, 0, f, 0, index);
- points = f;
+ float[] f = new float[xpoints.length << 1];
+ System.arraycopy(xpoints, 0, f, 0, index);
+ xpoints = f;
+ f = new float[ypoints.length << 1];
+ System.arraycopy(ypoints, 0, f, 0, index);
+ ypoints = f;
+ }
+
+ /**
+ * Helper method - Get the total number of intersections from (x,y) along
+ * a given axis, within a given distance.
+ */
+ private int getAxisIntersections(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ return (evaluateCrossings(x, y, false, useYaxis, distance));
+ }
+
+ /**
+ * Helper method - returns the winding number of a point.
+ */
+ private int getWindingNumber(double x, double y)
+ {
+ /* Evaluate the crossings from x,y to infinity on the y axis (arbitrary
+ choice). Note that we don't actually use Double.INFINITY, since that's
+ slower, and may cause problems. */
+ return (evaluateCrossings(x, y, true, true, BIG_VALUE));
+ }
+
+ /**
+ * Helper method - evaluates the number of intersections on an axis from
+ * the point (x,y) to the point (x,y+distance) or (x+distance,y).
+ * @param x x coordinate.
+ * @param y y coordinate.
+ * @param neg True if opposite-directed intersections should cancel,
+ * false to sum all intersections.
+ * @param useYaxis Use the Y axis, false uses the X axis.
+ * @param distance Interval from (x,y) on the selected axis to find
+ * intersections.
+ */
+ private int evaluateCrossings(double x, double y, boolean neg,
+ boolean useYaxis, double distance)
+ {
+ float cx = 0.0f;
+ float cy = 0.0f;
+ float firstx = 0.0f;
+ float firsty = 0.0f;
+
+ int negative = (neg) ? -1 : 1;
+ double x0;
+ double x1;
+ double x2;
+ double x3;
+ double y0;
+ double y1;
+ double y2;
+ double y3;
+ double[] r = new double[4];
+ int nRoots;
+ double epsilon = 0.0;
+ int pos = 0;
+ int windingNumber = 0;
+ boolean pathStarted = false;
+
+ if (index == 0)
+ return (0);
+ if (useYaxis)
+ {
+ float[] swap1;
+ swap1 = ypoints;
+ ypoints = xpoints;
+ xpoints = swap1;
+ double swap2;
+ swap2 = y;
+ y = x;
+ x = swap2;
+ }
+
+ /* Get a value which is hopefully small but not insignificant relative
+ the path. */
+ epsilon = ypoints[0] * 1E-9;
+
+ pos = 0;
+ while (pos < index)
+ {
+ switch (types[pos])
+ {
+ case PathIterator.SEG_MOVETO:
+ if (pathStarted) // close old path
+ {
+ x0 = cx;
+ y0 = cy;
+ x1 = firstx;
+ y1 = firsty;
+
+ if (y0 == 0.0)
+ y0 += epsilon;
+ if (y1 == 0.0)
+ y1 += epsilon;
+ if (Line2D.linesIntersect(x0, y0, x1, y1, 0.0, 0.0, distance,
+ 0.0))
+ windingNumber += (y1 < y0) ? 1 : negative;
+
+ cx = firstx;
+ cy = firsty;
+ }
+ cx = firstx = xpoints[pos] - (float) x;
+ cy = firsty = ypoints[pos++] - (float) y;
+ pathStarted = true;
+ break;
+ case PathIterator.SEG_CLOSE:
+ x0 = cx;
+ y0 = cy;
+ x1 = firstx;
+ y1 = firsty;
+
+ if (y0 == 0.0)
+ y0 += epsilon;
+ if (y1 == 0.0)
+ y1 += epsilon;
+ if (Line2D.linesIntersect(x0, y0, x1, y1, 0.0, 0.0, distance, 0.0))
+ windingNumber += (y1 < y0) ? 1 : negative;
+
+ cx = firstx;
+ cy = firsty;
+ pos++;
+ pathStarted = false;
+ break;
+ case PathIterator.SEG_LINETO:
+ x0 = cx;
+ y0 = cy;
+ x1 = xpoints[pos] - (float) x;
+ y1 = ypoints[pos++] - (float) y;
+
+ if (y0 == 0.0)
+ y0 += epsilon;
+ if (y1 == 0.0)
+ y1 += epsilon;
+ if (Line2D.linesIntersect(x0, y0, x1, y1, 0.0, 0.0, distance, 0.0))
+ windingNumber += (y1 < y0) ? 1 : negative;
+
+ cx = xpoints[pos - 1] - (float) x;
+ cy = ypoints[pos - 1] - (float) y;
+ break;
+ case PathIterator.SEG_QUADTO:
+ x0 = cx;
+ y0 = cy;
+ x1 = xpoints[pos] - x;
+ y1 = ypoints[pos++] - y;
+ x2 = xpoints[pos] - x;
+ y2 = ypoints[pos++] - y;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0)
+ && (y0 * y1 <= 0 || y1 * y2 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 += epsilon;
+ if (y2 == 0.0)
+ y2 += epsilon;
+
+ r[0] = y0;
+ r[1] = 2 * (y1 - y0);
+ r[2] = (y2 - 2 * y1 + y0);
+
+ /* degenerate roots (=tangent points) do not
+ contribute to the winding number. */
+ if ((nRoots = QuadCurve2D.solveQuadratic(r)) == 2)
+ for (int i = 0; i < nRoots; i++)
+ {
+ float t = (float) r[i];
+ if (t > 0.0f && t < 1.0f)
+ {
+ double crossing = t * t * (x2 - 2 * x1 + x0)
+ + 2 * t * (x1 - x0) + x0;
+ if (crossing >= 0.0 && crossing <= distance)
+ windingNumber += (2 * t * (y2 - 2 * y1 + y0)
+ + 2 * (y1 - y0) < 0) ? 1 : negative;
+ }
+ }
+ }
+
+ cx = xpoints[pos - 1] - (float) x;
+ cy = ypoints[pos - 1] - (float) y;
+ break;
+ case PathIterator.SEG_CUBICTO:
+ x0 = cx;
+ y0 = cy;
+ x1 = xpoints[pos] - x;
+ y1 = ypoints[pos++] - y;
+ x2 = xpoints[pos] - x;
+ y2 = ypoints[pos++] - y;
+ x3 = xpoints[pos] - x;
+ y3 = ypoints[pos++] - y;
+
+ /* check if curve may intersect X+ axis. */
+ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0)
+ && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0))
+ {
+ if (y0 == 0.0)
+ y0 += epsilon;
+ if (y3 == 0.0)
+ y3 += epsilon;
+
+ r[0] = y0;
+ r[1] = 3 * (y1 - y0);
+ r[2] = 3 * (y2 + y0 - 2 * y1);
+ r[3] = y3 - 3 * y2 + 3 * y1 - y0;
+
+ if ((nRoots = CubicCurve2D.solveCubic(r)) != 0)
+ for (int i = 0; i < nRoots; i++)
+ {
+ float t = (float) r[i];
+ if (t > 0.0 && t < 1.0)
+ {
+ double crossing = -(t * t * t) * (x0 - 3 * x1
+ + 3 * x2 - x3)
+ + 3 * t * t * (x0 - 2 * x1 + x2)
+ + 3 * t * (x1 - x0) + x0;
+ if (crossing >= 0 && crossing <= distance)
+ windingNumber += (3 * t * t * (y3 + 3 * y1
+ - 3 * y2 - y0)
+ + 6 * t * (y0 - 2 * y1 + y2)
+ + 3 * (y1 - y0) < 0) ? 1 : negative;
+ }
+ }
+ }
+
+ cx = xpoints[pos - 1] - (float) x;
+ cy = ypoints[pos - 1] - (float) y;
+ break;
+ }
+ }
+
+ // swap coordinates back
+ if (useYaxis)
+ {
+ float[] swap;
+ swap = ypoints;
+ ypoints = xpoints;
+ xpoints = swap;
+ }
+ return (windingNumber);
}
} // class GeneralPath
diff --git a/libjava/java/awt/geom/QuadCurve2D.java b/libjava/java/awt/geom/QuadCurve2D.java
index 409c484..0cc9eb4 100644
--- a/libjava/java/awt/geom/QuadCurve2D.java
+++ b/libjava/java/awt/geom/QuadCurve2D.java
@@ -1,5 +1,5 @@
/* QuadCurve2D.java -- represents a parameterized quadratic curve in 2-D space
- Copyright (C) 2002, 2003 Free Software Foundation
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -35,7 +35,6 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-
package java.awt.geom;
import java.awt.Rectangle;
@@ -53,12 +52,14 @@ import java.util.NoSuchElementException;
* @author Eric Blake (ebb9@email.byu.edu)
* @author Graydon Hoare (graydon@redhat.com)
* @author Sascha Brawer (brawer@dandelis.ch)
+ * @author Sven de Marothy (sven@physto.se)
*
* @since 1.2
*/
-public abstract class QuadCurve2D
- implements Shape, Cloneable
+public abstract class QuadCurve2D implements Shape, Cloneable
{
+ private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0;
+
/**
* Constructs a new QuadCurve2D. Typical users will want to
* construct instances of a subclass, such as {@link
@@ -68,67 +69,57 @@ public abstract class QuadCurve2D
{
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s start
* point.
*/
public abstract double getX1();
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s start
* point.
*/
public abstract double getY1();
-
/**
* Returns the curve&#x2019;s start point.
*/
public abstract Point2D getP1();
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s control
* point.
*/
public abstract double getCtrlX();
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s control
* point.
*/
public abstract double getCtrlY();
-
/**
* Returns the curve&#x2019;s control point.
*/
public abstract Point2D getCtrlPt();
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s end
* point.
*/
public abstract double getX2();
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s end
* point.
*/
public abstract double getY2();
-
/**
* Returns the curve&#x2019;s end point.
*/
public abstract Point2D getP2();
-
/**
* Changes the curve geometry, separately specifying each coordinate
* value.
@@ -154,7 +145,6 @@ public abstract class QuadCurve2D
public abstract void setCurve(double x1, double y1, double cx, double cy,
double x2, double y2);
-
/**
* Changes the curve geometry, passing coordinate values in an
* array.
@@ -174,12 +164,10 @@ public abstract class QuadCurve2D
*/
public void setCurve(double[] coords, int offset)
{
- setCurve(coords[offset++], coords[offset++],
- coords[offset++], coords[offset++],
- coords[offset++], coords[offset++]);
+ setCurve(coords[offset++], coords[offset++], coords[offset++],
+ coords[offset++], coords[offset++], coords[offset++]);
}
-
/**
* Changes the curve geometry, specifying coordinate values in
* separate Point objects.
@@ -198,11 +186,9 @@ public abstract class QuadCurve2D
*/
public void setCurve(Point2D p1, Point2D c, Point2D p2)
{
- setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(),
- p2.getX(), p2.getY());
+ setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(), p2.getX(), p2.getY());
}
-
/**
* Changes the curve geometry, specifying coordinate values in an
* array of Point objects.
@@ -223,12 +209,11 @@ public abstract class QuadCurve2D
*/
public void setCurve(Point2D[] pts, int offset)
{
- setCurve(pts[offset].getX(), pts[offset].getY(),
- pts[offset + 1].getX(), pts[offset + 1].getY(),
- pts[offset + 2].getX(), pts[offset + 2].getY());
+ setCurve(pts[offset].getX(), pts[offset].getY(), pts[offset + 1].getX(),
+ pts[offset + 1].getY(), pts[offset + 2].getX(),
+ pts[offset + 2].getY());
}
-
/**
* Changes the geometry of the curve to that of another curve.
*
@@ -236,11 +221,10 @@ public abstract class QuadCurve2D
*/
public void setCurve(QuadCurve2D c)
{
- setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(),
- c.getX2(), c.getY2());
+ setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(), c.getX2(),
+ c.getY2());
}
-
/**
* Calculates the squared flatness of a quadratic curve, directly
* specifying each coordinate value. The flatness is the distance of
@@ -267,7 +251,6 @@ public abstract class QuadCurve2D
return Line2D.ptSegDistSq(x1, y1, x2, y2, cx, cy);
}
-
/**
* Calculates the flatness of a quadratic curve, directly specifying
* each coordinate value. The flatness is the distance of the
@@ -294,7 +277,6 @@ public abstract class QuadCurve2D
return Line2D.ptSegDist(x1, y1, x2, y2, cx, cy);
}
-
/**
* Calculates the squared flatness of a quadratic curve, specifying
* the coordinate values in an array. The flatness is the distance
@@ -328,7 +310,6 @@ public abstract class QuadCurve2D
coords[offset + 2], coords[offset + 3]);
}
-
/**
* Calculates the flatness of a quadratic curve, specifying the
* coordinate values in an array. The flatness is the distance of
@@ -362,7 +343,6 @@ public abstract class QuadCurve2D
coords[offset + 2], coords[offset + 3]);
}
-
/**
* Calculates the squared flatness of this curve. The flatness is
* the distance of the control point to the line between start and
@@ -378,12 +358,10 @@ public abstract class QuadCurve2D
*/
public double getFlatnessSq()
{
- return Line2D.ptSegDistSq(getX1(), getY1(),
- getX2(), getY2(),
- getCtrlX(), getCtrlY());
+ return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
+ getCtrlY());
}
-
/**
* Calculates the flatness of this curve. The flatness is the
* distance of the control point to the line between start and end
@@ -399,12 +377,10 @@ public abstract class QuadCurve2D
*/
public double getFlatness()
{
- return Line2D.ptSegDist(getX1(), getY1(),
- getX2(), getY2(),
- getCtrlX(), getCtrlY());
+ return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(),
+ getCtrlY());
}
-
/**
* Subdivides this curve into two halves.
*
@@ -423,8 +399,11 @@ public abstract class QuadCurve2D
public void subdivide(QuadCurve2D left, QuadCurve2D right)
{
// Use empty slots at end to share single array.
- double[] d = new double[] { getX1(), getY1(), getCtrlX(), getCtrlY(),
- getX2(), getY2(), 0, 0, 0, 0 };
+ double[] d = new double[]
+ {
+ getX1(), getY1(), getCtrlX(), getCtrlY(), getX2(), getY2(),
+ 0, 0, 0, 0
+ };
subdivide(d, 0, d, 0, d, 4);
if (left != null)
left.setCurve(d, 0);
@@ -432,7 +411,6 @@ public abstract class QuadCurve2D
right.setCurve(d, 4);
}
-
/**
* Subdivides a quadratic curve into two halves.
*
@@ -456,7 +434,6 @@ public abstract class QuadCurve2D
src.subdivide(left, right);
}
-
/**
* Subdivides a quadratic curve into two halves, passing all
* coordinates in an array.
@@ -500,11 +477,15 @@ public abstract class QuadCurve2D
* index where the start point&#x2019;s <i>x</i> coordinate will be
* stored.
*/
- public static void subdivide(double[] src, int srcOff,
- double[] left, int leftOff,
- double[] right, int rightOff)
+ public static void subdivide(double[] src, int srcOff, double[] left,
+ int leftOff, double[] right, int rightOff)
{
- double x1, y1, xc, yc, x2, y2;
+ double x1;
+ double y1;
+ double xc;
+ double yc;
+ double x2;
+ double y2;
x1 = src[srcOff];
y1 = src[srcOff + 1];
@@ -514,16 +495,16 @@ public abstract class QuadCurve2D
y2 = src[srcOff + 5];
if (left != null)
- {
- left[leftOff] = x1;
- left[leftOff + 1] = y1;
- }
+ {
+ left[leftOff] = x1;
+ left[leftOff + 1] = y1;
+ }
if (right != null)
- {
- right[rightOff + 4] = x2;
- right[rightOff + 5] = y2;
- }
+ {
+ right[rightOff + 4] = x2;
+ right[rightOff + 5] = y2;
+ }
x1 = (x1 + xc) / 2;
x2 = (xc + x2) / 2;
@@ -533,23 +514,22 @@ public abstract class QuadCurve2D
yc = (y1 + y2) / 2;
if (left != null)
- {
- left[leftOff + 2] = x1;
- left[leftOff + 3] = y1;
- left[leftOff + 4] = xc;
- left[leftOff + 5] = yc;
- }
+ {
+ left[leftOff + 2] = x1;
+ left[leftOff + 3] = y1;
+ left[leftOff + 4] = xc;
+ left[leftOff + 5] = yc;
+ }
if (right != null)
- {
- right[rightOff] = xc;
- right[rightOff + 1] = yc;
- right[rightOff + 2] = x2;
- right[rightOff + 3] = y2;
- }
+ {
+ right[rightOff] = xc;
+ right[rightOff + 1] = yc;
+ right[rightOff + 2] = x2;
+ right[rightOff + 3] = y2;
+ }
}
-
/**
* Finds the non-complex roots of a quadratic equation, placing the
* results into the same array as the equation coefficients. The
@@ -594,7 +574,6 @@ public abstract class QuadCurve2D
return solveQuadratic(eqn, eqn);
}
-
/**
* Finds the non-complex roots of a quadratic equation. The
* following equation is being solved:
@@ -649,8 +628,10 @@ public abstract class QuadCurve2D
// The Java implementation is very similar to the GSL code, but
// not a strict one-to-one copy. For example, GSL would sort the
// result.
-
- double a, b, c, disc;
+ double a;
+ double b;
+ double c;
+ double disc;
c = eqn[0];
b = eqn[1];
@@ -661,13 +642,13 @@ public abstract class QuadCurve2D
// wouldn't return -1 for constant functions, and 2 instead of 1
// for linear functions.
if (a == 0)
- {
- if (b == 0)
- return -1;
-
- res[0] = -c / b;
- return 1;
- }
+ {
+ if (b == 0)
+ return -1;
+
+ res[0] = -c / b;
+ return 1;
+ }
disc = b * b - 4 * a * c;
@@ -675,96 +656,149 @@ public abstract class QuadCurve2D
return 0;
if (disc == 0)
- {
- // The GNU Scientific Library returns two identical results here.
- // We just return one.
- res[0] = -0.5 * b / a ;
- return 1;
- }
+ {
+ // The GNU Scientific Library returns two identical results here.
+ // We just return one.
+ res[0] = -0.5 * b / a;
+ return 1;
+ }
// disc > 0
if (b == 0)
- {
- double r;
+ {
+ double r;
- r = Math.abs(0.5 * Math.sqrt(disc) / a);
- res[0] = -r;
- res[1] = r;
- }
+ r = Math.abs(0.5 * Math.sqrt(disc) / a);
+ res[0] = -r;
+ res[1] = r;
+ }
else
- {
- double sgnb, temp;
-
- sgnb = (b > 0 ? 1 : -1);
- temp = -0.5 * (b + sgnb * Math.sqrt(disc));
-
- // The GNU Scientific Library sorts the result here. We don't.
- res[0] = temp / a;
- res[1] = c / temp;
- }
+ {
+ double sgnb;
+ double temp;
+
+ sgnb = (b > 0 ? 1 : -1);
+ temp = -0.5 * (b + sgnb * Math.sqrt(disc));
+
+ // The GNU Scientific Library sorts the result here. We don't.
+ res[0] = temp / a;
+ res[1] = c / temp;
+ }
return 2;
}
-
/**
- * Determines whether a point lies inside the area that is bounded
+ * Determines whether a point is inside the area bounded
* by the curve and the straight line connecting its end points.
*
* <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
* alt="A drawing of the area spanned by the curve" />
*
* <p>The above drawing illustrates in which area points are
- * considered &#x201c;contained&#x201d; in a QuadCurve2D.
+ * considered &#x201c;inside&#x201d; a QuadCurve2D.
*/
public boolean contains(double x, double y)
{
- // XXX Implement.
- throw new Error("not implemented");
- }
+ if (! getBounds2D().contains(x, y))
+ return false;
+ return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0);
+ }
/**
- * Determines whether a point lies inside the area that is bounded
+ * Determines whether a point is inside the area bounded
* by the curve and the straight line connecting its end points.
*
* <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
* alt="A drawing of the area spanned by the curve" />
*
* <p>The above drawing illustrates in which area points are
- * considered &#x201c;contained&#x201d; in a QuadCurve2D.
+ * considered &#x201c;inside&#x201d; a QuadCurve2D.
*/
public boolean contains(Point2D p)
{
return contains(p.getX(), p.getY());
}
-
+ /**
+ * Determines whether any part of a rectangle is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; in a CubicCurve2D.
+ */
public boolean intersects(double x, double y, double w, double h)
{
- // XXX Implement.
- throw new Error("not implemented");
- }
+ if (! getBounds2D().contains(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return true;
+
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+ return false;
+ }
+ /**
+ * Determines whether any part of a Rectangle2D is inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ * @see #intersects(double, double, double, double)
+ */
public boolean intersects(Rectangle2D r)
{
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
-
+ /**
+ * Determines whether a rectangle is entirely inside the area bounded
+ * by the curve and the straight line connecting its end points.
+ *
+ * <p><img src="doc-files/QuadCurve2D-5.png" width="350" height="180"
+ * alt="A drawing of the area spanned by the curve" />
+ *
+ * <p>The above drawing illustrates in which area points are
+ * considered &#x201c;inside&#x201d; a QuadCurve2D.
+ * @see #contains(double, double)
+ */
public boolean contains(double x, double y, double w, double h)
{
- // XXX Implement.
- throw new Error("not implemented");
- }
+ if (! getBounds2D().intersects(x, y, w, h))
+ return false;
+
+ /* Does any edge intersect? */
+ if (getAxisIntersections(x, y, true, w) != 0 /* top */
+ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */
+ || getAxisIntersections(x + w, y, false, h) != 0 /* right */
+ || getAxisIntersections(x, y, false, h) != 0) /* left */
+ return false;
+ /* No intersections, is any point inside? */
+ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0)
+ return true;
+ return false;
+ }
+
+ /**
+ * Determines whether a Rectangle2D is entirely inside the area that is
+ * bounded by the curve and the straight line connecting its end points.
+ * @see #contains(double, double, double, double)
+ */
public boolean contains(Rectangle2D r)
{
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
-
/**
* Determines the smallest rectangle that encloses the
* curve&#x2019;s start, end and control point. As the illustration
@@ -780,97 +814,85 @@ public abstract class QuadCurve2D
return getBounds2D().getBounds();
}
-
public PathIterator getPathIterator(final AffineTransform at)
{
return new PathIterator()
- {
- /** Current coordinate. */
- private int current = 0;
-
-
- public int getWindingRule()
- {
- return WIND_NON_ZERO;
- }
-
-
- public boolean isDone()
- {
- return current >= 2;
- }
-
-
- public void next()
- {
- current++;
- }
-
-
- public int currentSegment(float[] coords)
{
- int result;
- switch (current)
- {
- case 0:
- coords[0] = (float) getX1();
- coords[1] = (float) getY1();
- result = SEG_MOVETO;
- break;
-
- case 1:
- coords[0] = (float) getCtrlX();
- coords[1] = (float) getCtrlY();
- coords[2] = (float) getX2();
- coords[3] = (float) getY2();
- result = SEG_QUADTO;
- break;
-
- default:
- throw new NoSuchElementException("quad iterator out of bounds");
- }
- if (at != null)
- at.transform(coords, 0, coords, 0, 2);
- return result;
- }
-
-
- public int currentSegment(double[] coords)
- {
- int result;
- switch (current)
- {
- case 0:
- coords[0] = getX1();
- coords[1] = getY1();
- result = SEG_MOVETO;
- break;
-
- case 1:
- coords[0] = getCtrlX();
- coords[1] = getCtrlY();
- coords[2] = getX2();
- coords[3] = getY2();
- result = SEG_QUADTO;
- break;
-
- default:
- throw new NoSuchElementException("quad iterator out of bounds");
- }
- if (at != null)
- at.transform(coords, 0, coords, 0, 2);
- return result;
- }
- };
+ /** Current coordinate. */
+ private int current = 0;
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current >= 2;
+ }
+
+ public void next()
+ {
+ current++;
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = (float) getX1();
+ coords[1] = (float) getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = (float) getCtrlX();
+ coords[1] = (float) getCtrlY();
+ coords[2] = (float) getX2();
+ coords[3] = (float) getY2();
+ result = SEG_QUADTO;
+ break;
+ default:
+ throw new NoSuchElementException("quad iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 2);
+ return result;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = getX1();
+ coords[1] = getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = getCtrlX();
+ coords[1] = getCtrlY();
+ coords[2] = getX2();
+ coords[3] = getY2();
+ result = SEG_QUADTO;
+ break;
+ default:
+ throw new NoSuchElementException("quad iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 2);
+ return result;
+ }
+ };
}
-
public PathIterator getPathIterator(AffineTransform at, double flatness)
{
return new FlatteningPathIterator(getPathIterator(at), flatness);
}
-
/**
* Creates a new curve with the same contents as this one.
*
@@ -879,15 +901,106 @@ public abstract class QuadCurve2D
public Object clone()
{
try
- {
- return super.clone();
- }
+ {
+ return super.clone();
+ }
catch (CloneNotSupportedException e)
- {
- throw (Error) new InternalError().initCause(e); // Impossible
- }
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
}
+ /**
+ * Helper method used by contains() and intersects() methods
+ * Return the number of curve/line intersections on a given axis
+ * extending from a certain point. useYaxis is true for using the Y axis,
+ * @param x x coordinate of the origin point
+ * @param y y coordinate of the origin point
+ * @param useYaxis axis to follow, if true the positive Y axis is used,
+ * false uses the positive X axis.
+ *
+ * This is an implementation of the line-crossings algorithm,
+ * Detailed in an article on Eric Haines' page:
+ * http://www.acm.org/tog/editors/erich/ptinpoly/
+ */
+ private int getAxisIntersections(double x, double y, boolean useYaxis,
+ double distance)
+ {
+ int nCrossings = 0;
+ double a0;
+ double a1;
+ double a2;
+ double b0;
+ double b1;
+ double b2;
+ double[] r = new double[3];
+ int nRoots;
+
+ a0 = a2 = 0.0;
+
+ if (useYaxis)
+ {
+ a0 = getY1() - y;
+ a1 = getCtrlY() - y;
+ a2 = getY2() - y;
+ b0 = getX1() - x;
+ b1 = getCtrlX() - x;
+ b2 = getX2() - x;
+ }
+ else
+ {
+ a0 = getX1() - x;
+ a1 = getCtrlX() - x;
+ a2 = getX2() - x;
+ b0 = getY1() - y;
+ b1 = getCtrlY() - y;
+ b2 = getY2() - y;
+ }
+
+ /* If the axis intersects a start/endpoint, shift it up by some small
+ amount to guarantee the line is 'inside'
+ If this is not done,bad behaviour may result for points on that axis. */
+ if (a0 == 0.0 || a2 == 0.0)
+ {
+ double small = getFlatness() * (1E-10);
+ if (a0 == 0.0)
+ a0 += small;
+
+ if (a2 == 0.0)
+ a2 += small;
+ }
+
+ r[0] = a0;
+ r[1] = 2 * (a1 - a0);
+ r[2] = (a2 - 2 * a1 + a0);
+
+ nRoots = solveQuadratic(r);
+ for (int i = 0; i < nRoots; i++)
+ {
+ double t = r[i];
+ if (t >= 0.0 && t <= 1.0)
+ {
+ double crossing = t * t * (b2 - 2 * b1 + b0) + 2 * t * (b1 - b0)
+ + b0;
+ /* single root is always doubly degenerate in quads */
+ if (crossing > 0 && crossing < distance)
+ nCrossings += (nRoots == 1) ? 2 : 1;
+ }
+ }
+
+ if (useYaxis)
+ {
+ if (Line2D.linesIntersect(b0, a0, b2, a2, 0.0, 0.0, distance, 0.0))
+ nCrossings++;
+ }
+ else
+ {
+ if (Line2D.linesIntersect(a0, b0, a2, b2, 0.0, 0.0, 0.0, distance))
+ nCrossings++;
+ }
+
+ return (nCrossings);
+ }
/**
* A two-dimensional curve that is parameterized with a quadratic
@@ -899,45 +1012,38 @@ public abstract class QuadCurve2D
* @author Eric Blake (ebb9@email.byu.edu)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
- public static class Double
- extends QuadCurve2D
+ public static class Double extends QuadCurve2D
{
/**
* The <i>x</i> coordinate of the curve&#x2019;s start point.
*/
public double x1;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s start point.
*/
public double y1;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s control point.
*/
public double ctrlx;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s control point.
*/
public double ctrly;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s end point.
*/
public double x2;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s end point.
*/
public double y2;
-
/**
* Constructs a new QuadCurve2D that stores its coordinate values
* in double-precision floating-point format. All points are
@@ -947,7 +1053,6 @@ public abstract class QuadCurve2D
{
}
-
/**
* Constructs a new QuadCurve2D that stores its coordinate values
* in double-precision floating-point format, specifying the
@@ -971,8 +1076,8 @@ public abstract class QuadCurve2D
* @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
* point.
*/
- public Double(double x1, double y1, double cx, double cy,
- double x2, double y2)
+ public Double(double x1, double y1, double cx, double cy, double x2,
+ double y2)
{
this.x1 = x1;
this.y1 = y1;
@@ -982,7 +1087,6 @@ public abstract class QuadCurve2D
this.y2 = y2;
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s start
* point.
@@ -992,7 +1096,6 @@ public abstract class QuadCurve2D
return x1;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s start
* point.
@@ -1002,7 +1105,6 @@ public abstract class QuadCurve2D
return y1;
}
-
/**
* Returns the curve&#x2019;s start point.
*/
@@ -1011,7 +1113,6 @@ public abstract class QuadCurve2D
return new Point2D.Double(x1, y1);
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s control
* point.
@@ -1021,7 +1122,6 @@ public abstract class QuadCurve2D
return ctrlx;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s control
* point.
@@ -1031,7 +1131,6 @@ public abstract class QuadCurve2D
return ctrly;
}
-
/**
* Returns the curve&#x2019;s control point.
*/
@@ -1040,7 +1139,6 @@ public abstract class QuadCurve2D
return new Point2D.Double(ctrlx, ctrly);
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s end
* point.
@@ -1050,7 +1148,6 @@ public abstract class QuadCurve2D
return x2;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s end
* point.
@@ -1060,7 +1157,6 @@ public abstract class QuadCurve2D
return y2;
}
-
/**
* Returns the curve&#x2019;s end point.
*/
@@ -1069,7 +1165,6 @@ public abstract class QuadCurve2D
return new Point2D.Double(x2, y2);
}
-
/**
* Changes the geometry of the curve.
*
@@ -1102,7 +1197,6 @@ public abstract class QuadCurve2D
this.y2 = y2;
}
-
/**
* Determines the smallest rectangle that encloses the
* curve&#x2019;s start, end and control point. As the
@@ -1123,7 +1217,6 @@ public abstract class QuadCurve2D
}
}
-
/**
* A two-dimensional curve that is parameterized with a quadratic
* function and stores coordinate values in single-precision
@@ -1134,45 +1227,38 @@ public abstract class QuadCurve2D
* @author Eric Blake (ebb9@email.byu.edu)
* @author Sascha Brawer (brawer@dandelis.ch)
*/
- public static class Float
- extends QuadCurve2D
+ public static class Float extends QuadCurve2D
{
/**
* The <i>x</i> coordinate of the curve&#x2019;s start point.
*/
public float x1;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s start point.
*/
public float y1;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s control point.
*/
public float ctrlx;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s control point.
*/
public float ctrly;
-
/**
* The <i>x</i> coordinate of the curve&#x2019;s end point.
*/
public float x2;
-
/**
* The <i>y</i> coordinate of the curve&#x2019;s end point.
*/
public float y2;
-
/**
* Constructs a new QuadCurve2D that stores its coordinate values
* in single-precision floating-point format. All points are
@@ -1182,7 +1268,6 @@ public abstract class QuadCurve2D
{
}
-
/**
* Constructs a new QuadCurve2D that stores its coordinate values
* in single-precision floating-point format, specifying the
@@ -1206,8 +1291,7 @@ public abstract class QuadCurve2D
* @param y2 the <i>y</i> coordinate of the curve&#x2019;s end
* point.
*/
- public Float(float x1, float y1, float cx, float cy,
- float x2, float y2)
+ public Float(float x1, float y1, float cx, float cy, float x2, float y2)
{
this.x1 = x1;
this.y1 = y1;
@@ -1217,7 +1301,6 @@ public abstract class QuadCurve2D
this.y2 = y2;
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s start
* point.
@@ -1227,7 +1310,6 @@ public abstract class QuadCurve2D
return x1;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s start
* point.
@@ -1237,7 +1319,6 @@ public abstract class QuadCurve2D
return y1;
}
-
/**
* Returns the curve&#x2019;s start point.
*/
@@ -1246,7 +1327,6 @@ public abstract class QuadCurve2D
return new Point2D.Float(x1, y1);
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s control
* point.
@@ -1256,7 +1336,6 @@ public abstract class QuadCurve2D
return ctrlx;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s control
* point.
@@ -1266,7 +1345,6 @@ public abstract class QuadCurve2D
return ctrly;
}
-
/**
* Returns the curve&#x2019;s control point.
*/
@@ -1275,7 +1353,6 @@ public abstract class QuadCurve2D
return new Point2D.Float(ctrlx, ctrly);
}
-
/**
* Returns the <i>x</i> coordinate of the curve&#x2019;s end
* point.
@@ -1285,7 +1362,6 @@ public abstract class QuadCurve2D
return x2;
}
-
/**
* Returns the <i>y</i> coordinate of the curve&#x2019;s end
* point.
@@ -1295,7 +1371,6 @@ public abstract class QuadCurve2D
return y2;
}
-
/**
* Returns the curve&#x2019;s end point.
*/
@@ -1304,7 +1379,6 @@ public abstract class QuadCurve2D
return new Point2D.Float(x2, y2);
}
-
/**
* Changes the geometry of the curve, specifying coordinate values
* as double-precision floating-point numbers.
@@ -1338,7 +1412,6 @@ public abstract class QuadCurve2D
this.y2 = (float) y2;
}
-
/**
* Changes the geometry of the curve, specifying coordinate values
* as single-precision floating-point numbers.
@@ -1361,8 +1434,8 @@ public abstract class QuadCurve2D
* @param y2 the <i>y</i> coordinate of the curve&#x2019;s new
* end point.
*/
- public void setCurve(float x1, float y1, float cx, float cy,
- float x2, float y2)
+ public void setCurve(float x1, float y1, float cx, float cy, float x2,
+ float y2)
{
this.x1 = x1;
this.y1 = y1;
@@ -1372,7 +1445,6 @@ public abstract class QuadCurve2D
this.y2 = y2;
}
-
/**
* Determines the smallest rectangle that encloses the
* curve&#x2019;s start, end and control point. As the
diff --git a/libjava/java/awt/geom/RoundRectangle2D.java b/libjava/java/awt/geom/RoundRectangle2D.java
index 3a7899d..3f004ed 100644
--- a/libjava/java/awt/geom/RoundRectangle2D.java
+++ b/libjava/java/awt/geom/RoundRectangle2D.java
@@ -1,5 +1,5 @@
/* RoundRectangle2D.java -- represents a rectangle with rounded corners
- Copyright (C) 2000, 2002, 2003 Free Software Foundation
+ Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation
This file is part of GNU Classpath.
@@ -39,6 +39,7 @@ package java.awt.geom;
import java.util.NoSuchElementException;
+
/** This class implements a rectangle with rounded corners.
* @author Tom Tromey <tromey@cygnus.com>
* @date December 3, 2000
@@ -60,12 +61,12 @@ public abstract class RoundRectangle2D extends RectangularShape
* @param arcHeight The arc height
*/
public abstract void setRoundRect(double x, double y, double w, double h,
- double arcWidth, double arcHeight);
+ double arcWidth, double arcHeight);
/** Create a RoundRectangle2D. This is protected because this class
* is abstract and cannot be instantiated.
*/
- protected RoundRectangle2D()
+ protected RoundRectangle2D()
{
}
@@ -87,8 +88,11 @@ public abstract class RoundRectangle2D extends RectangularShape
// Now check to see if the point is in range of an arc.
double dy = Math.min(Math.abs(my - y), Math.abs(my + mh - y));
double dx = Math.min(Math.abs(mx - x), Math.abs(mx + mw - x));
- double aw = getArcWidth();
- double ah = getArcHeight();
+
+ // The arc dimensions are that of the corresponding ellipse
+ // thus a 90 degree segment is half of that.
+ double aw = getArcWidth() / 2.0;
+ double ah = getArcHeight() / 2.0;
if (dx > aw || dy > ah)
return true;
@@ -112,8 +116,8 @@ public abstract class RoundRectangle2D extends RectangularShape
{
// We have to check all four points here (for ordinary rectangles
// we can just check opposing corners).
- return (contains(x, y) && contains(x + w, h)
- && contains(x, y + h) && contains(x + w, y + h));
+ return (contains(x, y) && contains(x, y + h) && contains(x + w, y + h)
+ && contains(x + w, y));
}
/** Return a new path iterator which iterates over this rectangle.
@@ -128,154 +132,161 @@ public abstract class RoundRectangle2D extends RectangularShape
final double arcwidth = getArcWidth();
final double archeight = getArcHeight();
return new PathIterator()
- {
- /** We iterate clockwise around the rectangle, starting in the
- * upper left. This variable tracks our current point, which
- * can be on either side of a given corner. */
- private int current = 0;
-
- /** Child path iterator, used for corners. */
- private PathIterator corner;
-
- /** This is used when rendering the corners. We re-use the arc
- * for each corner. */
- private Arc2D arc = new Arc2D.Double();
-
- /** Temporary array used by getPoint. */
- private double[] temp = new double[2];
-
- public int getWindingRule()
{
- return WIND_NON_ZERO;
- }
-
- public boolean isDone()
- {
- return current > 9;
- }
-
- private void getPoint(int val)
- {
- switch (val)
- {
- case 0:
- case 8:
- temp[0] = minx;
- temp[1] = miny + archeight;
- break;
- case 1:
- temp[0] = minx + arcwidth;
- temp[1] = miny;
- break;
- case 2:
- temp[0] = maxx - arcwidth;
- temp[1] = maxy;
- break;
- case 3:
- temp[0] = maxx;
- temp[1] = miny + archeight;
- break;
- case 4:
- temp[0] = maxx;
- temp[1] = maxy - archeight;
- break;
- case 5:
- temp[0] = maxx - arcwidth;
- temp[1] = maxy;
- break;
- case 6:
- temp[0] = minx + arcwidth;
- temp[1] = maxy;
- break;
- case 7:
- temp[0] = minx;
- temp[1] = maxy - archeight;
- break;
- }
- }
-
- public void next()
- {
- if (current >= 8)
- ++current;
- else if (corner != null)
- {
- // We're iterating through the corner. Work on the child
- // iterator; if it finishes, reset and move to the next
- // point along the rectangle.
- corner.next();
- if (corner.isDone())
- {
- corner = null;
- ++current;
- }
- }
- else
- {
- // Make an arc between this point on the rectangle and
- // the next one, and then iterate over this arc.
- getPoint(current);
- double x1 = temp[0];
- double y1 = temp[1];
- getPoint(current + 1);
- arc.setFrameFromDiagonal(x1, y1, temp[0], temp[1]);
- arc.setAngles(x1, y1, temp[0], temp[1]);
- corner = arc.getPathIterator(at);
- }
- }
-
- public int currentSegment(float[] coords)
- {
- if (corner != null)
- {
- int r = corner.currentSegment(coords);
- if (r == SEG_MOVETO)
- r = SEG_LINETO;
- return r;
- }
-
- if (current < 9)
- {
- getPoint(current);
- coords[0] = (float) temp[0];
- coords[1] = (float) temp[1];
- }
- else if (current == 9)
- return SEG_CLOSE;
- else
- throw new NoSuchElementException("rect iterator out of bounds");
-
- if (at != null)
- at.transform(coords, 0, coords, 0, 1);
- return current == 0 ? SEG_MOVETO : SEG_LINETO;
- }
-
- public int currentSegment(double[] coords)
- {
- if (corner != null)
- {
- int r = corner.currentSegment(coords);
- if (r == SEG_MOVETO)
- r = SEG_LINETO;
- return r;
- }
-
- if (current < 9)
- {
- getPoint(current);
- coords[0] = temp[0];
- coords[1] = temp[1];
- }
- else if (current == 9)
- return SEG_CLOSE;
- else
- throw new NoSuchElementException("rect iterator out of bounds");
-
- if (at != null)
- at.transform(coords, 0, coords, 0, 1);
- return current == 0 ? SEG_MOVETO : SEG_LINETO;
- }
- };
+ /** We iterate counterclockwise around the rectangle, starting in the
+ * upper right. This variable tracks our current point, which
+ * can be on either side of a given corner. */
+ private int current = 0;
+
+ /** Child path iterator, used for corners. */
+ private PathIterator corner;
+
+ /** This is used when rendering the corners. We re-use the arc
+ * for each corner. */
+ private Arc2D arc = new Arc2D.Double();
+
+ /** Temporary array used by getPoint. */
+ private double[] temp = new double[2];
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current > 9;
+ }
+
+ private void getPoint(int val)
+ {
+ switch (val)
+ {
+ case 0:
+ case 8:
+ temp[0] = maxx;
+ temp[1] = miny + archeight;
+ break;
+ case 7:
+ temp[0] = maxx;
+ temp[1] = maxy - archeight;
+ break;
+ case 6:
+ temp[0] = maxx - arcwidth;
+ temp[1] = maxy;
+ break;
+ case 5:
+ temp[0] = minx + arcwidth;
+ temp[1] = maxy;
+ break;
+ case 4:
+ temp[0] = minx;
+ temp[1] = maxy - archeight;
+ break;
+ case 3:
+ temp[0] = minx;
+ temp[1] = miny + archeight;
+ break;
+ case 2:
+ temp[0] = minx + arcwidth;
+ temp[1] = miny;
+ break;
+ case 1:
+ temp[0] = maxx - arcwidth;
+ temp[1] = miny;
+ break;
+ }
+ }
+
+ public void next()
+ {
+ if (current >= 8)
+ ++current;
+ else if (corner != null)
+ {
+ // We're iterating through the corner. Work on the child
+ // iterator; if it finishes, reset and move to the next
+ // point along the rectangle.
+ corner.next();
+ if (corner.isDone())
+ {
+ corner = null;
+ ++current;
+ }
+ }
+ else
+ {
+ // Make an arc between this point on the rectangle and
+ // the next one, and then iterate over this arc.
+ getPoint(current);
+ double x1 = temp[0];
+ double y1 = temp[1];
+ getPoint(current + 1);
+ Rectangle2D.Double r = new Rectangle2D.Double(Math.min(x1,
+ temp[0]),
+ Math.min(y1,
+ temp[1]),
+ Math.abs(x1
+ - temp[0]),
+ Math.abs(y1
+ - temp[1]));
+ arc.setArc(r, (current >> 1) * 90.0, 90.0, Arc2D.OPEN);
+ corner = arc.getPathIterator(at);
+ }
+ }
+
+ public int currentSegment(float[] coords)
+ {
+ if (corner != null)
+ {
+ int r = corner.currentSegment(coords);
+ if (r == SEG_MOVETO)
+ r = SEG_LINETO;
+ return r;
+ }
+
+ if (current < 9)
+ {
+ getPoint(current);
+ coords[0] = (float) temp[0];
+ coords[1] = (float) temp[1];
+ }
+ else if (current == 9)
+ return SEG_CLOSE;
+ else
+ throw new NoSuchElementException("rect iterator out of bounds");
+
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return current == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+
+ public int currentSegment(double[] coords)
+ {
+ if (corner != null)
+ {
+ int r = corner.currentSegment(coords);
+ if (r == SEG_MOVETO)
+ r = SEG_LINETO;
+ return r;
+ }
+
+ if (current < 9)
+ {
+ getPoint(current);
+ coords[0] = temp[0];
+ coords[1] = temp[1];
+ }
+ else if (current == 9)
+ return SEG_CLOSE;
+ else
+ throw new NoSuchElementException("rect iterator out of bounds");
+
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return current == 0 ? SEG_MOVETO : SEG_LINETO;
+ }
+ };
}
/** Return true if the given rectangle intersects this shape.
@@ -286,14 +297,9 @@ public abstract class RoundRectangle2D extends RectangularShape
*/
public boolean intersects(double x, double y, double w, double h)
{
- // Here we can use the same code we use for an ordinary rectangle.
- double mx = getX();
- double mw = getWidth();
- if (x < mx || x >= mx + mw || x + w < mx || x + w >= mx + mw)
- return false;
- double my = getY();
- double mh = getHeight();
- return y >= my && y < my + mh && y + h >= my && y + h < my + mh;
+ // Check if any corner is within the rectangle
+ return (contains(x, y) || contains(x, y + h) || contains(x + w, y + h)
+ || contains(x + w, y));
}
/** Set the boundary of this round rectangle.
@@ -315,7 +321,7 @@ public abstract class RoundRectangle2D extends RectangularShape
public void setRoundRect(RoundRectangle2D rr)
{
setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
- rr.getArcWidth(), rr.getArcHeight());
+ rr.getArcWidth(), rr.getArcHeight());
}
/** A subclass of RoundRectangle which keeps its parameters as
@@ -353,8 +359,8 @@ public abstract class RoundRectangle2D extends RectangularShape
* @param arcWidth The arc width
* @param arcHeight The arc height
*/
- public Double(double x, double y, double w, double h,
- double arcWidth, double arcHeight)
+ public Double(double x, double y, double w, double h, double arcWidth,
+ double arcHeight)
{
this.x = x;
this.y = y;
@@ -405,7 +411,7 @@ public abstract class RoundRectangle2D extends RectangularShape
}
public void setRoundRect(double x, double y, double w, double h,
- double arcWidth, double arcHeight)
+ double arcWidth, double arcHeight)
{
this.x = x;
this.y = y;
@@ -451,8 +457,8 @@ public abstract class RoundRectangle2D extends RectangularShape
* @param arcWidth The arc width
* @param arcHeight The arc height
*/
- public Float(float x, float y, float w, float h,
- float arcWidth, float arcHeight)
+ public Float(float x, float y, float w, float h, float arcWidth,
+ float arcHeight)
{
this.x = x;
this.y = y;
@@ -503,7 +509,7 @@ public abstract class RoundRectangle2D extends RectangularShape
}
public void setRoundRect(float x, float y, float w, float h,
- float arcWidth, float arcHeight)
+ float arcWidth, float arcHeight)
{
this.x = x;
this.y = y;
@@ -514,7 +520,7 @@ public abstract class RoundRectangle2D extends RectangularShape
}
public void setRoundRect(double x, double y, double w, double h,
- double arcWidth, double arcHeight)
+ double arcWidth, double arcHeight)
{
this.x = (float) x;
this.y = (float) y;