Browse Source

Back svg icons by cached renderer image.

pull/170/head
weisj 5 years ago
parent
commit
f2f70f412e
  1. 23
      core/src/main/java/com/github/weisj/darklaf/graphics/ImageUtil.java
  2. 4
      core/src/main/java/com/github/weisj/darklaf/ui/list/DarkListCellRendererDelegate.java
  3. 47
      property-loader/src/main/java/com/github/weisj/darklaf/icons/DarkSVGIcon.java
  4. 36
      property-loader/src/main/java/com/github/weisj/darklaf/icons/ImageSource.java
  5. 13
      property-loader/src/main/java/com/github/weisj/darklaf/icons/ThemedSVGIcon.java
  6. 21
      utils/src/main/java/com/github/weisj/darklaf/util/Scale.java

23
core/src/main/java/com/github/weisj/darklaf/graphics/ImageUtil.java

@ -29,6 +29,7 @@ import java.awt.image.BufferedImage;
import javax.swing.*;
import com.github.weisj.darklaf.icons.ImageSource;
import com.github.weisj.darklaf.util.Scale;
/**
@ -45,8 +46,8 @@ public final class ImageUtil {
int w = icon.getIconWidth();
int h = icon.getIconHeight();
GraphicsConfiguration gc = c.getGraphicsConfiguration();
double sx = gc != null ? Scale.getScaleX(gc) : Scale.SCALE_X;
double sy = gc != null ? Scale.getScaleY(gc) : Scale.SCALE_Y;
double sx = Scale.getScaleX(gc);
double sy = Scale.getScaleY(gc);
double scaleX = sx * (((double) FRAME_ICON_SIZE) / w);
double scaleY = sy * (((double) FRAME_ICON_SIZE) / h);
return createScaledImage(icon, scaleX, scaleY);
@ -56,13 +57,17 @@ public final class ImageUtil {
if (icon == null) return null;
int w = (int) (scalex * icon.getIconWidth());
int h = (int) (scaley * icon.getIconHeight());
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
if (icon instanceof ImageSource) {
return ((ImageSource) icon).createImage(w, h);
} else {
BufferedImage image = createCompatibleTranslucentImage(w, h);
Graphics2D g = (Graphics2D) image.getGraphics();
g.scale(scalex, scaley);
icon.paintIcon(null, g, 0, 0);
g.dispose();
return image;
}
}
public static Image createDragImage(final Component c, final int lw, final Color borderColor) {
return createDragImage(c, new Rectangle(0, 0, c.getWidth(), c.getHeight()), lw, borderColor);
@ -130,10 +135,9 @@ public final class ImageUtil {
BufferedImage image;
boolean scale = scalex != 1.0 || scaley != 1.0;
if (scale) {
image = new BufferedImage((int) (scalex * bounds.width), (int) (scaley * bounds.height),
BufferedImage.TYPE_INT_RGB);
image = createCompatibleImage((int) (scalex * bounds.width), (int) (scaley * bounds.height));
} else {
image = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_RGB);
image = createCompatibleImage(bounds.width, bounds.height);
}
final Graphics2D g2d = (Graphics2D) image.getGraphics();
if (scale) {
@ -150,6 +154,13 @@ public final class ImageUtil {
return image;
}
public static BufferedImage createCompatibleImage(final int width,
final int height) {
return isHeadless() ? new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB)
: getGraphicsConfiguration().createCompatibleImage(width, height,
Transparency.OPAQUE);
}
public static BufferedImage createCompatibleTranslucentImage(final int width,
final int height) {
return isHeadless() ? new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)

4
core/src/main/java/com/github/weisj/darklaf/ui/list/DarkListCellRendererDelegate.java

@ -28,8 +28,6 @@ import java.awt.*;
import javax.swing.*;
import org.jdesktop.swingx.renderer.DefaultListRenderer;
import com.github.weisj.darklaf.delegate.ListCellRendererDelegate;
import com.github.weisj.darklaf.ui.cell.CellUtil;
import com.github.weisj.darklaf.util.PropertyUtil;
@ -43,7 +41,7 @@ public class DarkListCellRendererDelegate extends ListCellRendererDelegate<Objec
@Override
public void setDelegate(final ListCellRenderer<Object> delegate) {
if (delegate == null) {
super.setDelegate(new DefaultListRenderer());
super.setDelegate(new DefaultListCellRenderer());
} else {
super.setDelegate(delegate);
}

47
property-loader/src/main/java/com/github/weisj/darklaf/icons/DarkSVGIcon.java

@ -30,9 +30,8 @@ import java.net.URI;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import javax.swing.*;
import com.github.weisj.darklaf.util.LogUtil;
import com.github.weisj.darklaf.util.Scale;
import com.kitfox.svg.app.beans.SVGIcon;
/**
@ -41,13 +40,16 @@ import com.kitfox.svg.app.beans.SVGIcon;
* @author Jannis Weis
* @since 2019
*/
public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Serializable {
public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Serializable, ImageSource {
private static final Logger LOGGER = LogUtil.getLogger(DarkSVGIcon.class);
private final Dimension size;
private final SVGIcon icon;
private final URI uri;
protected final URI uri;
private final AtomicBoolean loaded;
private double scaleX;
private double scaleY;
private Image image;
/**
* Method to fetch the SVG icon from a url.
@ -83,16 +85,38 @@ public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Seri
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
ensureLoaded();
paintIcon(c, g, x, y, 0);
}
private void ensureLoaded() {
protected boolean ensureLoaded() {
if (!loaded.get()) {
LOGGER.fine(() -> "Loading icon '" + uri.toASCIIString() + "'.");
icon.setSvgURI(uri);
loaded.set(true);
return true;
}
return false;
}
protected void updateCache(final boolean update, final Component c) {
GraphicsConfiguration gc = c != null ? c.getGraphicsConfiguration() : null;
double sx = Scale.getScaleX(gc);
double sy = Scale.getScaleY(gc);
if (!update && Scale.equalWithError(scaleX, sx) && Scale.equalWithError(scaleY, sy) && image != null) return;
scaleX = sx;
scaleY = sy;
image = createImage(Scale.scale(scaleX, scaleY, size));
}
@Override
public Image createImage(final Dimension size) {
ensureLoaded();
icon.setPreferredSize(size);
return icon.getImage();
}
protected void ensureImageLoaded(final Component c) {
updateCache(ensureLoaded(), c);
}
protected SVGIcon createSVGIcon() {
@ -102,14 +126,17 @@ public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Seri
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y,
final double rotation) {
ensureLoaded();
ensureImageLoaded(c);
Graphics2D g2 = (Graphics2D) g;
g2.translate(x, y);
double sx = size.width / (double) image.getWidth(null);
double sy = size.height / (double) image.getWidth(null);
g2.scale(sx, sy);
if (rotation != 0) {
g2.rotate(rotation, size.width / 2.0, size.height / 2.0);
}
icon.setPreferredSize(size);
icon.paintIcon(c, g2, 0, 0);
g2.drawImage(image, 0, 0, null);
g2.scale(1 / sx, 1 / sy);
g2.translate(-x, -y);
}
@ -124,7 +151,7 @@ public class DarkSVGIcon implements DerivableIcon<DarkSVGIcon>, RotateIcon, Seri
}
public SVGIcon getSVGIcon() {
ensureLoaded();
if (!loaded.get()) ensureLoaded();
return icon;
}
}

36
property-loader/src/main/java/com/github/weisj/darklaf/icons/ImageSource.java

@ -0,0 +1,36 @@
/*
* MIT License
*
* Copyright (c) 2020 Jannis Weis
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
package com.github.weisj.darklaf.icons;
import java.awt.*;
public interface ImageSource {
Image createImage(final Dimension size);
default Image createImage(final int width, final int height) {
return createImage(new Dimension(width, height));
}
}

13
property-loader/src/main/java/com/github/weisj/darklaf/icons/ThemedSVGIcon.java

@ -39,18 +39,21 @@ public class ThemedSVGIcon extends DarkSVGIcon {
currentTheme = new Object();
}
@Override
public void paintIcon(final Component c, final Graphics g, final int x, final int y, final double rotation) {
ensureTheme();
super.paintIcon(c, g, x, y, rotation);
protected boolean ensureLoaded() {
/*
* Use non-short-circuiting operand here to ensure the colors are actually patched.
*/
return super.ensureLoaded() | ensureTheme();
}
private void ensureTheme() {
protected boolean ensureTheme() {
Object theme = IconLoader.getThemeStatus();
if (currentTheme != theme) {
patchColors();
currentTheme = theme;
return true;
}
return false;
}
protected void patchColors() {

21
utils/src/main/java/com/github/weisj/darklaf/util/Scale.java

@ -31,6 +31,7 @@ public class Scale {
public static final double SCALE;
public static final double SCALE_X;
public static final double SCALE_Y;
private static final double EPSILON = 0.0001;
static {
DisplayMode mode = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDisplayMode();
@ -41,11 +42,13 @@ public class Scale {
}
public static double scaleWidth(final double value, final GraphicsConfiguration gc) {
if (gc == null) return scaleWidth(value);
AffineTransform transform = gc.getDefaultTransform();
return transform.getScaleX() * value;
}
public static double scaleHeight(final double value, final GraphicsConfiguration gc) {
if (gc == null) return scaleHeight(value);
AffineTransform transform = gc.getDefaultTransform();
return transform.getScaleY() * value;
}
@ -83,10 +86,28 @@ public class Scale {
}
public static double getScaleX(final GraphicsConfiguration gc) {
if (gc == null) return SCALE_X;
return gc.getDefaultTransform().getScaleX();
}
public static double getScaleY(final GraphicsConfiguration gc) {
if (gc == null) return SCALE_Y;
return gc.getDefaultTransform().getScaleY();
}
public static Dimension scale(final GraphicsConfiguration gc, final Dimension size) {
return new Dimension((int) scaleWidth(size.width, gc), (int) scaleHeight(size.height, gc));
}
public static double scale(final double scale, final double value) {
return scale * value;
}
public static Dimension scale(final double scaleX, final double scaleY, final Dimension size) {
return new Dimension((int) scale(scaleX, size.width), (int) scale(scaleY, size.height));
}
public static boolean equalWithError(final double a, final double b) {
return Math.abs(a - b) < EPSILON;
}
}

Loading…
Cancel
Save