org.xlrnet.tibaija.tools.fontgen.FontgenApplication.java Source code

Java tutorial

Introduction

Here is the source code for org.xlrnet.tibaija.tools.fontgen.FontgenApplication.java

Source

/*
 * Copyright (c) 2015 Jakob Hende
 *
 * 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 org.xlrnet.tibaija.tools.fontgen;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xlrnet.tibaija.graphics.PixelState;

import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * Application class for generating the Tibaija font configuration from the font gifs on TIBasicDev.
 * <p>
 * HowTo:
 * <p>
 * <ul> <li>Download the small gif files displayed in the table on the top from {@see
 * http://tibasicdev.wikidot.com/83lgfont} and {@see http://tibasicdev.wikidot.com/83smfont} to a directory of your
 * choice. Do NOT rename any files!</li> <li> Run this application with the directory to which you downloaded the files
 * as first parameter and with the target directory for the created font files as the second parameter. </li> <li>After
 * the .json files have been generated, set all "text"-fields accordingly.</li> </ul>
 */
public class FontgenApplication {

    private static final Logger LOGGER = LoggerFactory.getLogger(FontgenApplication.class);

    private static final String LARGE_FONT_IDENTIFIER = "L";

    private static final String SMALL_FONT_IDENTIFIER = "S";

    private static final ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);

    public static void main(String[] args) throws IOException {
        new FontgenApplication().run(args);
    }

    private Symbol importFile(Path path, Font font, String fontIdentifier) throws IOException, ImageReadException {
        LOGGER.info("Importing file {} ...", path.toAbsolutePath());

        BufferedImage image = Imaging.getBufferedImage(Files.newInputStream(path));
        int width = image.getWidth();
        int height = image.getHeight();
        int finalWidth = width / 2;
        int finalHeight = height / 2;

        if (width % 2 != 0 || height % 2 != 0) {
            LOGGER.warn("Width and height must be multiple of 2");
            return null;
        }

        Symbol symbol = new Symbol();
        PixelState[][] pixelStates = new PixelState[finalHeight][finalWidth];
        Raster imageData = image.getData();

        for (int y = 0; y < finalHeight; y++) {
            for (int x = 0; x < finalWidth; x++) {
                int sample = imageData.getSample(x * 2, y * 2, 0);
                PixelState pixelState = sample == 0 ? PixelState.ON : PixelState.OFF;
                pixelStates[y][x] = pixelState;
            }
        }

        symbol.setData(pixelStates);
        return symbol;
    }

    @NotNull
    private Font importFont(String source, String fontIdentifier) throws IOException {
        Path sourcePath = Paths.get(source);

        Pattern filePattern = Pattern.compile("[0-9A-F]{2}h_" + fontIdentifier + "[a-zA-Z0-9]*.gif");

        List<Path> fileList = Files.list(sourcePath)
                .filter(p -> filePattern.matcher(p.getFileName().toString()).matches())
                .collect(Collectors.toList());

        Font font = new Font();
        List<Symbol> symbols = new ArrayList<>();

        for (Path path : fileList) {
            try {
                Symbol symbol = importFile(path, font, fontIdentifier);

                if (symbol == null)
                    continue;

                String filename = path.getFileName().toString();
                String hexValue = StringUtils.substring(filename, 0, 2);
                String internalIdentifier = StringUtils.substringBetween(filename, "_" + fontIdentifier, ".gif");

                symbol.setHexValue(hexValue);
                symbol.setInternalIdentifier(internalIdentifier);

                symbols.add(symbol);
            } catch (ImageReadException e) {
                LOGGER.error("Reading image {} failed", path.toAbsolutePath(), e);
            }
        }

        Collections.sort(symbols);
        font.setSymbols(symbols);

        return font;
    }

    private void run(String[] args) throws IOException {
        checkArgument(args.length == 2, "Wrong argument count");

        String source = args[0];
        String target = args[1];

        LOGGER.info("Source directory: {}", source);
        LOGGER.info("Target directory: {}", target);

        Font largeFont = importFont(source, LARGE_FONT_IDENTIFIER);
        largeFont.setFontName("TI-83+ large");
        Font smallFont = importFont(source, SMALL_FONT_IDENTIFIER);
        smallFont.setFontName("TI-83+ small");

        Path largePath = Paths.get(target, "largeFont.json");
        Path smallPath = Paths.get(target, "smallFont.json");

        OutputStream largeOutputStream = Files.newOutputStream(largePath);
        OutputStream smallOutputStream = Files.newOutputStream(smallPath);

        objectMapper.writer().writeValue(largeOutputStream, largeFont);
        objectMapper.writer().writeValue(smallOutputStream, smallFont);

        LOGGER.info("Imported {} elements.", largeFont.getSymbols().size() + smallFont.getSymbols().size());
    }

}