Skip to content

Commit

Permalink
Add alpha channels to tonal painters
Browse files Browse the repository at this point in the history
And convert tonal Gemini border painter to use the recently added complementary container outline + custom alpha channels

For #400
  • Loading branch information
kirill-grouchnikov committed Feb 2, 2025
1 parent 1027357 commit 0656ba9
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ public abstract class FractionBasedTonalPainter implements RadianceTrait {
*/
protected float[] fractions;

/**
* The alphas of this painter. Each entry in this array corresponds to the matching entry in
* {@link #fractions} and {@link #colorQueries}. Each entry is applied to the matching
* @link #colorQueries} entry to determine the final color at the {@link #fractions} entry.
*/
protected int[] alphas;

/**
* The color queries of this painter. Each entry in this array corresponds
* to the matching index in the {@link #fractions}, specifying which color
Expand All @@ -67,26 +74,53 @@ public abstract class FractionBasedTonalPainter implements RadianceTrait {
*/
protected ContainerColorTokensSingleColorQuery[] colorQueries;

private static int[] makeDefaultAlphas(int count) {
int[] result = new int[count];
for (int i = 0; i < count; i++) {
result[i] = 255;
}
return result;
}

/**
* Creates a new fraction-based border painter.
* Creates a new fraction-based painter.
*
* @param displayName
* The display name of this painter.
* The display name of this painter.
* @param fractions
* The fractions of this painter. Must be strictly increasing,
* starting from 0.0 and ending at 1.0.
* The fractions of this painter. Must be strictly increasing,
* starting from 0.0 and ending at 1.0.
* @param colorQueries
* The color queries of this painter. Must have the same size as
* the fractions array, and all entries must be non-
* <code>null</code>.
* The color queries of this painter. Must have the same size as
* the fractions array, and all entries must be non-<code>null</code>.
*/
public FractionBasedTonalPainter(String displayName, float[] fractions,
ContainerColorTokensSingleColorQuery[] colorQueries) {
protected FractionBasedTonalPainter(String displayName, float[] fractions,
ContainerColorTokensSingleColorQuery[] colorQueries) {
this(displayName, fractions, makeDefaultAlphas(fractions.length), colorQueries);
}

/**
* Creates a new fraction-based painter.
*
* @param displayName
* The display name of this painter.
* @param fractions
* The fractions of this painter. Must be strictly increasing,
* starting from 0.0 and ending at 1.0.
* @param alphas
* Alpha channels of this painter. Must have the same size as fractions.
* @param colorQueries
* The color queries of this painter. Must have the same size as
* the fractions array, and all entries must be non-<code>null</code>.
*/
protected FractionBasedTonalPainter(String displayName, float[] fractions,
int[] alphas, ContainerColorTokensSingleColorQuery[] colorQueries) {

this.displayName = displayName;
if ((fractions == null) || (colorQueries == null)) {
if ((fractions == null) || (alphas == null) || (colorQueries == null)) {
throw new IllegalArgumentException("Cannot pass null arguments");
}
if (fractions.length != colorQueries.length) {
if ((fractions.length != alphas.length) || (fractions.length != colorQueries.length)) {
throw new IllegalArgumentException("Argument length does not match");
}
int length = fractions.length;
Expand All @@ -105,10 +139,12 @@ public FractionBasedTonalPainter(String displayName, float[] fractions,
throw new IllegalArgumentException("Cannot pass null query");
}
}
this.colorQueries = new ContainerColorTokensSingleColorQuery[length];
System.arraycopy(colorQueries, 0, this.colorQueries, 0, length);
this.fractions = new float[length];
System.arraycopy(fractions, 0, this.fractions, 0, length);
this.alphas = new int[length];
System.arraycopy(alphas, 0, this.alphas, 0, length);
this.colorQueries = new ContainerColorTokensSingleColorQuery[length];
System.arraycopy(colorQueries, 0, this.colorQueries, 0, length);
}

@Override
Expand All @@ -127,6 +163,12 @@ public float[] getFractions() {
return result;
}

public int[] getAlphas() {
int[] result = new int[this.alphas.length];
System.arraycopy(this.alphas, 0, result, 0, this.alphas.length);
return result;
}

/**
* Returns the color queries of this painter.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.pushingpixels.radiance.theming.api.colorscheme.RadianceColorScheme;
import org.pushingpixels.radiance.theming.api.painter.FractionBasedTonalPainter;
import org.pushingpixels.radiance.theming.api.palette.ContainerColorTokens;
import org.pushingpixels.radiance.theming.internal.utils.RadianceColorUtilities;
import org.pushingpixels.radiance.theming.internal.utils.RadianceInternalArrowButton;

import java.awt.*;
Expand Down Expand Up @@ -61,10 +62,29 @@ public class FractionBasedTonalBorderPainter extends FractionBasedTonalPainter
* <code>null</code>.
*/
public FractionBasedTonalBorderPainter(String displayName, float[] fractions,
ContainerColorTokensSingleColorQuery[] colorQueries) {
ContainerColorTokensSingleColorQuery[] colorQueries) {
super(displayName, fractions, colorQueries);
}

/**
* Creates a new fraction-based border painter.
*
* @param displayName
* The display name of this painter.
* @param fractions
* The fractions of this painter. Must be strictly increasing,
* starting from 0.0 and ending at 1.0.
* @param alphas Alpha channels of this painter. Must have the same size as fractions.
* @param colorQueries
* The color queries of this painter. Must have the same size as
* the fractions array, and all entries must be non-
* <code>null</code>.
*/
public FractionBasedTonalBorderPainter(String displayName, float[] fractions,
int[] alphas, ContainerColorTokensSingleColorQuery[] colorQueries) {
super(displayName, fractions, alphas, colorQueries);
}

@Override
public void paintBorder(Graphics g, Component c, float width, float height, Shape contour,
Shape innerContour, ContainerColorTokens colorTokens) {
Expand All @@ -76,7 +96,11 @@ public void paintBorder(Graphics g, Component c, float width, float height, Shap
Color[] drawColors = new Color[this.fractions.length];
for (int i = 0; i < this.fractions.length; i++) {
ContainerColorTokensSingleColorQuery colorQuery = this.colorQueries[i];
drawColors[i] = colorQuery.query(colorTokens);
Color fromQuery = colorQuery.query(colorTokens);
int alpha = this.alphas[i];
int finalAlpha = fromQuery.getAlpha() * alpha / 255;
Color finalColor = RadianceColorUtilities.getAlphaColor(fromQuery, finalAlpha);
drawColors[i] = finalColor;
}

// issue 433 - the "c" can be null when painting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.pushingpixels.radiance.theming.api.colorscheme.RadianceColorScheme;
import org.pushingpixels.radiance.theming.api.painter.FractionBasedTonalPainter;
import org.pushingpixels.radiance.theming.api.palette.ExtendedContainerColorTokens;
import org.pushingpixels.radiance.theming.internal.utils.RadianceColorUtilities;
import org.pushingpixels.radiance.theming.internal.utils.RadianceCoreUtilities;

import javax.swing.*;
Expand Down Expand Up @@ -140,10 +141,14 @@ private void paintDecoratedBackground(Graphics2D graphics, Component comp,
ExtendedContainerColorTokens colorTokens) {

Graphics2D g2d = (Graphics2D) graphics.create();
Color[] fillColors = new Color[this.fractions.length];
Color[] drawColors = new Color[this.fractions.length];
for (int i = 0; i < this.fractions.length; i++) {
ContainerColorTokensSingleColorQuery colorQuery = this.colorQueries[i];
fillColors[i] = colorQuery.query(colorTokens.getBaseContainerTokens());
Color fromQuery = colorQuery.query(colorTokens.getBaseContainerTokens());
int alpha = this.alphas[i];
int finalAlpha = fromQuery.getAlpha() * alpha / 255;
Color finalColor = RadianceColorUtilities.getAlphaColor(fromQuery, finalAlpha);
drawColors[i] = finalColor;
}

Component topMostWithSameDecorationAreaType = RadianceCoreUtilities
Expand All @@ -154,8 +159,8 @@ private void paintDecoratedBackground(Graphics2D graphics, Component comp,
int dy = inTopMost.y;

MultipleGradientPaint gradient = new LinearGradientPaint(0, 0, 0,
topMostWithSameDecorationAreaType.getHeight(), this.fractions,
fillColors, CycleMethod.REPEAT);
topMostWithSameDecorationAreaType.getHeight(), this.fractions,
drawColors, CycleMethod.REPEAT);
g2d.setPaint(gradient);
g2d.translate(0, -dy);
g2d.fillRect(0, 0, width, topMostWithSameDecorationAreaType.getHeight());
Expand All @@ -168,10 +173,14 @@ private void paintDecoratedBackground(Graphics2D graphics, Component comp,
ExtendedContainerColorTokens colorTokens) {

Graphics2D g2d = (Graphics2D) graphics.create();
Color[] fillColors = new Color[this.fractions.length];
Color[] drawColors = new Color[this.fractions.length];
for (int i = 0; i < this.fractions.length; i++) {
ContainerColorTokensSingleColorQuery colorQuery = this.colorQueries[i];
fillColors[i] = colorQuery.query(colorTokens.getBaseContainerTokens());
Color fromQuery = colorQuery.query(colorTokens.getBaseContainerTokens());
int alpha = this.alphas[i];
int finalAlpha = fromQuery.getAlpha() * alpha / 255;
Color finalColor = RadianceColorUtilities.getAlphaColor(fromQuery, finalAlpha);
drawColors[i] = finalColor;
}

Component topMostWithSameDecorationAreaType = RadianceCoreUtilities
Expand All @@ -182,8 +191,8 @@ private void paintDecoratedBackground(Graphics2D graphics, Component comp,
int dy = inTopMost.y;

MultipleGradientPaint gradient = new LinearGradientPaint(0, 0, 0,
topMostWithSameDecorationAreaType.getHeight(), this.fractions,
fillColors, CycleMethod.REPEAT);
topMostWithSameDecorationAreaType.getHeight(), this.fractions,
drawColors, CycleMethod.REPEAT);
g2d.setPaint(gradient);
g2d.translate(0, -dy);
g2d.fill(contour);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.pushingpixels.radiance.theming.api.colorscheme.RadianceColorScheme;
import org.pushingpixels.radiance.theming.api.painter.FractionBasedTonalPainter;
import org.pushingpixels.radiance.theming.api.palette.ContainerColorTokens;
import org.pushingpixels.radiance.theming.internal.utils.RadianceColorUtilities;

import java.awt.*;
import java.awt.MultipleGradientPaint.CycleMethod;
Expand Down Expand Up @@ -65,14 +66,18 @@ public void paintContourBackground(Graphics g, Component comp, float width, floa
Shape contour, ContainerColorTokens colorTokens) {
Graphics2D graphics = (Graphics2D) g.create();

Color[] fillColors = new Color[this.fractions.length];
Color[] drawColors = new Color[this.fractions.length];
for (int i = 0; i < this.fractions.length; i++) {
ContainerColorTokensSingleColorQuery colorQuery = this.colorQueries[i];
fillColors[i] = colorQuery.query(colorTokens);
Color fromQuery = colorQuery.query(colorTokens);
int alpha = this.alphas[i];
int finalAlpha = fromQuery.getAlpha() * alpha / 255;
Color finalColor = RadianceColorUtilities.getAlphaColor(fromQuery, finalAlpha);
drawColors[i] = finalColor;
}

MultipleGradientPaint gradient = new LinearGradientPaint(0, 0, 0, height, this.fractions,
fillColors, CycleMethod.REPEAT);
drawColors, CycleMethod.REPEAT);
graphics.setPaint(gradient);
graphics.fill(contour);
graphics.dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,14 @@ public GeminiTonalSkin() {

this.borderPainter = new CompositeBorderPainter("Gemini",
new FlatTonalBorderPainter(),
new DelegateFractionBasedTonalBorderPainter(
"Gemini Inner", new FlatTonalBorderPainter(),
new int[]{0xA0FFFFFF, 0x80FFFFFF, 0x60FFFFFF},
colorTokens -> ColorSchemeUtils.tint(colorTokens, 0.7f)));
new FractionBasedTonalBorderPainter("Gemini Inner",
new float[] {0.0f, 0.5f, 1.0f},
new int[] {96, 64, 32},
new ContainerColorTokensSingleColorQuery[] {
ContainerColorTokensSingleColorQuery.COMPLEMENTARY_CONTAINER_OUTLINE,
ContainerColorTokensSingleColorQuery.COMPLEMENTARY_CONTAINER_OUTLINE,
ContainerColorTokensSingleColorQuery.COMPLEMENTARY_CONTAINER_OUTLINE
}));
this.highlightBorderPainter = new FlatTonalBorderPainter();
}

Expand Down

0 comments on commit 0656ba9

Please sign in to comment.