Icons: cache paths for (complex) immutable icons that may be painted often (e.g. Tree icons or FileView icons)

This commit is contained in:
Karl Tauber
2022-08-11 22:26:48 +02:00
parent fb15cdc546
commit 380dae1017
8 changed files with 102 additions and 55 deletions

View File

@@ -39,6 +39,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
public class FlatCapsLockIcon public class FlatCapsLockIcon
extends FlatAbstractIcon extends FlatAbstractIcon
{ {
private Path2D path;
public FlatCapsLockIcon() { public FlatCapsLockIcon() {
super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) ); super( 16, 16, UIManager.getColor( "PasswordField.capsLockIconColor" ) );
} }
@@ -75,11 +77,13 @@ public class FlatCapsLockIcon
g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE ); g.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
BasicStroke stroke = new BasicStroke( 1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND ); BasicStroke stroke = new BasicStroke( 1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND );
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD ); if( path == null ) {
path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false ); path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
path.append( new Area( stroke.createStrokedShape( new Rectangle2D.Float( 5.5f, 11.5f, 5, 2 ) ) ), false ); path.append( new RoundRectangle2D.Float( 0, 0, 16, 16, 6, 6 ), false );
path.append( new Area( stroke.createStrokedShape( FlatUIUtils.createPath( path.append( new Area( stroke.createStrokedShape( new Rectangle2D.Float( 5.5f, 11.5f, 5, 2 ) ) ), false );
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 ); 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 ); g.fill( path );
} }
} }

View File

@@ -33,6 +33,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
public class FlatFileViewDirectoryIcon public class FlatFileViewDirectoryIcon
extends FlatAbstractIcon extends FlatAbstractIcon
{ {
private Path2D path;
public FlatFileViewDirectoryIcon() { public FlatFileViewDirectoryIcon() {
super( 16, 16, UIManager.getColor( "Objects.Grey" ) ); 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.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
g.draw( createFolderPath() ); if( path == null )
path = createFolderPath();
g.draw( path );
} }
static Path2D createFolderPath() { static Path2D createFolderPath() {

View File

@@ -20,6 +20,7 @@ import java.awt.BasicStroke;
import java.awt.Component; import java.awt.Component;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import javax.swing.UIManager; import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.ui.FlatUIUtils;
@@ -33,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
public class FlatFileViewFileIcon public class FlatFileViewFileIcon
extends FlatAbstractIcon extends FlatAbstractIcon
{ {
private Path2D path;
public FlatFileViewFileIcon() { public FlatFileViewFileIcon() {
super( 16, 16, UIManager.getColor( "Objects.Grey" ) ); 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.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) ); g.setStroke( new BasicStroke( 1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND ) );
double arc = 1.5; if( path == null ) {
g.draw( FlatUIUtils.createPath( double arc = 1.5;
// top-left path = FlatUIUtils.createPath( false,
2.5,1.5+arc, FlatUIUtils.QUAD_TO, 2.5,1.5, 2.5+arc,1.5, // top-left
// top-right 2.5,1.5+arc, FlatUIUtils.QUAD_TO, 2.5,1.5, 2.5+arc,1.5,
8.8,1.5, 13.5,6.2, // top-right
// bottom-right 8.8,1.5, 13.5,6.2,
13.5,14.5-arc, FlatUIUtils.QUAD_TO, 13.5,14.5, 13.5-arc,14.5, // bottom-right
// bottom-left 13.5,14.5-arc, FlatUIUtils.QUAD_TO, 13.5,14.5, 13.5-arc,14.5,
2.5+arc,14.5, FlatUIUtils.QUAD_TO, 2.5,14.5, 2.5,14.5-arc ) ); // 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, FlatUIUtils.MOVE_TO, 8.5,2,
8.5,6.5-arc, FlatUIUtils.QUAD_TO, 8.5,6.5, 8.5+arc,6.5, 8.5,6.5-arc, FlatUIUtils.QUAD_TO, 8.5,6.5, 8.5+arc,6.5,
13,6.5 ) ); 13,6.5 );
}
g.draw( path );
} }
} }

