From 380dae1017fab117d21aa8a4071e8f52db81b300 Mon Sep 17 00:00:00 2001 From: Karl Tauber Date: Thu, 11 Aug 2022 22:26:48 +0200 Subject: [PATCH] Icons: cache paths for (complex) immutable icons that may be painted often (e.g. Tree icons or FileView icons) --- .../flatlaf/icons/FlatCapsLockIcon.java | 14 ++++-- .../icons/FlatFileViewDirectoryIcon.java | 6 ++- .../flatlaf/icons/FlatFileViewFileIcon.java | 33 +++++++----- .../formdev/flatlaf/icons/FlatSearchIcon.java | 9 ++-- .../flatlaf/icons/FlatTreeClosedIcon.java | 7 ++- .../flatlaf/icons/FlatTreeCollapsedIcon.java | 9 +++- .../flatlaf/icons/FlatTreeOpenIcon.java | 50 +++++++++++-------- .../com/formdev/flatlaf/ui/FlatUIUtils.java | 29 ++++++++--- 8 files changed, 102 insertions(+), 55 deletions(-) diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java index 64a26a82..0fac6414 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatCapsLockIcon.java @@ -39,6 +39,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils; public class FlatCapsLockIcon extends FlatAbstractIcon { + private Path2D path; + public FlatCapsLockIcon() { super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) ); } @@ -75,11 +77,13 @@ public class FlatCapsLockIcon g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE ); BasicStroke stroke = new BasicStroke( 1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND ); - Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD ); - path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false ); - path.append( new Area( stroke.createStrokedShape( new Rectangle2D.Float( 5.5f, 11.5f, 5, 2 ) ) ), false ); - path.append( new Area( stroke.createStrokedShape( FlatUIUtils.createPath( - 2.5,7.5, 8,2, 13.5,7.5, 10.5,7.5, 10.5,9.5, 5.5,9.5, 5.5,7.5, 2.5,7.5 ) ) ), false ); + if( path == null ) { + path = new Path2D.Float( Path2D.WIND_EVEN_ODD ); + path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false ); + path.append( new Area( stroke.createStrokedShape( new Rectangle2D.Float( 5.5f, 11.5f, 5, 2 ) ) ), false ); + path.append( new Area( stroke.createStrokedShape( FlatUIUtils.createPath( + 2.5,7.5, 8,2, 13.5,7.5, 10.5,7.5, 10.5,9.5, 5.5,9.5, 5.5,7.5, 2.5,7.5 ) ) ), false ); + } g.fill( path ); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatFileViewDirectoryIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatFileViewDirectoryIcon.java index 6ffc401f..7cbc24ef 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatFileViewDirectoryIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatFileViewDirectoryIcon.java @@ -33,6 +33,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils; public class FlatFileViewDirectoryIcon extends FlatAbstractIcon { + private Path2D path; + public FlatFileViewDirectoryIcon() { super( 16, 16, UIManager.getColor( "Objects.Grey" ) ); } @@ -47,7 +49,9 @@ public class FlatFileViewDirectoryIcon g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE ); - g.draw( createFolderPath() ); + if( path == null ) + path = createFolderPath(); + g.draw( path ); } static Path2D createFolderPath() { diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatFileViewFileIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatFileViewFileIcon.java index f2ef9eb4..9942238c 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatFileViewFileIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatFileViewFileIcon.java @@ -20,6 +20,7 @@ import java.awt.BasicStroke; import java.awt.Component; import java.awt.Graphics2D; import java.awt.RenderingHints; +import java.awt.geom.Path2D; import javax.swing.UIManager; import com.formdev.flatlaf.ui.FlatUIUtils; @@ -33,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils; public class FlatFileViewFileIcon extends FlatAbstractIcon { + private Path2D path; + public FlatFileViewFileIcon() { super( 16, 16, UIManager.getColor( "Objects.Grey" ) ); } @@ -51,19 +54,23 @@ public class FlatFileViewFileIcon g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE ); g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) ); - double arc = 1.5; - g.draw( FlatUIUtils.createPath( - // top-left - 2.5,1.5+arc, FlatUIUtils.QUAD_TO, 2.5,1.5, 2.5+arc,1.5, - // top-right - 8.8,1.5, 13.5,6.2, - // bottom-right - 13.5,14.5-arc, FlatUIUtils.QUAD_TO, 13.5,14.5, 13.5-arc,14.5, - // bottom-left - 2.5+arc,14.5, FlatUIUtils.QUAD_TO, 2.5,14.5, 2.5,14.5-arc ) ); + if( path == null ) { + double arc = 1.5; + path = FlatUIUtils.createPath( false, + // top-left + 2.5,1.5+arc, FlatUIUtils.QUAD_TO, 2.5,1.5, 2.5+arc,1.5, + // top-right + 8.8,1.5, 13.5,6.2, + // bottom-right + 13.5,14.5-arc, FlatUIUtils.QUAD_TO, 13.5,14.5, 13.5-arc,14.5, + // bottom-left + 2.5+arc,14.5, FlatUIUtils.QUAD_TO, 2.5,14.5, 2.5,14.5-arc, + FlatUIUtils.CLOSE_PATH, - g.draw( FlatUIUtils.createPath( false, 8.5,2, - 8.5,6.5-arc, FlatUIUtils.QUAD_TO, 8.5,6.5, 8.5+arc,6.5, - 13,6.5 ) ); + FlatUIUtils.MOVE_TO, 8.5,2, + 8.5,6.5-arc, FlatUIUtils.QUAD_TO, 8.5,6.5, 8.5+arc,6.5, + 13,6.5 ); + } + g.draw( path ); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java index 007e9718..bcaf2bc1 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatSearchIcon.java @@ -46,6 +46,7 @@ public class FlatSearchIcon @Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" ); private final boolean ignoreButtonState; + private Area area; public FlatSearchIcon() { this( false ); @@ -89,9 +90,11 @@ public class FlatSearchIcon null, searchIconHoverColor, searchIconPressedColor ) ); // paint magnifier - Area area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) ); - area.subtract( new Area( new Ellipse2D.Float( 3, 3, 8, 8 ) ) ); - area.add( new Area( FlatUIUtils.createPath( 10.813,9.75, 14,12.938, 12.938,14, 9.75,10.813 ) ) ); + if( area == null ) { + area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) ); + area.subtract( new Area( new Ellipse2D.Float( 3, 3, 8, 8 ) ) ); + area.add( new Area( FlatUIUtils.createPath( 10.813,9.75, 14,12.938, 12.938,14, 9.75,10.813 ) ) ); + } g.fill( area ); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeClosedIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeClosedIcon.java index ca19812e..72ae473b 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeClosedIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeClosedIcon.java @@ -19,6 +19,7 @@ package com.formdev.flatlaf.icons; import java.awt.Component; import java.awt.Graphics2D; import java.awt.RenderingHints; +import java.awt.geom.Path2D; import javax.swing.UIManager; /** @@ -31,6 +32,8 @@ import javax.swing.UIManager; public class FlatTreeClosedIcon extends FlatAbstractIcon { + private Path2D path; + public FlatTreeClosedIcon() { super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) ); } @@ -47,6 +50,8 @@ public class FlatTreeClosedIcon g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE ); - g.draw( FlatFileViewDirectoryIcon.createFolderPath() ); + if( path == null ) + path = FlatFileViewDirectoryIcon.createFolderPath(); + g.draw( path ); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeCollapsedIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeCollapsedIcon.java index e7139ec2..6c3d4727 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeCollapsedIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeCollapsedIcon.java @@ -41,6 +41,7 @@ public class FlatTreeCollapsedIcon extends FlatAbstractIcon { private final boolean chevron; + private Path2D path; public FlatTreeCollapsedIcon() { this( UIManager.getColor( "Tree.icon.collapsedColor" ) ); @@ -62,10 +63,14 @@ public class FlatTreeCollapsedIcon if( chevron ) { // chevron arrow g.setStroke( new BasicStroke( 1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER ) ); - g.draw( FlatUIUtils.createPath( false, 3.5,1.5, 7.5,5.5, 3.5,9.5 ) ); + if( path == null ) + path = FlatUIUtils.createPath( false, 3.5,1.5, 7.5,5.5, 3.5,9.5 ); + g.draw( path ); } else { // triangle arrow - g.fill( FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 ) ); + if( path == null ) + path = FlatUIUtils.createPath( 2,1, 2,10, 10,5.5 ); + g.fill( path ); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeOpenIcon.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeOpenIcon.java index 456412e6..bce89b95 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeOpenIcon.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/icons/FlatTreeOpenIcon.java @@ -20,6 +20,7 @@ import java.awt.BasicStroke; import java.awt.Component; import java.awt.Graphics2D; import java.awt.RenderingHints; +import java.awt.geom.Path2D; import javax.swing.UIManager; import com.formdev.flatlaf.ui.FlatUIUtils; @@ -33,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils; public class FlatTreeOpenIcon extends FlatAbstractIcon { + private Path2D path; + public FlatTreeOpenIcon() { super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) ); } @@ -50,28 +53,31 @@ public class FlatTreeOpenIcon g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE ); g.setStroke( new BasicStroke( 1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER ) ); - double arc = 1.5; - double arc2 = 0.5; - g.draw( FlatUIUtils.createPath( false, - // bottom-left of opend part - 2,13.5, - // top-left of opend part - FlatUIUtils.ROUNDED, 4.5,7.5, arc, - // top-right of opend part - FlatUIUtils.ROUNDED, 15.5,7.5, arc2, + if( path == null ) { + double arc = 1.5; + double arc2 = 0.5; + path = FlatUIUtils.createPath( false, + // bottom-left of opend part + 2,13.5, + // top-left of opend part + FlatUIUtils.ROUNDED, 4.5,7.5, arc, + // top-right of opend part + FlatUIUtils.ROUNDED, 15.5,7.5, arc2, - // bottom-right - FlatUIUtils.ROUNDED, 13,13.5, arc, - // bottom-left - 1.5+arc,13.5, FlatUIUtils.QUAD_TO, 1.5,13.5, 1.5,13.5-arc, - // top-left - 1.5,2.5+arc, FlatUIUtils.QUAD_TO, 1.5,2.5, 1.5+arc,2.5, - // top-mid-left - 6.5-arc2,2.5, FlatUIUtils.QUAD_TO, 6.5,2.5, 6.5+arc2,2.5+arc2, - // top-mid-right - 8.5,4.5, - // top-right - 13.5-arc,4.5, FlatUIUtils.QUAD_TO, 13.5,4.5, 13.5,4.5+arc, - 13.5,6.5 ) ); + // bottom-right + FlatUIUtils.ROUNDED, 13,13.5, arc, + // bottom-left + 1.5+arc,13.5, FlatUIUtils.QUAD_TO, 1.5,13.5, 1.5,13.5-arc, + // top-left + 1.5,2.5+arc, FlatUIUtils.QUAD_TO, 1.5,2.5, 1.5+arc,2.5, + // top-mid-left + 6.5-arc2,2.5, FlatUIUtils.QUAD_TO, 6.5,2.5, 6.5+arc2,2.5+arc2, + // top-mid-right + 8.5,4.5, + // top-right + 13.5-arc,4.5, FlatUIUtils.QUAD_TO, 13.5,4.5, 13.5,4.5+arc, + 13.5,6.5 ); + } + g.draw( path ); } } diff --git a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java index 0a27a144..2f67d61b 100644 --- a/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java +++ b/flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatUIUtils.java @@ -896,9 +896,11 @@ debug*/ } debug*/ - /** @since 3 */ public static final double QUAD_TO = Double.MIN_VALUE; - /** @since 3 */ public static final double CURVE_TO = Double.MIN_NORMAL; - /** @since 3 */ public static final double ROUNDED = Double.MAX_VALUE; + /** @since 3 */ public static final double MOVE_TO = -1_000_000_000_001.; + /** @since 3 */ public static final double QUAD_TO = -1_000_000_000_002.; + /** @since 3 */ public static final double CURVE_TO = -1_000_000_000_003.; + /** @since 3 */ public static final double ROUNDED = -1_000_000_000_004.; + /** @since 3 */ public static final double CLOSE_PATH = -1_000_000_000_005.; /** * Creates a closed path for the given points. @@ -914,17 +916,23 @@ debug*/ Path2D path = new Path2D.Float( Path2D.WIND_NON_ZERO, points.length / 2 + (close ? 1 : 0) ); path.moveTo( points[0], points[1] ); for( int i = 2; i < points.length; ) { - if( points[i] == QUAD_TO ) { + double p = points[i]; + if( p == MOVE_TO ) { + // move pointer to + // params: x, y + path.moveTo( points[i + 1], points[i + 2] ); + i += 3; + } else if( p == QUAD_TO ) { // add quadratic curve // params: x1, y1, x2, y2 path.quadTo( points[i + 1], points[i + 2], points[i + 3], points[i + 4] ); i += 5; - } else if( points[i] == CURVE_TO ) { + } else if( p == CURVE_TO ) { // add bezier curve // params: x1, y1, x2, y2, x3, y3 path.curveTo( points[i + 1], points[i + 2], points[i + 3], points[i + 4], points[i + 5], points[i + 6] ); i += 7; - } else if( points[i] == ROUNDED ) { + } else if( p == ROUNDED ) { // add rounded corner // params: x, y, arc double x = points[i + 1]; @@ -952,10 +960,15 @@ debug*/ path.quadTo( x, y, lerp( x, x2, t2 ), lerp( y, y2, t2 ) ); i += 4; + } else if( p == CLOSE_PATH ) { + // close path + // params: - + path.closePath(); + i += 1; } else { - // add line + // add line to // params: x, y - path.lineTo( points[i], points[i + 1] ); + path.lineTo( p, points[i + 1] ); i += 2; } }