|
| 1 | +package eu.rekawek.coffeegb.ui.menu.artwork; |
| 2 | + |
| 3 | +import eu.rekawek.coffeegb.ui.menu.MenuRoute; |
| 4 | + |
| 5 | +import java.util.Collections; |
| 6 | +import java.util.EnumMap; |
| 7 | +import java.util.HashSet; |
| 8 | +import java.util.Map; |
| 9 | +import java.util.Objects; |
| 10 | +import java.util.Set; |
| 11 | + |
| 12 | +/** |
| 13 | + * The canonical Proposal 3 artwork catalog. |
| 14 | + * |
| 15 | + * <p>The source PNGs are complete 1672x941 compositions, but the test fixtures packaged by this |
| 16 | + * revision are already the fixed 924x736 crop declared by {@link #SOURCE_VISIBLE_CROP}. Runtime |
| 17 | + * route/atlas paths are reserved for the later sanitized compositor integration. |
| 18 | + */ |
| 19 | +public final class MenuArtworkCatalog { |
| 20 | + |
| 21 | + /** Width of every original Proposal 3 composition in pixels. */ |
| 22 | + public static final int SOURCE_WIDTH = 1672; |
| 23 | + |
| 24 | + /** Height of every original Proposal 3 composition in pixels. */ |
| 25 | + public static final int SOURCE_HEIGHT = 941; |
| 26 | + |
| 27 | + /** Width of each lossless packaged canonical crop. */ |
| 28 | + public static final int PACKAGED_WIDTH = 924; |
| 29 | + |
| 30 | + /** Height of each lossless packaged canonical crop. */ |
| 31 | + public static final int PACKAGED_HEIGHT = 736; |
| 32 | + |
| 33 | + /** Original-composition crop retained as provenance for every packaged image. */ |
| 34 | + public static final MenuRect SOURCE_VISIBLE_CROP = new MenuRect(374, 102, 924, 736); |
| 35 | + |
| 36 | + /** The complete bounds of each packaged image. */ |
| 37 | + public static final MenuRect PACKAGED_BOUNDS = new MenuRect(0, 0, PACKAGED_WIDTH, PACKAGED_HEIGHT); |
| 38 | + |
| 39 | + private static final String FIXTURE_RESOURCE_ROOT = |
| 40 | + "/eu/rekawek/coffeegb/ui/menu/artwork/proposal3/source/"; |
| 41 | + |
| 42 | + private static final Map<MenuRoute, MenuArtwork> ARTWORK = createCatalog(); |
| 43 | + |
| 44 | + private MenuArtworkCatalog() { |
| 45 | + } |
| 46 | + |
| 47 | + /** Returns the one canonical artwork entry for a route. */ |
| 48 | + public static MenuArtwork artwork(MenuRoute route) { |
| 49 | + return ARTWORK.get(Objects.requireNonNull(route, "route")); |
| 50 | + } |
| 51 | + |
| 52 | + /** Returns an immutable route-to-artwork view containing every menu route exactly once. */ |
| 53 | + public static Map<MenuRoute, MenuArtwork> all() { |
| 54 | + return ARTWORK; |
| 55 | + } |
| 56 | + |
| 57 | + private static Map<MenuRoute, MenuArtwork> createCatalog() { |
| 58 | + EnumMap<MenuRoute, MenuArtwork> catalog = new EnumMap<>(MenuRoute.class); |
| 59 | + add(catalog, MenuRoute.PAUSE_CONSOLE, "00-pause-console.png"); |
| 60 | + add(catalog, MenuRoute.SAVE_STATES, "01-save-states.png"); |
| 61 | + add(catalog, MenuRoute.SETTINGS, "02-settings.png"); |
| 62 | + add(catalog, MenuRoute.AUDIO, "03-audio.png"); |
| 63 | + add(catalog, MenuRoute.TOUCH_CONTROLS, "04-touch-controls.png"); |
| 64 | + add(catalog, MenuRoute.CONTROLLER_MAPPING, "05-controller-mapping.png"); |
| 65 | + add(catalog, MenuRoute.OPTIONAL_DEVICES, "06-optional-devices.png"); |
| 66 | + add(catalog, MenuRoute.DATA_MEDIA, "07-data-media.png"); |
| 67 | + add(catalog, MenuRoute.LIBRARY, "08-library.png"); |
| 68 | + add(catalog, MenuRoute.CHOOSE_ROM, "09-choose-rom.png"); |
| 69 | + add(catalog, MenuRoute.SYSTEM, "10-system.png"); |
| 70 | + add(catalog, MenuRoute.ABOUT, "11-about.png"); |
| 71 | + add(catalog, MenuRoute.CONFIRM_ACTION, "12-confirm-action.png"); |
| 72 | + add(catalog, MenuRoute.PRINTER_PAPER, "13-printer-paper.png"); |
| 73 | + |
| 74 | + if (catalog.size() != MenuRoute.values().length) { |
| 75 | + throw new IllegalStateException("Proposal 3 artwork catalog does not cover every route"); |
| 76 | + } |
| 77 | + Set<String> paths = new HashSet<>(); |
| 78 | + for (MenuRoute route : MenuRoute.values()) { |
| 79 | + MenuArtwork artwork = catalog.get(route); |
| 80 | + if (artwork == null || !paths.add(artwork.resourcePath())) { |
| 81 | + throw new IllegalStateException("Proposal 3 artwork catalog contains a duplicate or missing route"); |
| 82 | + } |
| 83 | + } |
| 84 | + return Collections.unmodifiableMap(catalog); |
| 85 | + } |
| 86 | + |
| 87 | + private static void add(EnumMap<MenuRoute, MenuArtwork> catalog, MenuRoute route, String filename) { |
| 88 | + if (catalog.containsKey(route)) { |
| 89 | + throw new IllegalStateException("Duplicate artwork route: " + route); |
| 90 | + } |
| 91 | + MenuArtwork artwork = new MenuArtwork(route, filename, FIXTURE_RESOURCE_ROOT + filename, |
| 92 | + SOURCE_VISIBLE_CROP); |
| 93 | + for (MenuArtwork existing : catalog.values()) { |
| 94 | + if (existing.resourcePath().equals(artwork.resourcePath())) { |
| 95 | + throw new IllegalStateException("Duplicate artwork resource: " + artwork.resourcePath()); |
| 96 | + } |
| 97 | + } |
| 98 | + catalog.put(route, artwork); |
| 99 | + } |
| 100 | +} |
0 commit comments