feat(renderer): add new font resources and update theme font settings

This commit is contained in:
extio-de
2025-12-28 16:23:07 +01:00
parent 8636ddd6dd
commit a156423dfb
24 changed files with 135 additions and 77 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,7 @@
package de.extio.game_engine.renderer; package de.extio.game_engine.renderer;
import de.extio.game_engine.renderer.model.options.UiOptions;
import de.extio.game_engine.renderer.model.options.VideoOptions;
import de.extio.game_engine.spatial2.model.CoordI2; import de.extio.game_engine.spatial2.model.CoordI2;
import de.extio.game_engine.spatial2.model.ImmutableCoordI2; import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
@@ -16,9 +18,13 @@ public interface RendererControl {
void setTitle(String title); void setTitle(String title);
VideoOptions getVideoOptions();
void applyVideoOptions(); void applyVideoOptions();
long getVideoOptionsAppliedAt(); long getVideoOptionsAppliedAt();
UiOptions getUiOptions();
CoordI2 getAbsoluteViewportDimension(); CoordI2 getAbsoluteViewportDimension();

View File

@@ -8,6 +8,8 @@ import org.slf4j.LoggerFactory;
import de.extio.game_engine.keyboard.KeyModifiers; import de.extio.game_engine.keyboard.KeyModifiers;
import de.extio.game_engine.keyboard.KeycodeRegistration; import de.extio.game_engine.keyboard.KeycodeRegistration;
import de.extio.game_engine.renderer.g2d.theme.Theme;
import de.extio.game_engine.renderer.g2d.theme.Theme;
import de.extio.game_engine.renderer.model.options.VideoOptions; import de.extio.game_engine.renderer.model.options.VideoOptions;
public class RendererLoop implements Runnable { public class RendererLoop implements Runnable {
@@ -32,9 +34,12 @@ public class RendererLoop implements Runnable {
this.rendererData.getStorageService() this.rendererData.getStorageService()
.loadByPath(VideoOptions.class, List.of("gameEngine"), "videoOptions") .loadByPath(VideoOptions.class, List.of("gameEngine"), "videoOptions")
.ifPresent(options -> this.rendererData.getVideoOptions().apply(options)); .ifPresent(options -> this.rendererData.getVideoOptions().apply(options));
this.rendererData.getRenderer().show(); this.rendererData.getRenderer().show();
this.rendererData.getThemeManager().setCurrentTheme((Theme)null);
LOGGER.info("Renderer loop started"); LOGGER.info("Renderer loop started");
int exceptionCount = 0; int exceptionCount = 0;
while (!this.shutdown) { while (!this.shutdown) {

View File

@@ -31,6 +31,16 @@ import de.extio.game_engine.storage.StorageService;
@ConditionalOnProperty(name = "game-engine.renderer.enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnProperty(name = "game-engine.renderer.enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnProperty(name = "game-engine.renderer.strategy", havingValue = "g2d", matchIfMissing = true) @ConditionalOnProperty(name = "game-engine.renderer.strategy", havingValue = "g2d", matchIfMissing = true)
public class G2DAutoConfiguration { public class G2DAutoConfiguration {
@Bean
G2DThemeManager g2dThemeManager(
final StaticResourceService staticResourceService,
final StorageService storageService,
final List<PatternRenderer> patternRendererList,
final Map<String, Theme> themes,
@Value("${game-engine.renderer.default-theme:urbanTheme}") final String defaultThemeName) {
return new G2DThemeManager(staticResourceService, storageService, patternRendererList, themes, defaultThemeName);
}
@Bean @Bean
G2DRenderer g2dRenderer( G2DRenderer g2dRenderer(
@@ -46,8 +56,10 @@ public class G2DAutoConfiguration {
} }
@Bean @Bean
G2DRendererControl g2dRendererControl(final G2DRenderer renderer) { G2DRendererControl g2dRendererControl(final G2DRenderer renderer, final G2DThemeManager themeManager) {
return new G2DRendererControl(renderer); var control = new G2DRendererControl(renderer);
themeManager.setG2dRendererControl(control);
return control;
} }
@Bean @Bean
@@ -110,14 +122,4 @@ public class G2DAutoConfiguration {
return new BlueprintThemeFactoryBean(); return new BlueprintThemeFactoryBean();
} }
@Bean
G2DThemeManager g2dThemeManager(
final StaticResourceService staticResourceService,
final StorageService storageService,
final List<PatternRenderer> patternRendererList,
final Map<String, Theme> themes,
@Value("${game-engine.renderer.default-theme:urbanTheme}") final String defaultThemeName) {
return new G2DThemeManager(staticResourceService, storageService, patternRendererList, themes, defaultThemeName);
}
} }

View File

@@ -165,7 +165,7 @@ public class G2DRenderer implements Renderer {
throw new G2DRendererWindowNotInitializedException(); throw new G2DRendererWindowNotInitializedException();
} }
if (this.previousDefaultFont == null && this.rendererData.getUiOptions().getFontResource() != null && !this.rendererData.getUiOptions().getFontResource().equals(this.previousDefaultFont)) { if (this.previousDefaultFont == null || (this.rendererData.getUiOptions().getFontResource() != null && !this.rendererData.getUiOptions().getFontResource().equals(this.previousDefaultFont))) {
this.previousDefaultFont = this.rendererData.getUiOptions().getFontResource(); this.previousDefaultFont = this.rendererData.getUiOptions().getFontResource();
G2DDrawFont.updateDefaultFont(this.rendererData.getStaticResourceService(), this.rendererData.getUiOptions().getFontResource()); G2DDrawFont.updateDefaultFont(this.rendererData.getStaticResourceService(), this.rendererData.getUiOptions().getFontResource());
} }

View File

@@ -11,6 +11,8 @@ import org.slf4j.LoggerFactory;
import de.extio.game_engine.renderer.RendererControl; import de.extio.game_engine.renderer.RendererControl;
import de.extio.game_engine.renderer.RendererData; import de.extio.game_engine.renderer.RendererData;
import de.extio.game_engine.renderer.model.event.ViewportResizeEvent; import de.extio.game_engine.renderer.model.event.ViewportResizeEvent;
import de.extio.game_engine.renderer.model.options.UiOptions;
import de.extio.game_engine.renderer.model.options.VideoOptions;
import de.extio.game_engine.renderer.model.options.VideoOptions.VideoOptionsVideoMode; import de.extio.game_engine.renderer.model.options.VideoOptions.VideoOptionsVideoMode;
import de.extio.game_engine.spatial2.model.CoordI2; import de.extio.game_engine.spatial2.model.CoordI2;
import de.extio.game_engine.spatial2.model.ImmutableCoordI2; import de.extio.game_engine.spatial2.model.ImmutableCoordI2;
@@ -286,6 +288,16 @@ public class G2DRendererControl implements RendererControl {
this.rendererData = rendererData; this.rendererData = rendererData;
} }
@Override
public UiOptions getUiOptions() {
return this.rendererData.getUiOptions();
}
@Override
public VideoOptions getVideoOptions() {
return this.rendererData.getVideoOptions();
}
private static record G2DRendererControlOptions(double scaleFactorModifier) { private static record G2DRendererControlOptions(double scaleFactorModifier) {
} }
} }

View File

@@ -8,6 +8,7 @@ public class BevelDarkThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Bevel Dark") .name("Bevel Dark")
.font("Roboto-Regular.ttf")
.patternRendererName("bevelPatternRenderer") .patternRendererName("bevelPatternRenderer")
// Highlight (Light Grey) // Highlight (Light Grey)
.borderOuter(new HSBColor(0.0f, 0.0f, 0.6f)) .borderOuter(new HSBColor(0.0f, 0.0f, 0.6f))

View File

@@ -8,6 +8,7 @@ public class BevelLightThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Bevel Light") .name("Bevel Light")
.font("Roboto-Regular.ttf")
.patternRendererName("bevelPatternRenderer") .patternRendererName("bevelPatternRenderer")
// Highlight (White) // Highlight (White)
.borderOuter(new HSBColor(0.0f, 0.0f, 1.0f)) .borderOuter(new HSBColor(0.0f, 0.0f, 1.0f))

View File

@@ -8,6 +8,7 @@ public class BlueprintThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Blueprint") .name("Blueprint")
.font("Inter_24pt-Regular.ttf")
.patternRendererName("blueprintPatternRenderer") .patternRendererName("blueprintPatternRenderer")
// Highlight/Border (White/Cyan) // Highlight/Border (White/Cyan)
.borderOuter(new HSBColor(0.5f, 0.0f, 1.0f)) .borderOuter(new HSBColor(0.5f, 0.0f, 1.0f))

View File

@@ -8,6 +8,7 @@ public class ContemporaryThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Contemporary") .name("Contemporary")
.font("Lato-Regular.ttf")
.patternRendererName("modernPatternRenderer") .patternRendererName("modernPatternRenderer")
.borderOuter(new HSBColor(0.88f, 0.12f, 0.75f)) .borderOuter(new HSBColor(0.88f, 0.12f, 0.75f))
.borderInner(new HSBColor(0.88f, 0.10f, 0.92f)) .borderInner(new HSBColor(0.88f, 0.10f, 0.92f))

View File

@@ -8,6 +8,7 @@ public class DreamThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Dream") .name("Dream")
.font("Lora-Regular.ttf")
.patternRendererName("dreamPatternRenderer") .patternRendererName("dreamPatternRenderer")
.borderOuter(new HSBColor(0.74f, 0.22f, 0.80f)) .borderOuter(new HSBColor(0.74f, 0.22f, 0.80f))
.borderInner(new HSBColor(0.83f, 0.18f, 0.95f)) .borderInner(new HSBColor(0.83f, 0.18f, 0.95f))

View File

@@ -8,6 +8,7 @@ public class FantasyThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Fantasy") .name("Fantasy")
.font("LibreBaskerville-Regular.ttf")
.patternRendererName("fantasyPatternRenderer") .patternRendererName("fantasyPatternRenderer")
.borderOuter(new HSBColor(0.12f, 0.55f, 0.48f)) .borderOuter(new HSBColor(0.12f, 0.55f, 0.48f))
.borderInner(new HSBColor(0.14f, 0.25f, 0.72f)) .borderInner(new HSBColor(0.14f, 0.25f, 0.72f))

View File

@@ -13,6 +13,7 @@ import org.slf4j.LoggerFactory;
import de.extio.game_engine.renderer.ThemeManager; import de.extio.game_engine.renderer.ThemeManager;
import de.extio.game_engine.renderer.g2d.G2DRenderer; import de.extio.game_engine.renderer.g2d.G2DRenderer;
import de.extio.game_engine.renderer.g2d.G2DRendererControl;
import de.extio.game_engine.resource.StaticResource; import de.extio.game_engine.resource.StaticResource;
import de.extio.game_engine.resource.StaticResourceService; import de.extio.game_engine.resource.StaticResourceService;
import de.extio.game_engine.storage.StorageService; import de.extio.game_engine.storage.StorageService;
@@ -25,6 +26,7 @@ public class G2DThemeManager implements ThemeManager {
private static final String THEME_STORAGE_NAME = "lastTheme"; private static final String THEME_STORAGE_NAME = "lastTheme";
private G2DRenderer g2dRenderer; private G2DRenderer g2dRenderer;
private G2DRendererControl g2dRendererControl;
private final StaticResourceService staticResourceService; private final StaticResourceService staticResourceService;
private final StorageService storageService; private final StorageService storageService;
@@ -52,33 +54,6 @@ public class G2DThemeManager implements ThemeManager {
LOGGER.info("G2DThemeManager initialized with {} pattern renderers: {}", this.patternRenderers.size(), this.patternRenderers.keySet()); LOGGER.info("G2DThemeManager initialized with {} pattern renderers: {}", this.patternRenderers.size(), this.patternRenderers.keySet());
LOGGER.info("G2DThemeManager initialized with {} themes: {}", this.themes.size(), this.themes.keySet()); LOGGER.info("G2DThemeManager initialized with {} themes: {}", this.themes.size(), this.themes.keySet());
this.currentTheme = this.defaultTheme;
this.loadLastUsedTheme();
}
private void registerTheme(final Theme theme) {
if (theme == null || theme.getName() == null || theme.getName().isBlank()) {
return;
}
this.themes.put(theme.getName(), theme);
}
private void loadLastUsedTheme() {
if (this.storageService == null) {
return;
}
try {
final Optional<Theme> persistedTheme = this.storageService.loadByPath(Theme.class, THEME_STORAGE_PATH, THEME_STORAGE_NAME);
if (persistedTheme.isPresent()) {
this.currentTheme = persistedTheme.get();
this.registerTheme(this.currentTheme);
LOGGER.info("Loaded last used theme: {}", this.currentTheme.getName());
return;
}
}
catch (final Exception e) {
LOGGER.warn("Could not load last used theme. Using default.", e);
}
} }
@Override @Override
@@ -131,7 +106,8 @@ public class G2DThemeManager implements ThemeManager {
@Override @Override
public void setCurrentTheme(final String themeName) { public void setCurrentTheme(final String themeName) {
if (themeName == null || themeName.isBlank()) { if (themeName == null || themeName.isBlank()) {
throw new IllegalArgumentException("themeName cannot be null/blank"); this.applyLastUsedOrDefault();
return;
} }
final var direct = this.themes.get(themeName); final var direct = this.themes.get(themeName);
@@ -151,45 +127,26 @@ public class G2DThemeManager implements ThemeManager {
this.setCurrentTheme(this.loadTheme(themeName)); this.setCurrentTheme(this.loadTheme(themeName));
} }
@Override
public void setCurrentTheme(final Theme theme) {
if (theme == null) {
this.applyLastUsedOrDefault();
return;
}
this.applyTheme(theme);
this.registerTheme(theme);
LOGGER.info("Theme switched to: {}", theme.getName());
this.persistLastUsedTheme(theme);
}
@Override @Override
public Theme getCurrentTheme() { public Theme getCurrentTheme() {
return this.currentTheme; return this.currentTheme;
} }
public PatternRenderer getPatternRenderer(final String rendererName) { private Theme loadTheme(final String themeName) {
return this.patternRenderers.get(rendererName);
}
@Override
public void setCurrentTheme(final Theme theme) {
if (theme == null) {
throw new IllegalArgumentException("Theme cannot be null");
}
this.currentTheme = theme;
this.registerTheme(theme);
LOGGER.info("Theme switched to: {}", theme.getName());
this.persistLastUsedTheme(theme);
if (this.g2dRenderer != null) {
this.g2dRenderer.reset();
}
}
private void persistLastUsedTheme(final Theme theme) {
if (this.storageService == null) {
return;
}
try {
this.storageService.store(THEME_STORAGE_PATH, THEME_STORAGE_NAME, theme);
}
catch (final Exception e) {
LOGGER.warn("Could not persist last used theme", e);
}
}
public Theme loadTheme(final String themeName) {
try { try {
final Optional<Theme> fromStorage = this.loadThemeFromStorage(themeName); final Optional<Theme> fromStorage = this.loadThemeFromStorage(themeName);
if (fromStorage.isPresent()) { if (fromStorage.isPresent()) {
@@ -205,7 +162,57 @@ public class G2DThemeManager implements ThemeManager {
return this.defaultTheme; return this.defaultTheme;
} }
private void applyLastUsedOrDefault() {
try {
final Optional<Theme> persistedTheme = this.storageService.loadByPath(Theme.class, THEME_STORAGE_PATH, THEME_STORAGE_NAME);
if (persistedTheme.isPresent()) {
this.applyTheme(persistedTheme.get());
this.registerTheme(this.currentTheme);
LOGGER.info("Loaded last used theme: {}", this.currentTheme.getName());
}
this.applyTheme(this.defaultTheme);
LOGGER.info("Loaded default theme: {}", this.currentTheme.getName());
}
catch (final Exception e) {
LOGGER.warn("Could not load last used theme. Using default.", e);
}
}
private void applyTheme(Theme theme) {
this.currentTheme = theme;
this.g2dRendererControl.getUiOptions().setFontResource(new StaticResource(List.of("renderer"), this.currentTheme.getFont()));
this.g2dRenderer.reset();
}
private void registerTheme(final Theme theme) {
if (theme == null || theme.getName() == null || theme.getName().isBlank()) {
return;
}
this.themes.put(theme.getName(), theme);
}
private void persistLastUsedTheme(final Theme theme) {
if (this.storageService == null) {
return;
}
try {
this.storageService.store(THEME_STORAGE_PATH, THEME_STORAGE_NAME, theme);
}
catch (final Exception e) {
LOGGER.warn("Could not persist last used theme", e);
}
}
public void setG2dRenderer(final G2DRenderer g2dRenderer) { public void setG2dRenderer(final G2DRenderer g2dRenderer) {
this.g2dRenderer = g2dRenderer; this.g2dRenderer = g2dRenderer;
} }
public void setG2dRendererControl(G2DRendererControl g2dRendererControl) {
this.g2dRendererControl = g2dRendererControl;
}
public PatternRenderer getPatternRenderer(final String rendererName) {
return this.patternRenderers.get(rendererName);
}
} }

View File

@@ -8,6 +8,7 @@ public class ModernThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Modern") .name("Modern")
.font("Inter_24pt-Regular.ttf")
.patternRendererName("modernPatternRenderer") .patternRendererName("modernPatternRenderer")
.borderOuter(new HSBColor(0.58f, 0.08f, 0.82f)) .borderOuter(new HSBColor(0.58f, 0.08f, 0.82f))
.borderInner(new HSBColor(0.58f, 0.10f, 0.92f)) .borderInner(new HSBColor(0.58f, 0.10f, 0.92f))

View File

@@ -8,6 +8,7 @@ public class NeonThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Neon") .name("Neon")
.font("Geist-Regular.ttf")
.patternRendererName("dreamPatternRenderer") .patternRendererName("dreamPatternRenderer")
.borderOuter(new HSBColor(0.83f, 0.80f, 0.95f)) .borderOuter(new HSBColor(0.83f, 0.80f, 0.95f))
.borderInner(new HSBColor(0.52f, 0.85f, 0.92f)) .borderInner(new HSBColor(0.52f, 0.85f, 0.92f))

View File

@@ -8,6 +8,7 @@ public class NoirThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Noir") .name("Noir")
.font("Lora-Regular.ttf")
.patternRendererName("urbanPatternRenderer") .patternRendererName("urbanPatternRenderer")
.borderOuter(new HSBColor(0.00f, 0.00f, 0.18f)) .borderOuter(new HSBColor(0.00f, 0.00f, 0.18f))
.borderInner(new HSBColor(0.00f, 0.00f, 0.45f)) .borderInner(new HSBColor(0.00f, 0.00f, 0.45f))

View File

@@ -8,6 +8,7 @@ public class SpacecraftThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Spacecraft") .name("Spacecraft")
.font("Roboto-Regular.ttf")
.patternRendererName("spacecraftPatternRenderer") .patternRendererName("spacecraftPatternRenderer")
.borderOuter(new HSBColor(0.71f, 0.12f, 0.50f)) .borderOuter(new HSBColor(0.71f, 0.12f, 0.50f))
.borderInner(new HSBColor(0.71f, 0.12f, 0.80f)) .borderInner(new HSBColor(0.71f, 0.12f, 0.80f))

View File

@@ -11,7 +11,8 @@ public class Theme {
private final String name; private final String name;
private final String patternRendererName; private final String patternRendererName;
private final String font;
// Element colors - Borders // Element colors - Borders
private final HSBColor borderOuter; private final HSBColor borderOuter;
private final HSBColor borderInner; private final HSBColor borderInner;
@@ -40,6 +41,7 @@ public class Theme {
public Theme( public Theme(
@JsonProperty("name") final String name, @JsonProperty("name") final String name,
@JsonProperty("patternRendererName") final String patternRendererName, @JsonProperty("patternRendererName") final String patternRendererName,
@JsonProperty("font") final String font,
@JsonProperty("borderOuter") final HSBColor borderOuter, @JsonProperty("borderOuter") final HSBColor borderOuter,
@JsonProperty("borderInner") final HSBColor borderInner, @JsonProperty("borderInner") final HSBColor borderInner,
@JsonProperty("borderInnerDisabled") final HSBColor borderInnerDisabled, @JsonProperty("borderInnerDisabled") final HSBColor borderInnerDisabled,
@@ -54,6 +56,7 @@ public class Theme {
@JsonProperty("pressedBrightnessAdjustment") final float pressedBrightnessAdjustment) { @JsonProperty("pressedBrightnessAdjustment") final float pressedBrightnessAdjustment) {
this.name = name; this.name = name;
this.patternRendererName = patternRendererName; this.patternRendererName = patternRendererName;
this.font = font;
this.borderOuter = borderOuter; this.borderOuter = borderOuter;
this.borderInner = borderInner; this.borderInner = borderInner;
this.borderInnerDisabled = borderInnerDisabled; this.borderInnerDisabled = borderInnerDisabled;
@@ -72,6 +75,7 @@ public class Theme {
this( this(
builder.name, builder.name,
builder.patternRendererName, builder.patternRendererName,
builder.font,
builder.borderOuter, builder.borderOuter,
builder.borderInner, builder.borderInner,
builder.borderInnerDisabled, builder.borderInnerDisabled,
@@ -94,6 +98,10 @@ public class Theme {
return this.patternRendererName; return this.patternRendererName;
} }
public String getFont() {
return this.font;
}
public HSBColor getBorderOuter() { public HSBColor getBorderOuter() {
return this.borderOuter; return this.borderOuter;
} }
@@ -149,6 +157,7 @@ public class Theme {
public static class Builder { public static class Builder {
private String name; private String name;
private String patternRendererName; private String patternRendererName;
private String font;
private HSBColor borderOuter; private HSBColor borderOuter;
private HSBColor borderInner; private HSBColor borderInner;
private HSBColor borderInnerDisabled; private HSBColor borderInnerDisabled;
@@ -172,6 +181,11 @@ public class Theme {
return this; return this;
} }
public Builder font(final String font) {
this.font = font;
return this;
}
public Builder borderOuter(final HSBColor borderOuter) { public Builder borderOuter(final HSBColor borderOuter) {
this.borderOuter = borderOuter; this.borderOuter = borderOuter;
return this; return this;

View File

@@ -8,6 +8,7 @@ public class UrbanThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Urban") .name("Urban")
.font("Geist-Regular.ttf")
.patternRendererName("metroPatternRenderer") .patternRendererName("metroPatternRenderer")
.borderOuter(new HSBColor(0.58f, 0.08f, 0.30f)) .borderOuter(new HSBColor(0.58f, 0.08f, 0.30f))
.borderInner(new HSBColor(0.58f, 0.06f, 0.72f)) .borderInner(new HSBColor(0.58f, 0.06f, 0.72f))

View File

@@ -8,6 +8,7 @@ public class VintageThemeFactoryBean implements FactoryBean<Theme> {
public Theme getObject() { public Theme getObject() {
return Theme.builder() return Theme.builder()
.name("Vintage") .name("Vintage")
.font("LibreBaskerville-Regular.ttf")
.patternRendererName("vintagePatternRenderer") .patternRendererName("vintagePatternRenderer")
.borderOuter(new HSBColor(0.08f, 0.55f, 0.22f)) .borderOuter(new HSBColor(0.08f, 0.55f, 0.22f))
.borderInner(new HSBColor(0.10f, 0.30f, 0.55f)) .borderInner(new HSBColor(0.10f, 0.30f, 0.55f))