Index: graph/examples/src/org/netbeans/modules/visual/examples/RunDialog.java =================================================================== RCS file: /cvs/graph/examples/src/org/netbeans/modules/visual/examples/RunDialog.java,v retrieving revision 1.77 diff -u -r1.77 RunDialog.java --- graph/examples/src/org/netbeans/modules/visual/examples/RunDialog.java 19 Jul 2007 07:15:42 -0000 1.77 +++ graph/examples/src/org/netbeans/modules/visual/examples/RunDialog.java 1 Aug 2007 14:28:24 -0000 @@ -77,6 +77,7 @@ "test.keyboard.EnterKeyProcessingTest", "test.keyboard.EnterKeyTest", "test.keyboard.KeyboardTest", + "test.label.LabelGlyphVectorTest", "test.label.LabelOrientationTest", "test.layout.CardLayoutWithLabelTest", "test.layout.FlowLayoutTest", Index: graph/examples/src/test/label/LabelGlyphVectorTest.java =================================================================== RCS file: graph/examples/src/test/label/LabelGlyphVectorTest.java diff -N graph/examples/src/test/label/LabelGlyphVectorTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ graph/examples/src/test/label/LabelGlyphVectorTest.java 1 Aug 2007 14:28:24 -0000 @@ -0,0 +1,61 @@ +/* + * The contents of this file are subject to the terms of the Common Development + * and Distribution License (the License). You may not use this file except in + * compliance with the License. + * + * You can obtain a copy of the License at http://www.netbeans.org/cddl.html + * or http://www.netbeans.org/cddl.txt. + * + * When distributing Covered Code, include this CDDL Header Notice in each file + * and include the License file at http://www.netbeans.org/cddl.txt. + * If applicable, add the following below the CDDL Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + */ + +package test.label; + +import org.netbeans.api.visual.action.ActionFactory; +import org.netbeans.api.visual.widget.LabelWidget; +import org.netbeans.api.visual.widget.LayerWidget; +import org.netbeans.api.visual.widget.Scene; +import test.SceneSupport; + +import java.awt.*; + +/** + * @author David Kaspar + */ +public class LabelGlyphVectorTest { + + public static void main (String[] args) { + Scene scene = new Scene (); + scene.getActions ().addAction (ActionFactory.createZoomAction (1.1, false)); + scene.getActions ().addAction (ActionFactory.createPanAction ()); + + LayerWidget layer = new LayerWidget (scene); + scene.addChild (layer); + + createLabel (layer, 100, 100, "We are glyph-vector labels"); + createLabel (layer, 100, 150, "Zoom the scene in/out using Ctrl+MouseWheel"); + createLabel (layer, 100, 200, "The labels should be rendered correctly all the time (not clipping)"); + + SceneSupport.show (scene); + } + + private static void createLabel (LayerWidget layer, int x, int y, String label) { + LabelWidget widget = new LabelWidget (layer.getScene (), label); + widget.setOpaque (true); + widget.setBackground (Color.GREEN); + widget.setUseGlyphVector (true); + widget.setAlignment (LabelWidget.Alignment.CENTER); + widget.setVerticalAlignment (LabelWidget.VerticalAlignment.CENTER); + widget.setPreferredLocation (new Point (x, y)); + layer.addChild (widget); + } + +} Index: graph/lib/apichanges.xml =================================================================== RCS file: /cvs/graph/lib/apichanges.xml,v retrieving revision 1.33 diff -u -r1.33 apichanges.xml --- graph/lib/apichanges.xml 1 Aug 2007 08:13:34 -0000 1.33 +++ graph/lib/apichanges.xml 1 Aug 2007 14:28:24 -0000 @@ -444,6 +444,22 @@ + + + + Accurate LabelWidget rendering using glyph vector + + + + + + LabelWidget now has useGlyphVector property. If true then the text in a LabelWidget is converted into glyph-vector (a shape) + that is rendered. This allows accurate rendering independently on zoom-factor of a scene. + Note that the glyph-vector rendering is slower than regular rendering. + + + + Index: graph/lib/manifest.mf =================================================================== RCS file: /cvs/graph/lib/manifest.mf,v retrieving revision 1.14 diff -u -r1.14 manifest.mf --- graph/lib/manifest.mf 1 Aug 2007 07:31:49 -0000 1.14 +++ graph/lib/manifest.mf 1 Aug 2007 14:28:24 -0000 @@ -1,4 +1,4 @@ Manifest-Version: 1.0 OpenIDE-Module: org.netbeans.api.visual OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/visual/resources/Bundle.properties -OpenIDE-Module-Specification-Version: 2.6 +OpenIDE-Module-Specification-Version: 2.7 Index: graph/lib/src/org/netbeans/api/visual/widget/LabelWidget.java =================================================================== RCS file: /cvs/graph/lib/src/org/netbeans/api/visual/widget/LabelWidget.java,v retrieving revision 1.14 diff -u -r1.14 LabelWidget.java --- graph/lib/src/org/netbeans/api/visual/widget/LabelWidget.java 3 Apr 2007 15:10:48 -0000 1.14 +++ graph/lib/src/org/netbeans/api/visual/widget/LabelWidget.java 1 Aug 2007 14:28:24 -0000 @@ -21,6 +21,8 @@ import org.netbeans.modules.visual.util.GeomUtil; import java.awt.*; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; @@ -60,6 +62,11 @@ private VerticalAlignment verticalAlignment = VerticalAlignment.BASELINE; private Orientation orientation = Orientation.NORMAL; private boolean paintAsDisabled; + private boolean useGlyphVector = false; + + private GlyphVector cacheGlyphVector; + private String cacheLabel; + private Font cacheFont; /** * Creates a label widget. @@ -174,16 +181,58 @@ } /** + * Returns whether the label widget is using glyph vector for rendering text. + * @return true, if the label widget is using glyph vector + */ + public boolean isUseGlyphVector () { + return useGlyphVector; + } + + /** + * Sets whether the label widget is using glyph vector for rendering text. + *

+ * Note that using glyph vector could slow-down the rendering performance. + * Note that if you are not using glyph vector then the text may be clipped when a scene has zoom factor different from 1.0. + * @param useGlyphVector if true, then a glyph vector is used for rendering text + */ + public void setUseGlyphVector (boolean useGlyphVector) { + if (this.useGlyphVector == useGlyphVector) + return; + this.useGlyphVector = useGlyphVector; + cacheGlyphVector = null; + cacheLabel = null; + cacheFont = null; + revalidate (); + } + + private void assureGlyphVector () { + Font font = getFont (); + FontRenderContext fontRenderContext = getGraphics ().getFontRenderContext (); + if (cacheGlyphVector != null && cacheFont == font && cacheLabel == label) + return; + cacheFont = font; + cacheLabel = label; + cacheGlyphVector = font.createGlyphVector (new FontRenderContext (new AffineTransform (), fontRenderContext.isAntiAliased (), fontRenderContext.usesFractionalMetrics ()), cacheLabel); + } + + /** * Calculates a client area for the label. * @return the client area */ protected Rectangle calculateClientArea () { if (label == null) return super.calculateClientArea (); - Graphics2D gr = getGraphics (); - FontMetrics fontMetrics = gr.getFontMetrics (getFont ()); - Rectangle2D stringBounds = fontMetrics.getStringBounds (label, gr); - Rectangle rectangle = GeomUtil.roundRectangle (stringBounds); + Rectangle rectangle; + if (useGlyphVector) { + assureGlyphVector (); + rectangle = GeomUtil.roundRectangle (cacheGlyphVector.getVisualBounds ()); + rectangle.grow (1, 1); // WORKAROUND - even text antialiasing is included into the boundary + } else { + Graphics2D gr = getGraphics (); + FontMetrics fontMetrics = gr.getFontMetrics (getFont ()); + Rectangle2D stringBounds = fontMetrics.getStringBounds (label, gr); + rectangle = GeomUtil.roundRectangle (stringBounds); + } switch (orientation) { case NORMAL: return rectangle; @@ -201,7 +250,10 @@ if (label == null) return; Graphics2D gr = getGraphics (); - gr.setFont (getFont ()); + if (useGlyphVector) + assureGlyphVector (); + else + gr.setFont (getFont ()); FontMetrics fontMetrics = gr.getFontMetrics (); Rectangle clientArea = getClientArea (); @@ -220,10 +272,16 @@ x = clientArea.x; break; case CENTER: - x = clientArea.x + (clientArea.width - fontMetrics.stringWidth (label)) / 2; + if (useGlyphVector) + x = clientArea.x + (clientArea.width - getCacheGlyphVectorWidth ()) / 2; + else + x = clientArea.x + (clientArea.width - fontMetrics.stringWidth (label)) / 2; break; case RIGHT: - x = clientArea.x + clientArea.width - fontMetrics.stringWidth (label); + if (useGlyphVector) + x = clientArea.x + clientArea.width - getCacheGlyphVectorWidth (); + else + x = clientArea.x + clientArea.width - fontMetrics.stringWidth (label); break; default: return; @@ -271,10 +329,16 @@ y = 0; break; case TOP: + if (useGlyphVector) + y = clientArea.y + getCacheGlyphVectorWidth (); + else y = clientArea.y + fontMetrics.stringWidth (label); break; case CENTER: - y = clientArea.y + (clientArea.height + fontMetrics.stringWidth (label)) / 2; + if (useGlyphVector) + y = clientArea.y + (clientArea.height + getCacheGlyphVectorWidth ()) / 2; + else + y = clientArea.y + (clientArea.height + fontMetrics.stringWidth (label)) / 2; break; case BOTTOM: y = clientArea.y + clientArea.height; @@ -304,15 +368,28 @@ if (paintAsDisabled && background instanceof Color) { Color color = ((Color) background); gr.setColor (color.brighter ()); - gr.drawString (label, 1, 1); + if (useGlyphVector) + gr.fill (cacheGlyphVector.getOutline (1, 1)); + else + gr.drawString (label, 1, 1); gr.setColor (color.darker ()); - gr.drawString (label, 0, 0); + if (useGlyphVector) + gr.fill (cacheGlyphVector.getOutline ()); + else + gr.drawString (label, 0, 0); } else { gr.setColor (getForeground ()); - gr.drawString (label, 0, 0); + if (useGlyphVector) + gr.fill (cacheGlyphVector.getOutline ()); + else + gr.drawString (label, 0, 0); } gr.setTransform(previousTransform); + } + + private int getCacheGlyphVectorWidth () { + return GeomUtil.roundRectangle (cacheGlyphVector.getVisualBounds ()).width; } } Index: graph/www/documentation.html =================================================================== RCS file: /cvs/graph/www/documentation.html,v retrieving revision 1.98 diff -u -r1.98 documentation.html --- graph/www/documentation.html 1 Aug 2007 14:23:16 -0000 1.98 +++ graph/www/documentation.html 1 Aug 2007 14:28:24 -0000 @@ -148,6 +148,7 @@

  • test.keyboard.EnterKeyProcessingTest - test of processing enter key
  • test.keyboard.EnterKeyTest - test of cooperation of Swing with an enter key processing within in-place editor
  • test.keyboard.KeyboardTest - test of CycleObjectSceneFocusAction +
  • test.label.LabelGlyphVectorTest - test of LabelWidget rendering using glyph vector
  • test.label.LabelOrientationTest - test of orientation vs. alignment of text in LabelWidget
  • test.layout.CardLayoutWithLabelTest - how to create non-jumping widget with card layout and label widget as child
  • test.layout.FlowLayoutTest - test of bugfix #105400 - FlowLayout does not work correctly with negative location of child widgets