in icon-scripts/hidpi-icons/src/main/java/org/netbeans/build/icons/IconTasks.java [69:314]
public static void main(String[] args) throws IOException {
final File ICON_SCRIPTS_DIR = new File(System.getProperty("user.dir"), "../");
if (!new File(ICON_SCRIPTS_DIR, "hidpi-icons/src/main/java/org/netbeans/build/icons/IconTasks.java").exists()) {
System.err.println("Error: Working directory must be icon-scripts/hidpi-icons");
System.exit(-1);
}
if (args.length != 1) {
System.err.println("Usage: IconTasks <netbeans repo directory>");
System.err.println();
System.err.println("(Working directory must be icon-scripts/hidpi-icons )");
System.exit(-1);
}
final File NBSRC_DIR = new File(args[0]);
if (!new File(NBSRC_DIR, "platform/core.windows/build.xml").exists()) {
System.err.println("Path " + args[0] + " (in command-line argument) is not a cloned NetBeans repository");
System.exit(-1);
}
final File ILLUSTRATOR_SVGS_DIR =
new File(ICON_SCRIPTS_DIR, "illustrator_exports/");
final File TABLES_DIR = new File(ICON_SCRIPTS_DIR, "tables/");
final File ICON_HASHES_FILE = new File(TABLES_DIR, "icon-hashes.txt");
final File MAPPINGS_FILE = new File(TABLES_DIR, "mappings.tsv");
final File READY_ARTBOARDS_FILE = new File(TABLES_DIR, "ready-artboards.txt");
final File ICONS_HTML_FILE = new File(NBSRC_DIR, "icons.html");
boolean copySVGfiles =
ILLUSTRATOR_SVGS_DIR.listFiles(f-> f.toString().endsWith(".svg")).length > 0;
System.out.println("Using icon hashes file : " + ICON_HASHES_FILE);
System.out.println("Using mappings file : " + MAPPINGS_FILE);
System.out.println("Using ready-artboards file : " + READY_ARTBOARDS_FILE);
if (copySVGfiles) {
System.out.println("Copying SVG files from : " + ILLUSTRATOR_SVGS_DIR);
} else {
System.out.println("The " + ILLUSTRATOR_SVGS_DIR +
" folder has no SVGs in it to copy. " +
"Will verify the existence of existing SVG files in the NetBeans repo only.");
}
ImmutableMap<IconPath, Hash> iconHashesByFile =
readIconHashesByFile(NBSRC_DIR, ICON_HASHES_FILE);
ImmutableSetMultimap<Hash, IconPath> filesByHash = Util.reverse(iconHashesByFile);
ImmutableMap<Hash, Dimension> dimensionsByHash = readImageDimensions(NBSRC_DIR, filesByHash);
// iconHashesByFile.forEach((key, value) -> System.out.println(key + " : " + value));
ImmutableMap<IconPath, ArtboardName> artboardByFile =
readArtboardByFileMappings(NBSRC_DIR, MAPPINGS_FILE);
// artboardByFile.forEach((key, value) -> System.out.println(key + " : " + value));
ImmutableSet<ArtboardName> readyArtboards = readReadyArtboards(READY_ARTBOARDS_FILE);
SetMultimap<ArtboardName,Hash> hashesByArtboard = LinkedHashMultimap.create();
for (Entry<IconPath, ArtboardName> entry : artboardByFile.entrySet()) {
IconPath ip = entry.getKey();
ArtboardName artboard = entry.getValue();
Hash hash = Util.getChecked(iconHashesByFile, ip);
hashesByArtboard.put(artboard, hash);
}
Set<ArtboardName> unknownReadyArtboards =
Sets.difference(readyArtboards, hashesByArtboard.keySet());
if (!unknownReadyArtboards.isEmpty()) {
throw new RuntimeException("Unknown artboards " + unknownReadyArtboards);
}
if (copySVGfiles) {
for (ArtboardName artboard : readyArtboards) {
File artboardSVGFile = getIllustratorSVGFile(ILLUSTRATOR_SVGS_DIR, artboard);
if (!artboardSVGFile.exists()) {
System.out.println("Illustrator export " + artboardSVGFile + " not found; skipping.");
}
}
}
// hashesByArtboard.asMap().forEach((key, value) -> System.out.println(key + " : " + value));
Map<IconPath, ArtboardName> newArtboardByFile = Maps.newLinkedHashMap();
for (Entry<ArtboardName, Hash> entry : hashesByArtboard.entries()) {
ArtboardName artboard = entry.getKey();
Hash hash = entry.getValue();
List<IconPath> pathsForThisHash = Lists.newArrayList(filesByHash.get(hash));
pathsForThisHash.sort((e1, e2) -> e1.toString().compareTo(e2.toString()));
for (IconPath ip : pathsForThisHash) {
Util.putChecked(newArtboardByFile, ip, artboard);
}
}
ArtboardName UNASSIGNED_ARTBOARD = new ArtboardName("(no assigned artboard)");
{
List<Entry<IconPath,Dimension>> unassignedIcons = Lists.newArrayList();
for (Entry<IconPath, Hash> entry : iconHashesByFile.entrySet()) {
IconPath ip = entry.getKey();
Hash hash = entry.getValue();
Dimension dim = Util.getChecked(dimensionsByHash, hash);
if (dim.width <= 64 && dim.height <= 64 && dim.width > 1 && dim.height > 1) {
unassignedIcons.add(new SimpleEntry(ip, dim));
}
}
/* Order unassigned icons by width, then by height, then by path. (If there are multiple
paths, the first path will end up being used for sorting per putIfAbsent below.) */
unassignedIcons.sort((e1, e2) -> {
int ret = Integer.compare(e1.getValue().width, e2.getValue().width);
if (ret == 0) {
ret = Integer.compare(e1.getValue().height, e2.getValue().height);
}
if (ret == 0) {
ret = e1.getKey().toString().compareTo(e2.getKey().toString());
}
return ret;
});
for (Entry<IconPath,Dimension> entry : unassignedIcons) {
newArtboardByFile.putIfAbsent(entry.getKey(), UNASSIGNED_ARTBOARD);
}
}
// newArtboardByFile.forEach((key, value) -> System.out.println(key + " : " + value));
ImmutableSetMultimap<ArtboardName, IconPath> filesByArtboard =
Util.reverse(newArtboardByFile);
for (ArtboardName artboard : readyArtboards) {
final String svgContentToWrite;
if (copySVGfiles) {
svgContentToWrite = prepareSVGWithInsertedLicense(ILLUSTRATOR_SVGS_DIR, artboard);
} else {
svgContentToWrite = null;
}
for (IconPath ip : filesByArtboard.get(artboard)) {
if (shouldIgnoreFile(ip)) {
continue;
}
IconPath destSVG = getSVGIconPath(ip);
// System.out.println(srcSVGFile + "\t" + destSVG);
File destSVGFile = new File(NBSRC_DIR, destSVG.toString());
if (svgContentToWrite != null) {
try (PrintWriter pw = createPrintWriter(destSVGFile)) {
pw.print(svgContentToWrite);
}
System.out.println("Copied SVG file to " + destSVGFile);
} else {
if (!destSVGFile.exists()) {
throw new RuntimeException(destSVGFile + " does not exist, and no " +
"SVGs to copy exist in the illustrator_exports directory.");
}
System.out.println("Verified existence of SVG file " + destSVGFile);
}
}
}
/* The mappings file is assumed to be in a git repo so that the user of the script can
see what changed from run to run. */
try (PrintWriter mappingsPW = createPrintWriter(MAPPINGS_FILE);
PrintWriter htmlPW = createPrintWriter(ICONS_HTML_FILE))
{
htmlPW.println(LICENSE_HEADER);
htmlPW.println("""
<html>
<head>
<title>NetBeans Icons</title>
<!--The the image paths in this file assume that this HTML file is located in the
root of a clone of the NetBeans source repository. To use images from a specific
GitHub branch (e.g. belonging to a pull request), a line like the following can
be included here:
<base href="https://raw.githubusercontent.com/eirikbakke/incubator-netbeans/pr-svgs240612/">
-->
<style>
table td, table td * { vertical-align: top; margin-left: 5px; }
thead td { padding-right: 10px; padding-bottom: 10px; }
td { padding-right: 10px; }
thead { font-weight: bold; }
</style></head><body>
<h1>NetBeans Bitmap and SVG Icons</h1>
<p>This file lists bitmap icon files (GIF and PNG) in the NetBeans repo along with
their mapping to corresponding modernized SVG versions where available. A single
"artboard name" is assigned to icons that are exact or near duplicates, or which
are intended to have the same meaning.
<p>This file is generated by the
<tt>icon-scripts/hidpi-icons</tt> script in the
<a href="https://github.com/apache/netbeans-tools">netbeans-tools</a>
repository. Image paths are relative to the root of the NetBeans
<a href="https://github.com/apache/netbeans">source repository</a>.
<p>See the <a href="https://github.com/apache/netbeans-tools/tree/master/icon-scripts#readme">README</a>,
<a href="https://cwiki.apache.org/confluence/display/NETBEANS/SVG+Icon+Style+Guide+and+Process">Style Guide</a>, and
<a href="https://vimeo.com/667860571">Icon Drawing Video Tutorial</a> for more information.
"""
);
htmlPW.println("""
<p><table border='0' cellpadding='1' cellspacing='0'>
<thead><tr><td>Artboard Name<td>SVG<td>Bitmap<td>Dim<td>Path of Bitmap in
Source Repo (no icon image means same as for previous row)</tr></thead>""");
int artboardIdx = 0;
Set<ArtboardName> artboardsInOrder = Sets.newLinkedHashSet();
artboardsInOrder.addAll(Sets.filter(filesByArtboard.keySet(), a -> readyArtboards.contains(a)));
artboardsInOrder.addAll(filesByArtboard.keySet());
for (ArtboardName artboard : artboardsInOrder) {
List<IconPath> ips = Lists.newArrayList(filesByArtboard.get(artboard));
ips.removeIf(ip -> shouldIgnoreFile(ip));
/* Make sure to retain the original order, except keep files with the same hash
together. */
Map<Hash,Integer> order = Maps.newLinkedHashMap();
for (IconPath ip : ips) {
order.putIfAbsent(Util.getChecked(iconHashesByFile, ip), order.size());
}
ips.sort((ip1, ip2) -> Integer.compare(
Util.getChecked(order, Util.getChecked(iconHashesByFile, ip1)),
Util.getChecked(order, Util.getChecked(iconHashesByFile, ip2))));
int subRowIdx = 0;
Hash previousHash = null;
for (IconPath ip : ips) {
Hash hash = Util.getChecked(iconHashesByFile, ip);
if (!UNASSIGNED_ARTBOARD.equals(artboard)) {
mappingsPW.println(artboard + " " + ip);
}
htmlPW.print(artboardIdx % 2 == 0 ? "<tr>" :
"<tr style='background: #eee'>");
if (subRowIdx == 0) {
htmlPW.print("<td rowspan='" + ips.size() + "'>" + artboard);
htmlPW.print("<td rowspan='" + ips.size() + "'>");
if (readyArtboards.contains(artboard)) {
htmlPW.print("<img src='" + getSVGIconPath(ip) + "'>");
}
}
htmlPW.print("<td>");
if (!hash.equals(previousHash)) {
htmlPW.print("<img src='" + ip + "'>");
}
htmlPW.print("<td>");
if (!hash.equals(previousHash)) {
Dimension dim = Util.getChecked(dimensionsByHash, hash);
htmlPW.print(dim.width + "x" + dim.height);
}
htmlPW.print("<td>" + ip);
htmlPW.println("</tr>");
previousHash = hash;
subRowIdx++;
}
artboardIdx++;
}
htmlPW.println("</table>");
htmlPW.println("</body>");
}
System.out.println(
"A summary of bitmap icons, SVG icons, and artboard name mappings was generated here:");
System.out.println(ICONS_HTML_FILE);
}