View File

@@ -46,6 +46,7 @@ public class FlatSearchIcon
@Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" ); @Styleable protected Color searchIconPressedColor = UIManager.getColor( "SearchField.searchIconPressedColor" );
private final boolean ignoreButtonState; private final boolean ignoreButtonState;
private Area area;
public FlatSearchIcon() { public FlatSearchIcon() {
this( false ); this( false );
@@ -89,9 +90,11 @@ public class FlatSearchIcon
null, searchIconHoverColor, searchIconPressedColor ) ); null, searchIconHoverColor, searchIconPressedColor ) );
// paint magnifier // paint magnifier
Area area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) ); if( area == null ) {
area.subtract( new Area( new Ellipse2D.Float( 3, 3, 8, 8 ) ) ); area = new Area( new Ellipse2D.Float( 2, 2, 10, 10 ) );
area.add( new Area( FlatUIUtils.createPath( 10.813,9.75, 14,12.938, 12.938,14, 9.75,10.813 ) ) ); 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 ); g.fill( area );
} }
} }

View File

@@ -19,6 +19,7 @@ package com.formdev.flatlaf.icons;
import java.awt.Component; import java.awt.Component;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import javax.swing.UIManager; import javax.swing.UIManager;
/** /**
@@ -31,6 +32,8 @@ import javax.swing.UIManager;
public class FlatTreeClosedIcon public class FlatTreeClosedIcon
extends FlatAbstractIcon extends FlatAbstractIcon
{ {
private Path2D path;
public FlatTreeClosedIcon() { public FlatTreeClosedIcon() {
super( 16, 16, UIManager.getColor( "Tree.icon.closedColor" ) ); 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.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
g.draw( FlatFileViewDirectoryIcon.createFolderPath() ); if( path == null )
path = FlatFileViewDirectoryIcon.createFolderPath();
g.draw( path );
} }
} }

View File

@@ -41,6 +41,7 @@ public class FlatTreeCollapsedIcon
extends FlatAbstractIcon extends FlatAbstractIcon
{ {
private final boolean chevron; private final boolean chevron;
private Path2D path;
public FlatTreeCollapsedIcon() { public FlatTreeCollapsedIcon() {
this( UIManager.getColor( "Tree.icon.collapsedColor" ) ); this( UIManager.getColor( "Tree.icon.collapsedColor" ) );
@@ -62,10 +63,14 @@ public class FlatTreeCollapsedIcon
if( chevron ) { if( chevron ) {
// chevron arrow // chevron arrow
g.setStroke( new BasicStroke( 1f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER ) ); 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 { } else {
// triangle arrow // 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 );
} }
} }

View File

@@ -20,6 +20,7 @@ import java.awt.BasicStroke;
import java.awt.Component; import java.awt.Component;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.Path2D;
import javax.swing.UIManager; import javax.swing.UIManager;
import com.formdev.flatlaf.ui.FlatUIUtils; import com.formdev.flatlaf.ui.FlatUIUtils;
@@ -33,6 +34,8 @@ import com.formdev.flatlaf.ui.FlatUIUtils;
public class FlatTreeOpenIcon public class FlatTreeOpenIcon
extends FlatAbstractIcon extends FlatAbstractIcon
{ {
private Path2D path;
public FlatTreeOpenIcon() { public FlatTreeOpenIcon() {
super( 16, 16, UIManager.getColor( "Tree.icon.openColor" ) ); 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.setRenderingHint( RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE );
g.setStroke( new BasicStroke( 1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER ) ); g.setStroke( new BasicStroke( 1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER ) );
double arc = 1.5; if( path == null ) {
double arc2 = 0.5; double arc = 1.5;
g.draw( FlatUIUtils.createPath( false, double arc2 = 0.5;
// bottom-left of opend part path = FlatUIUtils.createPath( false,
2,13.5, // bottom-left of opend part
// top-left of opend part 2,13.5,
FlatUIUtils.ROUNDED, 4.5,7.5, arc, // top-left of opend part
// top-right of opend part FlatUIUtils.ROUNDED, 4.5,7.5, arc,
FlatUIUtils.ROUNDED, 15.5,7.5, arc2, // top-right of opend part
FlatUIUtils.ROUNDED, 15.5,7.5, arc2,
// bottom-right // bottom-right
FlatUIUtils.ROUNDED, 13,13.5, arc, FlatUIUtils.ROUNDED, 13,13.5, arc,
// bottom-left // bottom-left
1.5+arc,13.5, FlatUIUtils.QUAD_TO, 1.5,13.5, 1.5,13.5-arc, 1.5+arc,13.5, FlatUIUtils.QUAD_TO, 1.5,13.5, 1.5,13.5-arc,
// top-left // top-left
1.5,2.5+arc, FlatUIUtils.QUAD_TO, 1.5,2.5, 1.5+arc,2.5, 1.5,2.5+arc, FlatUIUtils.QUAD_TO, 1.5,2.5, 1.5+arc,2.5,
// top-mid-left // top-mid-left
6.5-arc2,2.5, FlatUIUtils.QUAD_TO, 6.5,2.5, 6.5+arc2,2.5+arc2, 6.5-arc2,2.5, FlatUIUtils.QUAD_TO, 6.5,2.5, 6.5+arc2,2.5+arc2,
// top-mid-right // top-mid-right
8.5,4.5, 8.5,4.5,
// top-right // top-right
13.5-arc,4.5, FlatUIUtils.QUAD_TO, 13.5,4.5, 13.5,4.5+arc, 13.5-arc,4.5, FlatUIUtils.QUAD_TO, 13.5,4.5, 13.5,4.5+arc,
13.5,6.5 ) ); 13.5,6.5 );
}
g.draw( path );
} }
} }

View File

@@ -896,9 +896,11 @@ debug*/
} }
debug*/ debug*/
/** @since 3 */ public static final double QUAD_TO = Double.MIN_VALUE; /** @since 3 */ public static final double MOVE_TO = -1_000_000_000_001.;
/** @since 3 */ public static final double CURVE_TO = Double.MIN_NORMAL; /** @since 3 */ public static final double QUAD_TO = -1_000_000_000_002.;
/** @since 3 */ public static final double ROUNDED = Double.MAX_VALUE; /** @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. * 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) ); Path2D path = new Path2D.Float( Path2D.WIND_NON_ZERO, points.length / 2 + (close ? 1 : 0) );
path.moveTo( points[0], points[1] ); path.moveTo( points[0], points[1] );
for( int i = 2; i < points.length; ) { 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 // add quadratic curve
// params: x1, y1, x2, y2 // params: x1, y1, x2, y2
path.quadTo( points[i + 1], points[i + 2], points[i + 3], points[i + 4] ); path.quadTo( points[i + 1], points[i + 2], points[i + 3], points[i + 4] );
i += 5; i += 5;
} else if( points[i] == CURVE_TO ) { } else if( p == CURVE_TO ) {
// add bezier curve // add bezier curve
// params: x1, y1, x2, y2, x3, y3 // 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] ); path.curveTo( points[i + 1], points[i + 2], points[i + 3], points[i + 4], points[i + 5], points[i + 6] );
i += 7; i += 7;
} else if( points[i] == ROUNDED ) { } else if( p == ROUNDED ) {
// add rounded corner // add rounded corner
// params: x, y, arc // params: x, y, arc
double x = points[i + 1]; double x = points[i + 1];
@@ -952,10 +960,15 @@ debug*/
path.quadTo( x, y, lerp( x, x2, t2 ), lerp( y, y2, t2 ) ); path.quadTo( x, y, lerp( x, x2, t2 ), lerp( y, y2, t2 ) );
i += 4; i += 4;
} else if( p == CLOSE_PATH ) {
// close path
// params: -
path.closePath();
i += 1;
} else { } else {
// add line // add line to
// params: x, y // params: x, y
path.lineTo( points[i], points[i + 1] ); path.lineTo( p, points[i + 1] );
i += 2; i += 2;
} }
} }